using System;
|
using System.Text;
|
using HH.WMS.Utils.NPOI.Util;
|
using HH.WMS.Utils.NPOI.SS.Formula;
|
using HH.WMS.Utils.NPOI.SS.Formula.PTG;
|
using System.Globalization;
|
|
namespace HH.WMS.Utils.NPOI.HSSF.Record
|
{
|
public class LbsDataSubRecord : SubRecord
|
{
|
|
public const int sid = 0x0013;
|
/**
|
* From [MS-XLS].pdf 2.5.147 FtLbsData:
|
*
|
* An unsigned integer that indirectly specifies whether
|
* some of the data in this structure appear in a subsequent Continue record.
|
* If _cbFContinued is 0x00, all of the fields in this structure except sid and _cbFContinued
|
* MUST NOT exist. If this entire structure is Contained within the same record,
|
* then _cbFContinued MUST be greater than or equal to the size, in bytes,
|
* of this structure, not including the four bytes for the ft and _cbFContinued fields
|
*/
|
private int _cbFContinued;
|
|
/**
|
* a formula that specifies the range of cell values that are the items in this list.
|
*/
|
private int _unknownPreFormulaInt;
|
private Ptg _linkPtg;
|
private Byte? _unknownPostFormulaByte;
|
|
/**
|
* An unsigned integer that specifies the number of items in the list.
|
*/
|
private int _cLines;
|
|
/**
|
* An unsigned integer that specifies the one-based index of the first selected item in this list.
|
* A value of 0x00 specifies there is no currently selected item.
|
*/
|
private int _iSel;
|
|
/**
|
* flags that tell what data follows
|
*/
|
private int _flags;
|
|
/**
|
* An ObjId that specifies the edit box associated with this list.
|
* A value of 0x00 specifies that there is no edit box associated with this list.
|
*/
|
private int _idEdit;
|
|
/**
|
* An optional LbsDropData that specifies properties for this dropdown control.
|
* This field MUST exist if and only if the Containing Obj?s cmo.ot is equal to 0x14.
|
*/
|
private LbsDropData _dropData;
|
|
/**
|
* An optional array of strings where each string specifies an item in the list.
|
* The number of elements in this array, if it exists, MUST be {@link #_cLines}
|
*/
|
private String[] _rgLines;
|
|
/**
|
* An optional array of bools that specifies
|
* which items in the list are part of a multiple selection
|
*/
|
private bool[] _bsels;
|
|
LbsDataSubRecord()
|
{
|
|
}
|
/**
|
* @param in the stream to read data from
|
* @param cbFContinued the seconf short in the record header
|
* @param cmoOt the Containing Obj's {@link CommonObjectDataSubRecord#field_1_objectType}
|
*/
|
public LbsDataSubRecord(ILittleEndianInput in1, int cbFContinued, int cmoOt)
|
{
|
_cbFContinued = cbFContinued;
|
|
int encodedTokenLen = in1.ReadUShort();
|
if (encodedTokenLen > 0)
|
{
|
int formulaSize = in1.ReadUShort();
|
_unknownPreFormulaInt = in1.ReadInt();
|
|
Ptg[] ptgs = Ptg.ReadTokens(formulaSize, in1);
|
if (ptgs.Length != 1)
|
{
|
throw new RecordFormatException("Read " + ptgs.Length
|
+ " tokens but expected exactly 1");
|
}
|
_linkPtg = ptgs[0];
|
switch (encodedTokenLen - formulaSize - 6)
|
{
|
case 1:
|
_unknownPostFormulaByte = (byte)in1.ReadByte();
|
break;
|
case 0:
|
_unknownPostFormulaByte = null;
|
break;
|
default:
|
throw new RecordFormatException("Unexpected leftover bytes");
|
}
|
}
|
|
_cLines = in1.ReadUShort();
|
_iSel = in1.ReadUShort();
|
_flags = in1.ReadUShort();
|
_idEdit = in1.ReadUShort();
|
|
// From [MS-XLS].pdf 2.5.147 FtLbsData:
|
// This field MUST exist if and only if the Containing Obj?s cmo.ot is equal to 0x14.
|
if (cmoOt == 0x14)
|
{
|
_dropData = new LbsDropData(in1);
|
}
|
|
// From [MS-XLS].pdf 2.5.147 FtLbsData:
|
// This array MUST exist if and only if the fValidPlex flag (0x2) is set
|
if ((_flags & 0x2) != 0)
|
{
|
_rgLines = new String[_cLines];
|
for (int i = 0; i < _cLines; i++)
|
{
|
_rgLines[i] = StringUtil.ReadUnicodeString(in1);
|
}
|
}
|
|
// bits 5-6 in the _flags specify the type
|
// of selection behavior this list control is expected to support
|
|
// From [MS-XLS].pdf 2.5.147 FtLbsData:
|
// This array MUST exist if and only if the wListType field is not equal to 0.
|
if (((_flags >> 4) & 0x2) != 0)
|
{
|
_bsels = new bool[_cLines];
|
for (int i = 0; i < _cLines; i++)
|
{
|
_bsels[i] = in1.ReadByte() == 1;
|
}
|
}
|
|
}
|
public override bool IsTerminating
|
{
|
get
|
{
|
return true;
|
}
|
}
|
/**
|
*
|
* @return the formula that specifies the range of cell values that are the items in this list.
|
*/
|
public Ptg Formula
|
{
|
get
|
{
|
return _linkPtg;
|
}
|
}
|
|
/**
|
* @return the number of items in the list
|
*/
|
public int NumberOfItems
|
{
|
get
|
{
|
return _cLines;
|
}
|
}
|
public override short Sid
|
{
|
get { return sid; }
|
}
|
public override int DataSize
|
{
|
get
|
{
|
int result = 2; // 2 Initial shorts
|
|
// optional link formula
|
if (_linkPtg != null)
|
{
|
result += 2; // encoded Ptg size
|
result += 4; // unknown int
|
result += _linkPtg.Size;
|
if (_unknownPostFormulaByte != null)
|
{
|
result += 1;
|
}
|
}
|
|
result += 4 * 2; // 4 shorts
|
if (_dropData != null)
|
{
|
result += _dropData.DataSize;
|
}
|
if (_rgLines != null)
|
{
|
foreach (String str in _rgLines)
|
{
|
result += StringUtil.GetEncodedSize(str);
|
}
|
}
|
if (_bsels != null)
|
{
|
result += _bsels.Length;
|
}
|
return result;
|
}
|
}
|
public override void Serialize(ILittleEndianOutput out1)
|
{
|
out1.WriteShort(sid);
|
out1.WriteShort(_cbFContinued); // note - this is *not* the size
|
if (_linkPtg == null)
|
{
|
out1.WriteShort(0);
|
}
|
else
|
{
|
int formulaSize = _linkPtg.Size;
|
int linkSize = formulaSize + 6;
|
if (_unknownPostFormulaByte != null)
|
{
|
linkSize++;
|
}
|
out1.WriteShort(linkSize);
|
out1.WriteShort(formulaSize);
|
out1.WriteInt(_unknownPreFormulaInt);
|
_linkPtg.Write(out1);
|
if (_unknownPostFormulaByte != null)
|
{
|
out1.WriteByte(Convert.ToByte(_unknownPostFormulaByte, CultureInfo.InvariantCulture));
|
}
|
}
|
out1.WriteShort(_cLines);
|
out1.WriteShort(_iSel);
|
out1.WriteShort(_flags);
|
out1.WriteShort(_idEdit);
|
|
if (_dropData != null)
|
{
|
_dropData.Serialize(out1);
|
}
|
|
if (_rgLines != null)
|
{
|
foreach (String str in _rgLines)
|
{
|
StringUtil.WriteUnicodeString(out1, str);
|
}
|
}
|
|
if (_bsels != null)
|
{
|
foreach (bool val in _bsels)
|
{
|
out1.WriteByte(val ? 1 : 0);
|
}
|
}
|
}
|
private static Ptg ReadRefPtg(byte[] formulaRawBytes)
|
{
|
ILittleEndianInput in1 = new LittleEndianByteArrayInputStream(formulaRawBytes);
|
byte ptgSid = (byte)in1.ReadByte();
|
switch (ptgSid)
|
{
|
case AreaPtg.sid: return new AreaPtg(in1);
|
case Area3DPtg.sid: return new Area3DPtg(in1);
|
case RefPtg.sid: return new RefPtg(in1);
|
case Ref3DPtg.sid: return new Ref3DPtg(in1);
|
}
|
return null;
|
}
|
public override Object Clone()
|
{
|
return this;
|
}
|
public override String ToString()
|
{
|
StringBuilder sb = new StringBuilder(256);
|
|
sb.Append("[ftLbsData]\n");
|
sb.Append(" .unknownshort1 =").Append(HexDump.ShortToHex(_cbFContinued)).Append("\n");
|
sb.Append(" .formula = ").Append('\n');
|
sb.Append(_linkPtg.ToString()).Append(_linkPtg.RVAType).Append('\n');
|
sb.Append(" .nEntryCount =").Append(HexDump.ShortToHex(_cLines)).Append("\n");
|
sb.Append(" .selEntryIx =").Append(HexDump.ShortToHex(_iSel)).Append("\n");
|
sb.Append(" .style =").Append(HexDump.ShortToHex(_flags)).Append("\n");
|
sb.Append(" .unknownshort10=").Append(HexDump.ShortToHex(_idEdit)).Append("\n");
|
if (_dropData != null) sb.Append('\n').Append(_dropData.ToString());
|
sb.Append("[/ftLbsData]\n");
|
return sb.ToString();
|
}
|
|
/**
|
*
|
* @return a new instance of LbsDataSubRecord to construct auto-filters
|
* @see org.apache.poi.hssf.model.ComboboxShape#createObjRecord(org.apache.poi.hssf.usermodel.HSSFSimpleShape, int)
|
*/
|
public static LbsDataSubRecord CreateAutoFilterInstance()
|
{
|
LbsDataSubRecord lbs = new LbsDataSubRecord();
|
lbs._cbFContinued = 0x1FEE; //autofilters seem to alway have this magic number
|
lbs._iSel = 0x000;
|
|
lbs._flags = 0x0301;
|
lbs._dropData = new LbsDropData();
|
lbs._dropData._wStyle = LbsDropData.STYLE_COMBO_SIMPLE_DROPDOWN;
|
|
// the number of lines to be displayed in the dropdown
|
lbs._dropData._cLine = 8;
|
return lbs;
|
}
|
}
|
|
/**
|
* This structure specifies properties of the dropdown list control
|
*/
|
public class LbsDropData {
|
|
/**
|
* Combo dropdown control
|
*/
|
public const int STYLE_COMBO_DROPDOWN = 0;
|
/**
|
* Combo Edit dropdown control
|
*/
|
public const int STYLE_COMBO_EDIT_DROPDOWN = 1;
|
/**
|
* Simple dropdown control (just the dropdown button)
|
*/
|
public const int STYLE_COMBO_SIMPLE_DROPDOWN = 2;
|
/**
|
* An unsigned integer that specifies the style of this dropdown.
|
*/
|
internal int _wStyle;
|
|
/**
|
* An unsigned integer that specifies the number of lines to be displayed in the dropdown.
|
*/
|
internal int _cLine;
|
|
/**
|
* An unsigned integer that specifies the smallest width in pixels allowed for the dropdown window
|
*/
|
private int _dxMin;
|
|
/**
|
* a string that specifies the current string value in the dropdown
|
*/
|
private String _str;
|
|
/**
|
* Optional, undefined and MUST be ignored.
|
* This field MUST exist if and only if the size of str in bytes is an odd number
|
*/
|
private Byte _unused;
|
|
public LbsDropData()
|
{
|
_str = "";
|
_unused = 0;
|
}
|
|
public LbsDropData(ILittleEndianInput in1){
|
_wStyle = in1.ReadUShort();
|
_cLine = in1.ReadUShort();
|
_dxMin = in1.ReadUShort();
|
_str = StringUtil.ReadUnicodeString(in1);
|
if(StringUtil.GetEncodedSize(_str) % 2 != 0){
|
_unused = (byte)in1.ReadByte();
|
}
|
}
|
|
public void Serialize(ILittleEndianOutput out1) {
|
out1.WriteShort(_wStyle);
|
out1.WriteShort(_cLine);
|
out1.WriteShort(_dxMin);
|
StringUtil.WriteUnicodeString(out1, _str);
|
out1.WriteByte(_unused);
|
}
|
|
public int DataSize
|
{
|
get
|
{
|
int size = 6;
|
size += StringUtil.GetEncodedSize(_str);
|
size += _unused;
|
return size;
|
}
|
}
|
|
public override String ToString(){
|
StringBuilder sb = new StringBuilder();
|
sb.Append("[LbsDropData]\n");
|
sb.Append(" ._wStyle: ").Append(_wStyle).Append('\n');
|
sb.Append(" ._cLine: ").Append(_cLine).Append('\n');
|
sb.Append(" ._dxMin: ").Append(_dxMin).Append('\n');
|
sb.Append(" ._str: ").Append(_str).Append('\n');
|
sb.Append(" ._unused: ").Append(_unused).Append('\n');
|
sb.Append("[/LbsDropData]\n");
|
|
return sb.ToString();
|
}
|
}
|
}
|