* @author Josh Micich
*/
public abstract class CellRecord extends StandardRecord implements CellValueRecordInterface {
- private int _rowIndex;
- private int _columnIndex;
- private int _formatIndex;
-
- protected CellRecord() {
- // fields uninitialised
- }
-
- protected CellRecord(RecordInputStream in) {
- _rowIndex = in.readUShort();
- _columnIndex = in.readUShort();
- _formatIndex = in.readUShort();
- }
-
- public final void setRow(int row) {
- _rowIndex = row;
- }
-
- public final void setColumn(short col) {
- _columnIndex = col;
- }
-
- /**
- * set the index to the ExtendedFormat
- *
- * @see org.apache.poi.hssf.record.ExtendedFormatRecord
- * @param xf index to the XF record
- */
- public final void setXFIndex(short xf) {
- _formatIndex = xf;
- }
-
- public final int getRow() {
- return _rowIndex;
- }
-
- public final short getColumn() {
- return (short) _columnIndex;
- }
-
- /**
- * get the index to the ExtendedFormat
- *
- * @see org.apache.poi.hssf.record.ExtendedFormatRecord
- * @return index to the XF record
- */
- public final short getXFIndex() {
- return (short) _formatIndex;
- }
-
- public final String toString() {
- StringBuilder sb = new StringBuilder();
- String recordName = getRecordName();
-
- sb.append("[").append(recordName).append("]\n");
- sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
- sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
- sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
- appendValueText(sb);
- sb.append("\n");
- sb.append("[/").append(recordName).append("]\n");
- return sb.toString();
- }
-
- /**
- * Append specific debug info (used by {@link #toString()} for the value
- * contained in this record. Trailing new-line should not be appended
- * (superclass does that).
- */
- protected abstract void appendValueText(StringBuilder sb);
-
- /**
- * Gets the debug info BIFF record type name (used by {@link #toString()}.
- */
- protected abstract String getRecordName();
-
- /**
- * writes out the value data for this cell record
- */
- protected abstract void serializeValue(LittleEndianOutput out);
-
- /**
- * @return the size (in bytes) of the value data for this cell record
- */
- protected abstract int getValueDataSize();
-
- public final void serialize(LittleEndianOutput out) {
- out.writeShort(getRow());
- out.writeShort(getColumn());
- out.writeShort(getXFIndex());
- serializeValue(out);
- }
-
- protected final int getDataSize() {
- return 6 + getValueDataSize();
- }
-
- protected final void copyBaseFields(CellRecord rec) {
- rec._rowIndex = _rowIndex;
- rec._columnIndex = _columnIndex;
- rec._formatIndex = _formatIndex;
- }
+ private int _rowIndex;
+ private int _columnIndex;
+ private int _formatIndex;
+
+ protected CellRecord() {
+ // fields uninitialised
+ }
+
+ protected CellRecord(RecordInputStream in) {
+ _rowIndex = in.readUShort();
+ _columnIndex = in.readUShort();
+ _formatIndex = in.readUShort();
+ }
+
+ public final void setRow(int row) {
+ _rowIndex = row;
+ }
+
+ public final void setColumn(short col) {
+ _columnIndex = col;
+ }
+
+ /**
+ * set the index to the ExtendedFormat
+ *
+ * @see org.apache.poi.hssf.record.ExtendedFormatRecord
+ * @param xf index to the XF record
+ */
+ public final void setXFIndex(short xf) {
+ _formatIndex = xf;
+ }
+
+ public final int getRow() {
+ return _rowIndex;
+ }
+
+ public final short getColumn() {
+ return (short) _columnIndex;
+ }
+
+ /**
+ * get the index to the ExtendedFormat
+ *
+ * @see org.apache.poi.hssf.record.ExtendedFormatRecord
+ * @return index to the XF record
+ */
+ public final short getXFIndex() {
+ return (short) _formatIndex;
+ }
+
+ @Override
+ public final String toString() {
+ StringBuilder sb = new StringBuilder();
+ String recordName = getRecordName();
+
+ sb.append("[").append(recordName).append("]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ appendValueText(sb);
+ sb.append("\n");
+ sb.append("[/").append(recordName).append("]\n");
+ return sb.toString();
+ }
+
+ /**
+ * Append specific debug info (used by {@link #toString()} for the value
+ * contained in this record. Trailing new-line should not be appended
+ * (superclass does that).
+ */
+ protected abstract void appendValueText(StringBuilder sb);
+
+ /**
+ * Gets the debug info BIFF record type name (used by {@link #toString()}.
+ */
+ protected abstract String getRecordName();
+
+ /**
+ * writes out the value data for this cell record
+ */
+ protected abstract void serializeValue(LittleEndianOutput out);
+
+ /**
+ * @return the size (in bytes) of the value data for this cell record
+ */
+ protected abstract int getValueDataSize();
+
+ @Override
+ public final void serialize(LittleEndianOutput out) {
+ out.writeShort(getRow());
+ out.writeShort(getColumn());
+ out.writeShort(getXFIndex());
+ serializeValue(out);
+ }
+
+ @Override
+ protected final int getDataSize() {
+ return 6 + getValueDataSize();
+ }
+
+ protected final void copyBaseFields(CellRecord rec) {
+ rec._rowIndex = _rowIndex;
+ rec._columnIndex = _columnIndex;
+ rec._formatIndex = _formatIndex;
+ }
}
}
+ @Override
protected int getDataSize(){
int result = 2 + 4; // short and int
result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short
return result;
}
+ @Override
public void serialize(LittleEndianOutput out) {
out.writeShort(field_1_option_flag);
out.writeShort(field_2_ixals);
}
}
+ @Override
public short getSid() {
return sid;
}
+ @Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[EXTERNALNAME]\n");
return 8;
}
+ @Override
public short getSid() {
return sid;
}
+ @Override
public Object clone() {
NumberRecord rec = new NumberRecord();
copyBaseFields(rec);
*/
public abstract class Record extends RecordBase {
- protected Record() {
- // no fields to initialise
- }
+ protected Record() {
+ // no fields to initialise
+ }
- /**
- * called by the class that is responsible for writing this sucker.
- * Subclasses should implement this so that their data is passed back in a
- * byte array.
- *
- * @return byte array containing instance data
- */
- public final byte[] serialize() {
- byte[] retval = new byte[ getRecordSize() ];
+ /**
+ * called by the class that is responsible for writing this sucker.
+ * Subclasses should implement this so that their data is passed back in a
+ * byte array.
+ *
+ * @return byte array containing instance data
+ */
+ public final byte[] serialize() {
+ byte[] retval = new byte[ getRecordSize() ];
- serialize(0, retval);
- return retval;
- }
+ serialize(0, retval);
+ return retval;
+ }
- /**
- * get a string representation of the record (for biffview/debugging)
- */
- public String toString() {
- return super.toString();
- }
+ /**
+ * get a string representation of the record (for biffview/debugging)
+ */
+ @Override
+ public String toString() {
+ return super.toString();
+ }
- /**
- * return the non static version of the id for this record.
- */
+ /**
+ * return the non static version of the id for this record.
+ */
- public abstract short getSid();
+ public abstract short getSid();
- public Object clone() {
- if (false) {
- // TODO - implement clone in a more standardised way
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e);
- }
- }
- throw new RuntimeException("The class "+getClass().getName()+" needs to define a clone method");
- }
+ @Override
+ public Object clone() {
+ if (false) {
+ // TODO - implement clone in a more standardised way
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ throw new RuntimeException("The class "+getClass().getName()+" needs to define a clone method");
+ }
- /**
- * Clone the current record, via a call to serialize
- * it, and another to create a new record from the
- * bytes.
- * May only be used for classes which don't have
- * internal counts / ids in them. For those which
- * do, a full model-aware cloning is needed, which
- * allocates new ids / counts as needed.
- */
- public Record cloneViaReserialise() {
- // Do it via a re-serialization
- // It's a cheat, but it works...
- byte[] b = serialize();
- RecordInputStream rinp = new RecordInputStream(new ByteArrayInputStream(b));
- rinp.nextRecord();
+ /**
+ * Clone the current record, via a call to serialize
+ * it, and another to create a new record from the
+ * bytes.
+ * May only be used for classes which don't have
+ * internal counts / ids in them. For those which
+ * do, a full model-aware cloning is needed, which
+ * allocates new ids / counts as needed.
+ */
+ public Record cloneViaReserialise() {
+ // Do it via a re-serialization
+ // It's a cheat, but it works...
+ byte[] b = serialize();
+ RecordInputStream rinp = new RecordInputStream(new ByteArrayInputStream(b));
+ rinp.nextRecord();
- Record[] r = RecordFactory.createRecord(rinp);
- if(r.length != 1) {
- throw new IllegalStateException("Re-serialised a record to clone it, but got " + r.length + " records back!");
- }
- return r[0];
- }
+ Record[] r = RecordFactory.createRecord(rinp);
+ if(r.length != 1) {
+ throw new IllegalStateException("Re-serialised a record to clone it, but got " + r.length + " records back!");
+ }
+ return r[0];
+ }
}
*/
public final class UnknownRecord extends StandardRecord {
- /*
- * Some Record IDs used by POI as 'milestones' in the record stream
- */
- /**
- * seems to be part of the {@link PageSettingsBlock}. Not interpreted by POI.
- * The name 'PRINTSIZE' was taken from OOO source.<br/>
- * The few POI test samples with this record have data { 0x03, 0x00 }.
- */
- public static final int PRINTSIZE_0033 = 0x0033;
- /**
- * Environment-Specific Print Record
- */
- public static final int PLS_004D = 0x004D;
- public static final int SHEETPR_0081 = 0x0081;
- public static final int SORT_0090 = 0x0090;
- public static final int STANDARDWIDTH_0099 = 0x0099;
- public static final int SCL_00A0 = 0x00A0;
- public static final int BITMAP_00E9 = 0x00E9;
- public static final int PHONETICPR_00EF = 0x00EF;
- public static final int LABELRANGES_015F = 0x015F;
- public static final int QUICKTIP_0800 = 0x0800;
- public static final int SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT
- public static final int SHEETPROTECTION_0867 = 0x0867;
- public static final int HEADER_FOOTER_089C = 0x089C;
- public static final int CODENAME_1BA = 0x01BA;
- public static final int PLV_MAC = 0x08C8;
+ /*
+ * Some Record IDs used by POI as 'milestones' in the record stream
+ */
+ /**
+ * seems to be part of the {@link PageSettingsBlock}. Not interpreted by POI.
+ * The name 'PRINTSIZE' was taken from OOO source.<br/>
+ * The few POI test samples with this record have data { 0x03, 0x00 }.
+ */
+ public static final int PRINTSIZE_0033 = 0x0033;
+ /**
+ * Environment-Specific Print Record
+ */
+ public static final int PLS_004D = 0x004D;
+ public static final int SHEETPR_0081 = 0x0081;
+ public static final int SORT_0090 = 0x0090;
+ public static final int STANDARDWIDTH_0099 = 0x0099;
+ public static final int SCL_00A0 = 0x00A0;
+ public static final int BITMAP_00E9 = 0x00E9;
+ public static final int PHONETICPR_00EF = 0x00EF;
+ public static final int LABELRANGES_015F = 0x015F;
+ public static final int QUICKTIP_0800 = 0x0800;
+ public static final int SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT
+ public static final int SHEETPROTECTION_0867 = 0x0867;
+ public static final int HEADER_FOOTER_089C = 0x089C;
+ public static final int CODENAME_1BA = 0x01BA;
+ public static final int PLV_MAC = 0x08C8;
- private int _sid;
- private byte[] _rawData;
+ private int _sid;
+ private byte[] _rawData;
- /**
- * @param id id of the record -not validated, just stored for serialization
- * @param data the data
- */
- public UnknownRecord(int id, byte[] data) {
- _sid = id & 0xFFFF;
- _rawData = data;
- }
+ /**
+ * @param id id of the record -not validated, just stored for serialization
+ * @param data the data
+ */
+ public UnknownRecord(int id, byte[] data) {
+ _sid = id & 0xFFFF;
+ _rawData = data;
+ }
- /**
- * construct an unknown record. No fields are interpreted and the record will
- * be serialized in its original form more or less
- * @param in the RecordInputstream to read the record from
- */
- public UnknownRecord(RecordInputStream in) {
- _sid = in.getSid();
- _rawData = in.readRemainder();
- if (false && getBiffName(_sid) == null) {
- // unknown sids in the range 0x0004-0x0013 are probably 'sub-records' of ObjectRecord
- // those sids are in a different number space.
- // TODO - put unknown OBJ sub-records in a different class
- System.out.println("Unknown record 0x" + Integer.toHexString(_sid).toUpperCase());
- }
- }
+ /**
+ * construct an unknown record. No fields are interpreted and the record will
+ * be serialized in its original form more or less
+ * @param in the RecordInputstream to read the record from
+ */
+ public UnknownRecord(RecordInputStream in) {
+ _sid = in.getSid();
+ _rawData = in.readRemainder();
+ if (false && getBiffName(_sid) == null) {
+ // unknown sids in the range 0x0004-0x0013 are probably 'sub-records' of ObjectRecord
+ // those sids are in a different number space.
+ // TODO - put unknown OBJ sub-records in a different class
+ System.out.println("Unknown record 0x" + Integer.toHexString(_sid).toUpperCase());
+ }
+ }
- /**
- * spit the record out AS IS. no interpretation or identification
- */
- public void serialize(LittleEndianOutput out) {
- out.write(_rawData);
- }
+ /**
+ * spit the record out AS IS. no interpretation or identification
+ */
+ @Override
+ public void serialize(LittleEndianOutput out) {
+ out.write(_rawData);
+ }
- protected int getDataSize() {
- return _rawData.length;
- }
+ @Override
+ protected int getDataSize() {
+ return _rawData.length;
+ }
- /**
- * print a sort of string representation ([UNKNOWN RECORD] id = x [/UNKNOWN RECORD])
- */
- public String toString() {
- String biffName = getBiffName(_sid);
- if (biffName == null) {
- biffName = "UNKNOWNRECORD";
- }
- StringBuffer sb = new StringBuffer();
+ /**
+ * print a sort of string representation ([UNKNOWN RECORD] id = x [/UNKNOWN RECORD])
+ */
+ @Override
+ public String toString() {
+ String biffName = getBiffName(_sid);
+ if (biffName == null) {
+ biffName = "UNKNOWNRECORD";
+ }
+ StringBuffer sb = new StringBuffer();
- sb.append("[").append(biffName).append("] (0x");
- sb.append(Integer.toHexString(_sid).toUpperCase() + ")\n");
- if (_rawData.length > 0) {
- sb.append(" rawData=").append(HexDump.toHex(_rawData)).append("\n");
- }
- sb.append("[/").append(biffName).append("]\n");
- return sb.toString();
- }
+ sb.append("[").append(biffName).append("] (0x");
+ sb.append(Integer.toHexString(_sid).toUpperCase() + ")\n");
+ if (_rawData.length > 0) {
+ sb.append(" rawData=").append(HexDump.toHex(_rawData)).append("\n");
+ }
+ sb.append("[/").append(biffName).append("]\n");
+ return sb.toString();
+ }
- public short getSid() {
- return (short) _sid;
- }
+ @Override
+ public short getSid() {
+ return (short) _sid;
+ }
- /**
- * These BIFF record types are known but still uninterpreted by POI
- *
- * @return the documented name of this BIFF record type, <code>null</code> if unknown to POI
- */
- public static String getBiffName(int sid) {
- // Note to POI developers:
- // Make sure you delete the corresponding entry from
- // this method any time a new Record subclass is created.
- switch (sid) {
- case PRINTSIZE_0033: return "PRINTSIZE";
- case PLS_004D: return "PLS";
- case 0x0050: return "DCON"; // Data Consolidation Information
- case 0x007F: return "IMDATA";
- case SHEETPR_0081: return "SHEETPR";
- case SORT_0090: return "SORT"; // Sorting Options
- case 0x0094: return "LHRECORD"; // .WK? File Conversion Information
- case STANDARDWIDTH_0099: return "STANDARDWIDTH"; //Standard Column Width
- case SCL_00A0: return "SCL"; // Window Zoom Magnification
- case 0x00AE: return "SCENMAN"; // Scenario Output Data
+ /**
+ * These BIFF record types are known but still uninterpreted by POI
+ *
+ * @return the documented name of this BIFF record type, <code>null</code> if unknown to POI
+ */
+ public static String getBiffName(int sid) {
+ // Note to POI developers:
+ // Make sure you delete the corresponding entry from
+ // this method any time a new Record subclass is created.
+ switch (sid) {
+ case PRINTSIZE_0033: return "PRINTSIZE";
+ case PLS_004D: return "PLS";
+ case 0x0050: return "DCON"; // Data Consolidation Information
+ case 0x007F: return "IMDATA";
+ case SHEETPR_0081: return "SHEETPR";
+ case SORT_0090: return "SORT"; // Sorting Options
+ case 0x0094: return "LHRECORD"; // .WK? File Conversion Information
+ case STANDARDWIDTH_0099: return "STANDARDWIDTH"; //Standard Column Width
+ case SCL_00A0: return "SCL"; // Window Zoom Magnification
+ case 0x00AE: return "SCENMAN"; // Scenario Output Data
- case 0x00B2: return "SXVI"; // (pivot table) View Item
- case 0x00B4: return "SXIVD"; // (pivot table) Row/Column Field IDs
- case 0x00B5: return "SXLI"; // (pivot table) Line Item Array
+ case 0x00B2: return "SXVI"; // (pivot table) View Item
+ case 0x00B4: return "SXIVD"; // (pivot table) Row/Column Field IDs
+ case 0x00B5: return "SXLI"; // (pivot table) Line Item Array
- case 0x00D3: return "OBPROJ";
- case 0x00DC: return "PARAMQRY";
- case 0x00DE: return "OLESIZE";
- case BITMAP_00E9: return "BITMAP";
- case PHONETICPR_00EF: return "PHONETICPR";
- case 0x00F1: return "SXEX"; // PivotTable View Extended Information
+ case 0x00D3: return "OBPROJ";
+ case 0x00DC: return "PARAMQRY";
+ case 0x00DE: return "OLESIZE";
+ case BITMAP_00E9: return "BITMAP";
+ case PHONETICPR_00EF: return "PHONETICPR";
+ case 0x00F1: return "SXEX"; // PivotTable View Extended Information
- case LABELRANGES_015F: return "LABELRANGES";
- case 0x01BA: return "CODENAME";
- case 0x01A9: return "USERBVIEW";
- case 0x01AD: return "QSI";
+ case LABELRANGES_015F: return "LABELRANGES";
+ case 0x01BA: return "CODENAME";
+ case 0x01A9: return "USERBVIEW";
+ case 0x01AD: return "QSI";
- case 0x01C0: return "EXCEL9FILE";
+ case 0x01C0: return "EXCEL9FILE";
- case 0x0802: return "QSISXTAG"; // Pivot Table and Query Table Extensions
- case 0x0803: return "DBQUERYEXT";
- case 0x0805: return "TXTQUERY";
- case 0x0810: return "SXVIEWEX9"; // Pivot Table Extensions
+ case 0x0802: return "QSISXTAG"; // Pivot Table and Query Table Extensions
+ case 0x0803: return "DBQUERYEXT";
+ case 0x0805: return "TXTQUERY";
+ case 0x0810: return "SXVIEWEX9"; // Pivot Table Extensions
- case 0x0812: return "CONTINUEFRT";
- case QUICKTIP_0800: return "QUICKTIP";
- case SHEETEXT_0862: return "SHEETEXT";
- case 0x0863: return "BOOKEXT";
- case 0x0864: return "SXADDL"; // Pivot Table Additional Info
- case SHEETPROTECTION_0867: return "SHEETPROTECTION";
- case 0x086B: return "DATALABEXTCONTENTS";
- case 0x086C: return "CELLWATCH";
- case 0x0874: return "DROPDOWNOBJIDS";
- case 0x0876: return "DCONN";
- case 0x087B: return "CFEX";
- case 0x087C: return "XFCRC";
- case 0x087D: return "XFEXT";
- case 0x087F: return "CONTINUEFRT12";
- case 0x088B: return "PLV";
- case 0x088C: return "COMPAT12";
- case 0x088D: return "DXF";
- case 0x0892: return "STYLEEXT";
- case 0x0896: return "THEME";
- case 0x0897: return "GUIDTYPELIB";
- case 0x089A: return "MTRSETTINGS";
- case 0x089B: return "COMPRESSPICTURES";
- case HEADER_FOOTER_089C: return "HEADERFOOTER";
- case 0x08A1: return "SHAPEPROPSSTREAM";
- case 0x08A3: return "FORCEFULLCALCULATION";
- case 0x08A4: return "SHAPEPROPSSTREAM";
- case 0x08A5: return "TEXTPROPSSTREAM";
- case 0x08A6: return "RICHTEXTSTREAM";
+ case 0x0812: return "CONTINUEFRT";
+ case QUICKTIP_0800: return "QUICKTIP";
+ case SHEETEXT_0862: return "SHEETEXT";
+ case 0x0863: return "BOOKEXT";
+ case 0x0864: return "SXADDL"; // Pivot Table Additional Info
+ case SHEETPROTECTION_0867: return "SHEETPROTECTION";
+ case 0x086B: return "DATALABEXTCONTENTS";
+ case 0x086C: return "CELLWATCH";
+ case 0x0874: return "DROPDOWNOBJIDS";
+ case 0x0876: return "DCONN";
+ case 0x087B: return "CFEX";
+ case 0x087C: return "XFCRC";
+ case 0x087D: return "XFEXT";
+ case 0x087F: return "CONTINUEFRT12";
+ case 0x088B: return "PLV";
+ case 0x088C: return "COMPAT12";
+ case 0x088D: return "DXF";
+ case 0x0892: return "STYLEEXT";
+ case 0x0896: return "THEME";
+ case 0x0897: return "GUIDTYPELIB";
+ case 0x089A: return "MTRSETTINGS";
+ case 0x089B: return "COMPRESSPICTURES";
+ case HEADER_FOOTER_089C: return "HEADERFOOTER";
+ case 0x08A1: return "SHAPEPROPSSTREAM";
+ case 0x08A3: return "FORCEFULLCALCULATION";
+ case 0x08A4: return "SHAPEPROPSSTREAM";
+ case 0x08A5: return "TEXTPROPSSTREAM";
+ case 0x08A6: return "RICHTEXTSTREAM";
- case 0x08C8: return "PLV{Mac Excel}";
+ case 0x08C8: return "PLV{Mac Excel}";
- }
- if (isObservedButUnknown(sid)) {
- return "UNKNOWN-" + Integer.toHexString(sid).toUpperCase();
- }
+ }
+ if (isObservedButUnknown(sid)) {
+ return "UNKNOWN-" + Integer.toHexString(sid).toUpperCase();
+ }
- return null;
- }
+ return null;
+ }
- /**
- * @return <code>true</code> if the unknown record id has been observed in POI unit tests
- */
- private static boolean isObservedButUnknown(int sid) {
- switch (sid) {
- case 0x0033:
- // contains 2 bytes of data: 0x0001 or 0x0003
- case 0x0034:
- // Seems to be written by MSAccess
- // contains text "[Microsoft JET Created Table]0021010"
- // appears after last cell value record and before WINDOW2
- case 0x01BD:
- case 0x01C2:
- // Written by Excel 2007
- // rawData is multiple of 12 bytes long
- // appears after last cell value record and before WINDOW2 or drawing records
- case 0x089D:
- case 0x089E:
- case 0x08A7:
+ /**
+ * @return <code>true</code> if the unknown record id has been observed in POI unit tests
+ */
+ private static boolean isObservedButUnknown(int sid) {
+ switch (sid) {
+ case 0x0033:
+ // contains 2 bytes of data: 0x0001 or 0x0003
+ case 0x0034:
+ // Seems to be written by MSAccess
+ // contains text "[Microsoft JET Created Table]0021010"
+ // appears after last cell value record and before WINDOW2
+ case 0x01BD:
+ case 0x01C2:
+ // Written by Excel 2007
+ // rawData is multiple of 12 bytes long
+ // appears after last cell value record and before WINDOW2 or drawing records
+ case 0x089D:
+ case 0x089E:
+ case 0x08A7:
- case 0x1001:
- case 0x1006:
- case 0x1007:
- case 0x1009:
- case 0x100A:
- case 0x100B:
- case 0x100C:
- case 0x1014:
- case 0x1017:
- case 0x1018:
- case 0x1019:
- case 0x101A:
- case 0x101B:
- case 0x101D:
- case 0x101E:
- case 0x101F:
- case 0x1020:
- case 0x1021:
- case 0x1022:
- case 0x1024:
- case 0x1025:
- case 0x1026:
- case 0x1027:
- case 0x1032:
- case 0x1033:
- case 0x1034:
- case 0x1035:
- case 0x103A:
- case 0x1041:
- case 0x1043:
- case 0x1044:
- case 0x1045:
- case 0x1046:
- case 0x104A:
- case 0x104B:
- case 0x104E:
- case 0x104F:
- case 0x1051:
- case 0x105C:
- case 0x105D:
- case 0x105F:
- case 0x1060:
- case 0x1062:
- case 0x1063:
- case 0x1064:
- case 0x1065:
- case 0x1066:
- return true;
- }
- return false;
- }
+ case 0x1001:
+ case 0x1006:
+ case 0x1007:
+ case 0x1009:
+ case 0x100A:
+ case 0x100B:
+ case 0x100C:
+ case 0x1014:
+ case 0x1017:
+ case 0x1018:
+ case 0x1019:
+ case 0x101A:
+ case 0x101B:
+ case 0x101D:
+ case 0x101E:
+ case 0x101F:
+ case 0x1020:
+ case 0x1021:
+ case 0x1022:
+ case 0x1024:
+ case 0x1025:
+ case 0x1026:
+ case 0x1027:
+ case 0x1032:
+ case 0x1033:
+ case 0x1034:
+ case 0x1035:
+ case 0x103A:
+ case 0x1041:
+ case 0x1043:
+ case 0x1044:
+ case 0x1045:
+ case 0x1046:
+ case 0x104A:
+ case 0x104B:
+ case 0x104E:
+ case 0x104F:
+ case 0x1051:
+ case 0x105C:
+ case 0x105D:
+ case 0x105F:
+ case 0x1060:
+ case 0x1062:
+ case 0x1063:
+ case 0x1064:
+ case 0x1065:
+ case 0x1066:
+ return true;
+ }
+ return false;
+ }
- public Object clone() {
- // immutable - OK to return this
- return this;
- }
+ @Override
+ public Object clone() {
+ // immutable - OK to return this
+ return this;
+ }
}
package org.apache.poi.poifs.dev;
-import java.io.*;
-
-import java.util.*;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
/**
* This class contains methods used to inspect POIFSViewable objects
* @return a List of Strings holding the content
*/
- public static List inspectViewable(final Object viewable,
+ public static List<String> inspectViewable(final Object viewable,
final boolean drilldown,
final int indentLevel,
final String indentString)
{
- List objects = new ArrayList();
+ List<String> objects = new ArrayList<String>();
if (viewable instanceof POIFSViewable)
{
}
else
{
- Iterator iter = inspected.getViewableIterator();
+ Iterator<Object> iter = inspected.getViewableIterator();
while (iter.hasNext())
{
* @return an Iterator; may not be null, but may have an empty
* back end store
*/
- @SuppressWarnings("unchecked")
- public Iterator getViewableIterator();
+ public Iterator<Object> getViewableIterator();
/**
* Give viewers a hint as to whether to call getViewableArray or
package org.apache.poi.poifs.dev;
-import java.io.*;
-
-import java.util.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
{
POIFSViewable fs =
new POIFSFileSystem(new FileInputStream(filename));
- List strings = POIFSViewEngine.inspectViewable(fs, true,
+ List<String> strings = POIFSViewEngine.inspectViewable(fs, true,
0, " ");
- Iterator iter = strings.iterator();
+ Iterator<String> iter = strings.iterator();
while (iter.hasNext())
{
* @return an Iterator; may not be null, but may have an empty
* back end store
*/
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Iterator getViewableIterator()
+ public Iterator<Object> getViewableIterator()
{
- List components = new ArrayList();
+ List<Object> components = new ArrayList<Object>();
components.add(getProperty());
Iterator<Entry> iter = _entries.iterator();
package org.apache.poi.poifs.filesystem;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DocumentProperty;
* @return true if the Entry is a DocumentEntry, else false
*/
+ @Override
public boolean isDocumentEntry()
{
return true;
* false
*/
+ @Override
protected boolean isDeleteOK()
{
return true;
* back end store
*/
- public Iterator getViewableIterator()
+ public Iterator<Object> getViewableIterator()
{
- List components = new ArrayList();
+ List<Object> components = new ArrayList<Object>();
components.add(getProperty());
components.add(_document);
* @return an Iterator; may not be null, but may have an empty back end
* store
*/
- public Iterator getViewableIterator() {
- return Collections.EMPTY_LIST.iterator();
+ public Iterator<Object> getViewableIterator() {
+ return Collections.emptyList().iterator();
}
/**
import org.apache.poi.poifs.property.DirectoryProperty;
import org.apache.poi.poifs.property.NPropertyTable;
import org.apache.poi.poifs.storage.BATBlock;
+import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex;
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
import org.apache.poi.poifs.storage.HeaderBlock;
import org.apache.poi.poifs.storage.HeaderBlockConstants;
import org.apache.poi.poifs.storage.HeaderBlockWriter;
-import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex;
import org.apache.poi.util.CloseIgnoringInputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LongField;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
/**
* This is the main class of the POIFS system; it manages the entire
public class NPOIFSFileSystem extends BlockStore
implements POIFSViewable, Closeable
{
- private static final POILogger _logger =
- POILogFactory.getLogger(NPOIFSFileSystem.class);
+// private static final POILogger _logger =
+// POILogFactory.getLogger(NPOIFSFileSystem.class);
/**
* Convenience method for clients that want to avoid the auto-close behaviour of the constructor.
*
* @exception IOException on errors reading, or on invalid data
*/
+ @SuppressWarnings("resource")
public NPOIFSFileSystem(File file, boolean readOnly)
throws IOException
{
/**
* Load the block at the given offset.
*/
+ @Override
protected ByteBuffer getBlockAt(final int offset) throws IOException {
// The header block doesn't count, so add one
long startAt = (offset+1) * bigBlockSize.getBigBlockSize();
* Load the block at the given offset,
* extending the file if needed
*/
+ @Override
protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException {
try {
return getBlockAt(offset);
* Returns the BATBlock that handles the specified offset,
* and the relative index within it
*/
+ @Override
protected BATBlockAndIndex getBATBlockAndIndex(final int offset) {
return BATBlock.getBATBlockAndIndex(
offset, _header, _bat_blocks
/**
* Works out what block follows the specified one.
*/
+ @Override
protected int getNextBlock(final int offset) {
BATBlockAndIndex bai = getBATBlockAndIndex(offset);
return bai.getBlock().getValueAt( bai.getIndex() );
/**
* Changes the record of what block follows the specified one.
*/
+ @Override
protected void setNextBlock(final int offset, final int nextBlock) {
BATBlockAndIndex bai = getBATBlockAndIndex(offset);
bai.getBlock().setValueAt(
* This method will extend the file if needed, and if doing
* so, allocate new FAT blocks to address the extra space.
*/
+ @Override
protected int getFreeBlock() throws IOException {
// First up, do we have any spare ones?
int offset = 0;
System.exit(1);
}
FileInputStream istream = new FileInputStream(args[ 0 ]);
- FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
-
- new NPOIFSFileSystem(istream).writeFilesystem(ostream);
- istream.close();
- ostream.close();
+ try {
+ FileOutputStream ostream = new FileOutputStream(args[ 1 ]);
+ try {
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(istream);
+ try {
+ fs.writeFilesystem(ostream);
+ } finally {
+ fs.close();
+ }
+ } finally {
+ ostream.close();
+ }
+ } finally {
+ istream.close();
+ }
}
/**
* back end store
*/
- public Iterator getViewableIterator()
+ public Iterator<Object> getViewableIterator()
{
if (!preferArray())
{
return (( POIFSViewable ) getRoot()).getViewableIterator();
}
- return Collections.EMPTY_LIST.iterator();
+ return Collections.emptyList().iterator();
}
/**
public int getBigBlockSize() {
return bigBlockSize.getBigBlockSize();
}
+
/**
* @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
*/
public POIFSBigBlockSize getBigBlockSizeDetails() {
return bigBlockSize;
}
+
+ @Override
protected int getBlockStoreBlockSize() {
return getBigBlockSize();
}
* @return an Iterator; may not be null, but may have an empty back end
* store
*/
- public Iterator getViewableIterator() {
- return Collections.EMPTY_LIST.iterator();
+ public Iterator<Object> getViewableIterator() {
+ return Collections.emptyList().iterator();
}
/**
import org.apache.poi.poifs.property.DirectoryProperty;
import org.apache.poi.poifs.property.Property;
import org.apache.poi.poifs.property.PropertyTable;
-import org.apache.poi.poifs.storage.BATBlock;
-import org.apache.poi.poifs.storage.BlockAllocationTableReader;
-import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
-import org.apache.poi.poifs.storage.BlockList;
-import org.apache.poi.poifs.storage.BlockWritable;
-import org.apache.poi.poifs.storage.HeaderBlockConstants;
-import org.apache.poi.poifs.storage.HeaderBlock;
-import org.apache.poi.poifs.storage.HeaderBlockWriter;
-import org.apache.poi.poifs.storage.RawDataBlockList;
-import org.apache.poi.poifs.storage.SmallBlockTableReader;
-import org.apache.poi.poifs.storage.SmallBlockTableWriter;
+import org.apache.poi.poifs.storage.*;
import org.apache.poi.util.CloseIgnoringInputStream;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LongField;
}
private PropertyTable _property_table;
- private List _documents;
+ private List<POIFSViewable> _documents;
private DirectoryNode _root;
/**
{
HeaderBlock header_block = new HeaderBlock(bigBlockSize);
_property_table = new PropertyTable(header_block);
- _documents = new ArrayList();
+ _documents = new ArrayList<POIFSViewable>();
_root = null;
}
// create a list of BATManaged objects: the documents plus the
// property table and the small block table
- List bm_objects = new ArrayList();
+ List<Object> bm_objects = new ArrayList<Object>();
bm_objects.addAll(_documents);
bm_objects.add(_property_table);
// walk the list, allocating space for each and assigning each
// a starting block number
- Iterator iter = bm_objects.iterator();
+ Iterator<Object> iter = bm_objects.iterator();
while (iter.hasNext())
{
// property table, the small block store, the small block
// allocation table, the block allocation table, and the
// extended block allocation table blocks)
- List writers = new ArrayList();
+ List<Object> writers = new ArrayList<Object>();
writers.add(header_block_writer);
writers.addAll(_documents);
private void processProperties(final BlockList small_blocks,
final BlockList big_blocks,
- final Iterator properties,
+ final Iterator<Property> properties,
final DirectoryNode dir,
final int headerPropertiesStartAt)
throws IOException
{
while (properties.hasNext())
{
- Property property = ( Property ) properties.next();
+ Property property = properties.next();
String name = property.getName();
DirectoryNode parent = (dir == null)
? (( DirectoryNode ) getRoot())
* back end store
*/
- public Iterator getViewableIterator()
+ public Iterator<Object> getViewableIterator()
{
if (!preferArray())
{
return (( POIFSViewable ) getRoot()).getViewableIterator();
}
- return Collections.EMPTY_LIST.iterator();
+ return Collections.emptyList().iterator();
}
/**
this(data, data.length);
}
+ @Override
public ByteBuffer read(int length, long position) {
if(position >= size) {
throw new IndexOutOfBoundsException(
return ByteBuffer.wrap(buffer, (int)position, toRead);
}
+ @Override
public void write(ByteBuffer src, long position) {
// Extend if needed
long endPosition = position + src.capacity();
buffer = nb;
}
+ @Override
public void copyTo(OutputStream stream) throws IOException {
stream.write(buffer, 0, (int)size);
}
+ @Override
public long size() {
return size;
}
+ @Override
public void close() {
buffer = null;
size = -1;
*/
public class FileBackedDataSource extends DataSource {
private FileChannel channel;
-
+
+ @SuppressWarnings("resource")
public FileBackedDataSource(File file) throws FileNotFoundException {
if(!file.exists()) {
throw new FileNotFoundException(file.toString());
}
this.channel = (new RandomAccessFile(file, "r")).getChannel();
}
+
public FileBackedDataSource(FileChannel channel) {
this.channel = channel;
}
-
+
+ @Override
public ByteBuffer read(int length, long position) throws IOException {
if(position >= size()) {
throw new IllegalArgumentException("Position " + position + " past the end of the file");
channel.position(position);
ByteBuffer dst = ByteBuffer.allocate(length);
int worked = IOUtils.readFully(channel, dst);
-
+
// Check
if(worked == -1) {
throw new IllegalArgumentException("Position " + position + " past the end of the file");
}
-
+
// Ready it for reading
dst.position(0);
-
+
// All done
return dst;
}
-
+
+ @Override
public void write(ByteBuffer src, long position) throws IOException {
channel.write(src, position);
}
-
+
+ @Override
public void copyTo(OutputStream stream) throws IOException {
// Wrap the OutputSteam as a channel
WritableByteChannel out = Channels.newChannel(stream);
// Now do the transfer
channel.transferTo(0, channel.size(), out);
}
-
+
+ @Override
public long size() throws IOException {
return channel.size();
}
-
+
+ @Override
public void close() throws IOException {
channel.close();
}
package org.apache.poi.poifs.property;
-import java.io.*;
-
-import java.util.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
import org.apache.poi.hpsf.ClassID;
-
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.util.ByteField;
* @return an Iterator; may not be null, but may have an empty
* back end store
*/
- public Iterator getViewableIterator()
+ public Iterator<Object> getViewableIterator()
{
- return Collections.EMPTY_LIST.iterator();
+ return Collections.emptyList().iterator();
}
/**
this.field_2_first_col = firstCol;
}
+ @Override
public void write(LittleEndianOutput out) {
out.writeByte(sid + getPtgClass());
out.writeShort(field_1_first_row);
out.writeShort(field_2_first_col);
}
+ @Override
public int getSize() {
return SIZE;
}
return field_2_first_col;
}
+ @Override
public String toFormulaString() {
throw new RuntimeException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't");
}
+ @Override
public String toString() {
StringBuffer buffer = new StringBuffer("[Array Formula or Shared Formula]\n");
buffer.append("row = ").append(getRow()).append("\n");
* This helps get rid of gratuitous diffs when comparing two dumps
* Subclasses may output more relevant information by overriding this method
**/
+ @Override
public String toString(){
return this.getClass().toString();
}
countSeen = 0;
lastRecordSeen = null;
}
+ @Override
public short abortableProcessRecord(Record record) {
countSeen++;
lastRecordSeen = record;
// Open the two filesystems
DirectoryNode[] files = new DirectoryNode[2];
files[0] = (new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream("Simple.xls"))).getRoot();
- files[1] = (new NPOIFSFileSystem(HSSFTestDataSamples.getSampleFile("Simple.xls"))).getRoot();
-
- // Open without preserving nodes
- for(DirectoryNode dir : files) {
- HSSFWorkbook workbook = new HSSFWorkbook(dir, false);
- HSSFSheet sheet = workbook.getSheetAt(0);
- HSSFCell cell = sheet.getRow(0).getCell(0);
- assertEquals("replaceMe", cell .getRichStringCellValue().getString());
- }
-
- // Now re-check with preserving
- for(DirectoryNode dir : files) {
- HSSFWorkbook workbook = new HSSFWorkbook(dir, true);
- HSSFSheet sheet = workbook.getSheetAt(0);
- HSSFCell cell = sheet.getRow(0).getCell(0);
- assertEquals("replaceMe", cell .getRichStringCellValue().getString());
+ NPOIFSFileSystem npoifsFileSystem = new NPOIFSFileSystem(HSSFTestDataSamples.getSampleFile("Simple.xls"));
+ try {
+ files[1] = npoifsFileSystem.getRoot();
+
+ // Open without preserving nodes
+ for(DirectoryNode dir : files) {
+ HSSFWorkbook workbook = new HSSFWorkbook(dir, false);
+ HSSFSheet sheet = workbook.getSheetAt(0);
+ HSSFCell cell = sheet.getRow(0).getCell(0);
+ assertEquals("replaceMe", cell .getRichStringCellValue().getString());
+ }
+
+ // Now re-check with preserving
+ for(DirectoryNode dir : files) {
+ HSSFWorkbook workbook = new HSSFWorkbook(dir, true);
+ HSSFSheet sheet = workbook.getSheetAt(0);
+ HSSFCell cell = sheet.getRow(0).getCell(0);
+ assertEquals("replaceMe", cell .getRichStringCellValue().getString());
+ }
+ } finally {
+ npoifsFileSystem.close();
}
}
// Open the two filesystems
DirectoryNode[] files = new DirectoryNode[2];
files[0] = (new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream("WithEmbeddedObjects.xls"))).getRoot();
- files[1] = (new NPOIFSFileSystem(HSSFTestDataSamples.getSampleFile("WithEmbeddedObjects.xls"))).getRoot();
-
- // Check the embedded parts
- for(DirectoryNode root : files) {
- HSSFWorkbook hw = new HSSFWorkbook(root, true);
- List<HSSFObjectData> objects = hw.getAllEmbeddedObjects();
- boolean found = false;
- for (int i = 0; i < objects.size(); i++) {
- HSSFObjectData embeddedObject = objects.get(i);
- if (embeddedObject.hasDirectoryEntry()) {
- DirectoryEntry dir = embeddedObject.getDirectory();
- if (dir instanceof DirectoryNode) {
- DirectoryNode dNode = (DirectoryNode)dir;
- if (hasEntry(dNode,"WordDocument")) {
- found = true;
- }
- }
- }
- }
- assertTrue(found);
+ NPOIFSFileSystem npoifsFileSystem = new NPOIFSFileSystem(HSSFTestDataSamples.getSampleFile("WithEmbeddedObjects.xls"));
+ try {
+ files[1] = npoifsFileSystem.getRoot();
+
+ // Check the embedded parts
+ for(DirectoryNode root : files) {
+ HSSFWorkbook hw = new HSSFWorkbook(root, true);
+ List<HSSFObjectData> objects = hw.getAllEmbeddedObjects();
+ boolean found = false;
+ for (int i = 0; i < objects.size(); i++) {
+ HSSFObjectData embeddedObject = objects.get(i);
+ if (embeddedObject.hasDirectoryEntry()) {
+ DirectoryEntry dir = embeddedObject.getDirectory();
+ if (dir instanceof DirectoryNode) {
+ DirectoryNode dNode = (DirectoryNode)dir;
+ if (hasEntry(dNode,"WordDocument")) {
+ found = true;
+ }
+ }
+ }
+ }
+ assertTrue(found);
+ }
+ } finally {
+ npoifsFileSystem.close();
}
}