Refactoring Record.serialize methods

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@718810 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-11-19 00:06:06 +00:00
parent a9c963b08a
commit 65af4a310a
41 changed files with 967 additions and 1879 deletions

View File

@ -95,7 +95,7 @@ public final class Workbook implements Model {
protected int numxfs = 0; // hold the number of extended format records
protected int numfonts = 0; // hold the number of font records
private short maxformatid = -1; // holds the max format id
private int maxformatid = -1; // holds the max format id
private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used
private DrawingManager2 drawingManager;
private List escherBSERecords = new ArrayList(); // EscherBSERecord
@ -1106,15 +1106,8 @@ public final class Workbook implements Model {
* @see org.apache.poi.hssf.record.Record
* @return record containing a TabIdRecord
*/
protected Record createTabId() {
TabIdRecord retval = new TabIdRecord();
short[] tabidarray = {
0
};
retval.setTabIdArray(tabidarray);
return retval;
private static TabIdRecord createTabId() {
return new TabIdRecord();
}
/**
@ -1334,7 +1327,6 @@ public final class Workbook implements Model {
* @see org.apache.poi.hssf.record.Record
* @return record containing a FontRecord
*/
protected Record createFont() {
FontRecord retval = new FontRecord();
@ -1342,7 +1334,6 @@ public final class Workbook implements Model {
retval.setAttributes(( short ) 0x0);
retval.setColorPaletteIndex(( short ) 0x7fff);
retval.setBoldWeight(( short ) 0x190);
retval.setFontNameLength(( byte ) 5);
retval.setFontName("Arial");
return retval;
}
@ -1355,66 +1346,21 @@ public final class Workbook implements Model {
* @see org.apache.poi.hssf.record.FormatRecord
* @see org.apache.poi.hssf.record.Record
*/
protected Record createFormat(int id) { // we'll need multiple editions for
FormatRecord retval = new FormatRecord(); // the differnt formats
private static FormatRecord createFormat(int id) {
// we'll need multiple editions for
// the different formats
switch (id) {
case 0 :
retval.setIndexCode(( short ) 5);
retval.setFormatStringLength(( byte ) 0x17);
retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)");
break;
case 1 :
retval.setIndexCode(( short ) 6);
retval.setFormatStringLength(( byte ) 0x1c);
retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
break;
case 2 :
retval.setIndexCode(( short ) 7);
retval.setFormatStringLength(( byte ) 0x1d);
retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
break;
case 3 :
retval.setIndexCode(( short ) 8);
retval.setFormatStringLength(( byte ) 0x22);
retval.setFormatString(
"\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
break;
case 4 :
retval.setIndexCode(( short ) 0x2a);
retval.setFormatStringLength(( byte ) 0x32);
retval.setFormatString(
"_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
break;
case 5 :
retval.setIndexCode(( short ) 0x29);
retval.setFormatStringLength(( byte ) 0x29);
retval.setFormatString(
"_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
break;
case 6 :
retval.setIndexCode(( short ) 0x2c);
retval.setFormatStringLength(( byte ) 0x3a);
retval.setFormatString(
"_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
break;
case 7 :
retval.setIndexCode(( short ) 0x2b);
retval.setFormatStringLength(( byte ) 0x31);
retval.setFormatString(
"_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
break;
case 0: return new FormatRecord(5, "\"$\"#,##0_);\\(\"$\"#,##0\\)");
case 1: return new FormatRecord(6, "\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
case 2: return new FormatRecord(7, "\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
case 3: return new FormatRecord(8, "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
case 4: return new FormatRecord(0x2a, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
case 5: return new FormatRecord(0x29, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
case 6: return new FormatRecord(0x2c, "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
case 7: return new FormatRecord(0x2b, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
}
return retval;
throw new IllegalArgumentException("Unexpected id " + id);
}
/**
@ -2061,12 +2007,12 @@ public final class Workbook implements Model {
for (iterator = formats.iterator(); iterator.hasNext();) {
FormatRecord r = (FormatRecord)iterator.next();
if (r.getFormatString().equals(format)) {
return r.getIndexCode();
return (short)r.getIndexCode();
}
}
if (createIfNotFound) {
return createFormat(format);
return (short)createFormat(format);
}
return -1;
@ -2082,21 +2028,15 @@ public final class Workbook implements Model {
/**
* Creates a FormatRecord, inserts it, and returns the index code.
* @param format the format string
* @param formatString the format string
* @return the index code of the format record.
* @see org.apache.poi.hssf.record.FormatRecord
* @see org.apache.poi.hssf.record.Record
*/
public short createFormat( String format )
{
// ++xfpos; //These are to ensure that positions are updated properly
// ++palettepos;
// ++bspos;
FormatRecord rec = new FormatRecord();
maxformatid = maxformatid >= (short) 0xa4 ? (short) ( maxformatid + 1 ) : (short) 0xa4; //Starting value from M$ empiracle study.
rec.setIndexCode( maxformatid );
rec.setFormatStringLength( (byte) format.length() );
rec.setFormatString( format );
public int createFormat(String formatString) {
maxformatid = maxformatid >= 0xa4 ? maxformatid + 1 : 0xa4; //Starting value from M$ empircal study.
FormatRecord rec = new FormatRecord(maxformatid, formatString);
int pos = 0;
while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid )

View File

@ -24,20 +24,19 @@ import java.util.List;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
* Title: Bound Sheet Record (aka BundleSheet) <P>
* Description: Defines a sheet within a workbook. Basically stores the sheetname
* Title: Bound Sheet Record (aka BundleSheet) (0x0085)<P>
* Description: Defines a sheet within a workbook. Basically stores the sheet name
* and tells where the Beginning of file record is within the HSSF
* file. <P>
* REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Sergei Kozello (sergeikozello at mail.ru)
* @version 2.0-pre
*/
public final class BoundSheetRecord extends Record {
public final class BoundSheetRecord extends StandardRecord {
public final static short sid = 0x0085;
private static final BitField hiddenFlag = BitFieldFactory.getInstance(0x01);
@ -160,23 +159,19 @@ public final class BoundSheetRecord extends Record {
return 8 + field_5_sheetname.length() * (isMultibyte() ? 2 : 1);
}
public int serialize(int offset, byte[] data) {
int dataSize = getDataSize();
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putInt(data, 4 + offset, getPositionOfBof());
LittleEndian.putUShort(data, 8 + offset, field_2_option_flags);
public void serialize(LittleEndianOutput out) {
out.writeInt(getPositionOfBof());
out.writeShort(field_2_option_flags);
String name = field_5_sheetname;
LittleEndian.putByte(data, 10 + offset, name.length());
LittleEndian.putByte(data, 11 + offset, field_4_isMultibyteUnicode);
out.writeByte(name.length());
out.writeByte(field_4_isMultibyteUnicode);
if (isMultibyte()) {
StringUtil.putUnicodeLE(name, data, 12 + offset);
StringUtil.putUnicodeLE(name, out);
} else {
StringUtil.putCompressedUnicode(name, data, 12 + offset);
StringUtil.putCompressedUnicode(name, out);
}
return 4 + dataSize;
}
public short getSid() {
@ -215,16 +210,14 @@ public final class BoundSheetRecord extends Record {
* Converts a List of {@link BoundSheetRecord}s to an array and sorts by the position of their
* BOFs.
*/
public static BoundSheetRecord[] orderByBofPosition(List boundSheetRecords) {
public static BoundSheetRecord[] orderByBofPosition(List<BoundSheetRecord> boundSheetRecords) {
BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()];
boundSheetRecords.toArray(bsrs);
Arrays.sort(bsrs, BOFComparator);
return bsrs;
}
private static final Comparator BOFComparator = new Comparator() {
public int compare(Object bsr1, Object bsr2) {
return compare((BoundSheetRecord)bsr1, (BoundSheetRecord)bsr2);
}
private static final Comparator<BoundSheetRecord> BOFComparator = new Comparator<BoundSheetRecord>() {
public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) {
return bsr1.getPositionOfBof() - bsr2.getPositionOfBof();
}

View File

@ -20,15 +20,15 @@ package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.cf.CellRangeUtil;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Conditional Formatting Header record CFHEADER (0x1B0)
* Conditional Formatting Header record CFHEADER (0x01B0)
*
* @author Dmitriy Kumshayev
*/
public final class CFHeaderRecord extends Record {
public static final short sid = 0x1B0;
public final class CFHeaderRecord extends StandardRecord {
public static final short sid = 0x01B0;
private int field_1_numcf;
private int field_2_need_recalculation;
@ -136,23 +136,15 @@ public final class CFHeaderRecord extends Record {
+ field_4_cell_ranges.getSize();
}
/**
* @return byte array containing instance data
*/
public int serialize(int offset, byte[] data) {
int dataSize = getDataSize();
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, field_1_numcf);
LittleEndian.putUShort(data, 6 + offset, field_2_need_recalculation);
field_3_enclosing_cell_range.serialize(8 + offset, data);
field_4_cell_ranges.serialize(16 + offset, data);
return 4 + dataSize;
public void serialize(LittleEndianOutput out) {
out.writeShort(field_1_numcf);
out.writeShort(field_2_need_recalculation);
field_3_enclosing_cell_range.serialize(out);
field_4_cell_ranges.serialize(out);
}
public short getSid()
{
public short getSid() {
return sid;
}

View File

@ -20,76 +20,67 @@
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import java.util.ArrayList;
import org.apache.poi.util.LittleEndianOutput;
/**
* CHARTTITLEFORMAT (0x1050)<p/>
* Describes the formatting runs associated with a chart title.
*/
public class ChartTitleFormatRecord extends Record {
public class ChartTitleFormatRecord extends StandardRecord {
public static final short sid = 0x1050;
private int m_recs;
private CTFormat[] _formats;
private class CTFormat {
private short m_offset;
private short m_fontIndex;
private static final class CTFormat {
public static final int ENCODED_SIZE=4;
private int _offset;
private int _fontIndex;
protected CTFormat(short offset,short fontIdx){
m_offset = offset;
m_fontIndex = fontIdx;
_offset = offset;
_fontIndex = fontIdx;
}
public short getOffset(){
return m_offset;
public CTFormat(RecordInputStream in) {
_offset = in.readShort();
_fontIndex = in.readShort();
}
public void setOffset(short newOff){
m_offset = newOff;
}
public short getFontIndex() {
return m_fontIndex;
}
}
private ArrayList m_formats;
public ChartTitleFormatRecord() {
super();
public int getOffset(){
return _offset;
}
public void setOffset(int newOff){
_offset = newOff;
}
public int getFontIndex() {
return _fontIndex;
}
public void serialize(LittleEndianOutput out) {
out.writeShort(_offset);
out.writeShort(_fontIndex);
}
}
public ChartTitleFormatRecord(RecordInputStream in) {
m_recs = in.readUShort();
int idx;
CTFormat ctf;
if (m_formats == null){
m_formats = new ArrayList(m_recs);
}
for(idx=0;idx<m_recs;idx++) {
ctf = new CTFormat(in.readShort(),in.readShort());
m_formats.add(ctf);
int nRecs = in.readUShort();
_formats = new CTFormat[nRecs];
for(int i=0;i<nRecs;i++) {
_formats[i] = new CTFormat(in);
}
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset,
( short ) (getRecordSize() - 4));
int idx;
CTFormat ctf;
LittleEndian.putShort(data, 4 + offset,(short)m_formats.size());
for(idx=0;idx<m_formats.size();idx++){
ctf = (CTFormat)m_formats.get(idx);
LittleEndian.putShort(data, 6 + (idx * 4) + offset, ctf.getOffset());
LittleEndian.putShort(data, 8 + (idx * 4) + offset, ctf.getFontIndex());
public void serialize(LittleEndianOutput out) {
out.writeShort(_formats.length);
for(int i=0; i<_formats.length; i++){
_formats[i].serialize(out);
}
return getRecordSize();
}
protected int getDataSize() {
return 2 + (4 * m_formats.size());
return 2 + CTFormat.ENCODED_SIZE * _formats.length;
}
public short getSid() {
@ -97,33 +88,29 @@ public class ChartTitleFormatRecord extends Record {
}
public int getFormatCount() {
return m_formats.size();
return _formats.length;
}
public void modifyFormatRun(short oldPos,short newLen) {
short shift = (short)0;
for(int idx=0;idx < m_formats.size();idx++) {
CTFormat ctf = (CTFormat)m_formats.get(idx);
public void modifyFormatRun(short oldPos, short newLen) {
int shift = 0;
for(int i=0; i < _formats.length; i++) {
CTFormat ctf = _formats[i];
if (shift != 0) {
ctf.setOffset((short)(ctf.getOffset() + shift));
} else if ((oldPos == ctf.getOffset()) && (idx < (m_formats.size() - 1))){
CTFormat nextCTF = (CTFormat)m_formats.get(idx + 1);
shift = (short)(newLen - (nextCTF.getOffset() - ctf.getOffset()));
ctf.setOffset(ctf.getOffset() + shift);
} else if (oldPos == ctf.getOffset() && i < _formats.length - 1){
CTFormat nextCTF = _formats[i + 1];
shift = newLen - (nextCTF.getOffset() - ctf.getOffset());
}
}
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[CHARTTITLEFORMAT]\n");
buffer.append(" .format_runs = ").append(m_recs)
.append("\n");
int idx;
CTFormat ctf;
for(idx=0;idx<m_formats.size();idx++){
ctf = (CTFormat)m_formats.get(idx);
buffer.append(" .format_runs = ").append(_formats.length).append("\n");
for(int i=0; i<_formats.length; i++) {
CTFormat ctf = _formats[i];
buffer.append(" .char_offset= ").append(ctf.getOffset());
buffer.append(",.fontidx= ").append(ctf.getFontIndex());
buffer.append("\n");

View File

@ -17,29 +17,56 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: DBCell Record
* Title: DBCell Record (0x00D7)<p/>
* Description: Used by Excel and other MS apps to quickly find rows in the sheets.<P>
* REFERENCE: PG 299/440 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height
* @version 2.0-pre
*/
public final class DBCellRecord extends Record {
public final class DBCellRecord extends StandardRecord {
public final static short sid = 0x00D7;
public final static int BLOCK_SIZE = 32;
public final static short sid = 0xd7;
private int field_1_row_offset;
private short[] field_2_cell_offsets;
public static final class Builder {
private short[] _cellOffsets;
private int _nCellOffsets;
public Builder() {
_cellOffsets = new short[4];
}
public DBCellRecord()
{
field_2_cell_offsets = new short[0];
public void addCellOffset(int cellRefOffset) {
if (_cellOffsets.length <= _nCellOffsets) {
short[] temp = new short[_nCellOffsets * 2];
System.arraycopy(_cellOffsets, 0, temp, 0, _nCellOffsets);
_cellOffsets = temp;
}
_cellOffsets[_nCellOffsets] = (short) cellRefOffset;
_nCellOffsets++;
}
public DBCellRecord build(int rowOffset) {
short[] cellOffsets = new short[_nCellOffsets];
System.arraycopy(_cellOffsets, 0, cellOffsets, 0, _nCellOffsets);
return new DBCellRecord(rowOffset, cellOffsets);
}
}
/**
* offset from the start of this DBCellRecord to the start of the first cell in
* the next DBCell block.
*/
private final int field_1_row_offset;
private final short[] field_2_cell_offsets;
DBCellRecord(int rowOffset, short[]cellOffsets) {
field_1_row_offset = rowOffset;
field_2_cell_offsets = cellOffsets;
}
public DBCellRecord(RecordInputStream in)
{
public DBCellRecord(RecordInputStream in) {
field_1_row_offset = in.readUShort();
int size = in.remaining();
field_2_cell_offsets = new short[ size / 2 ];
@ -50,101 +77,28 @@ public final class DBCellRecord extends Record {
}
}
/**
* sets offset from the start of this DBCellRecord to the start of the first cell in
* the next DBCell block.
*
* @param offset offset to the start of the first cell in the next DBCell block
*/
public void setRowOffset(int offset)
{
field_1_row_offset = offset;
}
// need short list impl.
public void addCellOffset(short offset)
{
if (field_2_cell_offsets == null)
{
field_2_cell_offsets = new short[ 1 ];
}
else
{
short[] temp = new short[ field_2_cell_offsets.length + 1 ];
System.arraycopy(field_2_cell_offsets, 0, temp, 0,
field_2_cell_offsets.length);
field_2_cell_offsets = temp;
}
field_2_cell_offsets[ field_2_cell_offsets.length - 1 ] = offset;
}
/**
* gets offset from the start of this DBCellRecord to the start of the first cell in
* the next DBCell block.
*
* @return rowoffset to the start of the first cell in the next DBCell block
*/
public int getRowOffset()
{
return field_1_row_offset;
}
/**
* return the cell offset in the array
*
* @param index of the cell offset to retrieve
* @return celloffset from the celloffset array
*/
public short getCellOffsetAt(int index)
{
return field_2_cell_offsets[ index ];
}
/**
* get the number of cell offsets in the celloffset array
*
* @return number of cell offsets
*/
public int getNumCellOffsets()
{
return field_2_cell_offsets.length;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[DBCELL]\n");
buffer.append(" .rowoffset = ")
.append(Integer.toHexString(getRowOffset())).append("\n");
for (int k = 0; k < getNumCellOffsets(); k++)
{
buffer.append(" .cell_" + k + " = ")
.append(Integer.toHexString(getCellOffsetAt(k))).append("\n");
buffer.append(" .rowoffset = ").append(HexDump.intToHex(field_1_row_offset)).append("\n");
for (int k = 0; k < field_2_cell_offsets.length; k++) {
buffer.append(" .cell_").append(k).append(" = ")
.append(HexDump.shortToHex(field_2_cell_offsets[ k ])).append("\n");
}
buffer.append("[/DBCELL]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
if (field_2_cell_offsets == null)
{
field_2_cell_offsets = new short[ 0 ];
public void serialize(LittleEndianOutput out) {
out.writeInt(field_1_row_offset);
for (int k = 0; k < field_2_cell_offsets.length; k++) {
out.writeShort(field_2_cell_offsets[ k ]);
}
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset,
(( short ) (4 + (getNumCellOffsets() * 2))));
LittleEndian.putInt(data, 4 + offset, getRowOffset());
for (int k = 0; k < getNumCellOffsets(); k++)
{
LittleEndian.putShort(data, 8 + 2*k + offset, getCellOffsetAt(k));
}
return getRecordSize();
}
protected int getDataSize() {
return 4 + (getNumCellOffsets() * 2);
return 4 + field_2_cell_offsets.length * 2;
}
/**
@ -158,14 +112,12 @@ public final class DBCellRecord extends Record {
return nBlocks * 8 + nRows * 2;
}
public short getSid()
{
public short getSid() {
return sid;
}
public Object clone() {
// TODO - make immutable.
// this should be safe because only the instantiating code mutates these objects
// safe because immutable
return this;
}
}

View File

@ -16,16 +16,15 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: DATAVALIDATIONS Record<P>
* Title: DATAVALIDATIONS Record (0x01B2)<p/>
* Description: used in data validation ;
* This record is the list header of all data validation records (0x01BE) in the current sheet.
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
public class DVALRecord extends Record
{
public final class DVALRecord extends StandardRecord {
public final static short sid = 0x01B2;
/** Options of the DVAL */
@ -48,57 +47,51 @@ public class DVALRecord extends Record
field_5_dv_no = 0x00000000;
}
public DVALRecord(RecordInputStream in)
{
this.field_1_options = in.readShort();
this.field_2_horiz_pos = in.readInt();
this.field_3_vert_pos = in.readInt();
this.field_cbo_id = in.readInt();
this.field_5_dv_no = in.readInt();
public DVALRecord(RecordInputStream in) {
field_1_options = in.readShort();
field_2_horiz_pos = in.readInt();
field_3_vert_pos = in.readInt();
field_cbo_id = in.readInt();
field_5_dv_no = in.readInt();
}
/**
* @param field_1_options the options of the dialog
*/
public void setOptions(short field_1_options) {
this.field_1_options = field_1_options;
public void setOptions(short options) {
field_1_options = options;
}
/**
* @param field_2_horiz_pos the Horizontal position of the dialog
*/
public void setHorizontalPos(int field_2_horiz_pos) {
this.field_2_horiz_pos = field_2_horiz_pos;
public void setHorizontalPos(int horiz_pos) {
field_2_horiz_pos = horiz_pos;
}
/**
* @param field_3_vert_pos the Vertical position of the dialog
*/
public void setVerticalPos(int field_3_vert_pos) {
this.field_3_vert_pos = field_3_vert_pos;
public void setVerticalPos(int vert_pos) {
field_3_vert_pos = vert_pos;
}
/**
* set the object ID of the drop down arrow object for list boxes
* @param cboID - Object ID
*/
public void setObjectID(int cboID)
{
this.field_cbo_id = cboID;
public void setObjectID(int cboID) {
field_cbo_id = cboID;
}
/**
* Set the number of following DV records
* @param dvNo - the DV records number
*/
public void setDVRecNo(int dvNo)
{
this.field_5_dv_no = dvNo;
public void setDVRecNo(int dvNo) {
field_5_dv_no = dvNo;
}
/**
* @return the field_1_options
*/
@ -123,64 +116,55 @@ public class DVALRecord extends Record
/**
* get Object ID of the drop down arrow object for list boxes
*/
public int getObjectID( )
{
return this.field_cbo_id;
public int getObjectID() {
return field_cbo_id;
}
/**
* Get number of following DV records
*/
public int getDVRecNo( )
{
return this.field_5_dv_no;
public int getDVRecNo() {
return field_5_dv_no;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[DVAL]\n");
buffer.append(" .options = ").append(this.getOptions()).append('\n');
buffer.append(" .horizPos = ").append(this.getHorizontalPos()).append('\n');
buffer.append(" .vertPos = ").append(this.getVerticalPos()).append('\n');
buffer.append(" .comboObjectID = ").append(Integer.toHexString(this.getObjectID())).append("\n");
buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(this.getDVRecNo())).append("\n");
buffer.append(" .options = ").append(getOptions()).append('\n');
buffer.append(" .horizPos = ").append(getHorizontalPos()).append('\n');
buffer.append(" .vertPos = ").append(getVerticalPos()).append('\n');
buffer.append(" .comboObjectID = ").append(Integer.toHexString(getObjectID())).append("\n");
buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(getDVRecNo())).append("\n");
buffer.append("[/DVAL]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, this.sid);
LittleEndian.putShort(data, 2 + offset, ( short)(this.getRecordSize()-4));
LittleEndian.putShort(data, 4 + offset, this.getOptions());
LittleEndian.putInt(data, 6 + offset, this.getHorizontalPos());
LittleEndian.putInt(data, 10 + offset, this.getVerticalPos());
LittleEndian.putInt(data, 14 + offset, this.getObjectID());
LittleEndian.putInt(data, 18 + offset, this.getDVRecNo());
return getRecordSize();
public void serialize(LittleEndianOutput out) {
out.writeShort(getOptions());
out.writeInt(getHorizontalPos());
out.writeInt(getVerticalPos());
out.writeInt(getObjectID());
out.writeInt(getDVRecNo());
}
protected int getDataSize() {
return 18;
}
public short getSid()
{
return this.sid;
public short getSid() {
return sid;
}
public Object clone()
{
public Object clone() {
DVALRecord rec = new DVALRecord();
rec.field_1_options = field_1_options;
rec.field_2_horiz_pos = field_2_horiz_pos;
rec.field_3_vert_pos = field_3_vert_pos;
rec.field_cbo_id = this.field_cbo_id;
rec.field_5_dv_no = this.field_5_dv_no;
rec.field_cbo_id = field_cbo_id;
rec.field_5_dv_no = field_5_dv_no;
return rec;
}
}

View File

@ -17,9 +17,12 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
public final class DrawingRecord extends Record {
import org.apache.poi.util.LittleEndianOutput;
/**
* DrawingRecord (0x00EC)<p/>
*
*/
public final class DrawingRecord extends StandardRecord {
public static final short sid = 0x00EC;
private static final byte[] EMPTY_BYTE_ARRAY = { };
@ -31,70 +34,50 @@ public final class DrawingRecord extends Record {
recordData = EMPTY_BYTE_ARRAY;
}
public DrawingRecord( RecordInputStream in )
{
public DrawingRecord(RecordInputStream in) {
recordData = in.readRemainder();
}
public void processContinueRecord( byte[] record )
{
public void processContinueRecord(byte[] record) {
//don't merge continue record with the drawing record, it must be serialized separately
contd = record;
}
public int serialize( int offset, byte[] data )
{
if (recordData == null)
{
recordData = new byte[ 0 ];
}
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, ( short ) (recordData.length));
if (recordData.length > 0)
{
System.arraycopy(recordData, 0, data, 4 + offset, recordData.length);
}
return getRecordSize();
public void serialize(LittleEndianOutput out) {
out.write(recordData);
}
protected int getDataSize() {
int retval = 0;
if (recordData != null) {
retval += recordData.length;
}
return retval;
return recordData.length;
}
public short getSid()
{
public short getSid() {
return sid;
}
public byte[] getData()
{
public byte[] getData() {
if(contd != null) {
byte[] newBuffer = new byte[ recordData.length + contd.length ];
System.arraycopy( recordData, 0, newBuffer, 0, recordData.length );
System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length);
return newBuffer;
} else {
return recordData;
}
return recordData;
}
public void setData( byte[] thedata )
{
this.recordData = thedata;
public void setData(byte[] thedata) {
if (thedata == null) {
throw new IllegalArgumentException("data must not be null");
}
recordData = thedata;
}
public Object clone() {
DrawingRecord rec = new DrawingRecord();
rec.recordData = new byte[ recordData.length ];
System.arraycopy(recordData, 0, rec.recordData, 0, recordData.length);
rec.recordData = recordData.clone();
if (contd != null) {
System.arraycopy(contd, 0, rec.contd, 0, contd.length);
rec.contd = new byte[ contd.length ];
// TODO - this code probably never executes
rec.contd = contd.clone();
}
return rec;

View File

@ -1,111 +0,0 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
/*
* ExtSSTInfoSubRecord.java
*
* Created on September 8, 2001, 8:37 PM
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
/**
* Extended SST table info subrecord<P>
* contains the elements of "info" in the SST's array field<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
* @see org.apache.poi.hssf.record.ExtSSTRecord
*/
public class ExtSSTInfoSubRecord
extends Record
{
public static final int INFO_SIZE = 8;
public final static short sid =
0xFFF; // only here for conformance, doesn't really have an sid
private int field_1_stream_pos; // stream pointer to the SST record
private short field_2_bucket_sst_offset; // don't really understand this yet.
private short field_3_zero; // must be 0;
/** Creates new ExtSSTInfoSubRecord */
public ExtSSTInfoSubRecord()
{
}
public ExtSSTInfoSubRecord(RecordInputStream in)
{
field_1_stream_pos = in.readInt();
field_2_bucket_sst_offset = in.readShort();
field_3_zero = in.readShort();
}
public void setStreamPos(int pos)
{
field_1_stream_pos = pos;
}
public void setBucketRecordOffset(short offset)
{
field_2_bucket_sst_offset = offset;
}
public int getStreamPos()
{
return field_1_stream_pos;
}
public short getBucketSSTOffset()
{
return field_2_bucket_sst_offset;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[EXTSST]\n");
buffer.append(" .streampos = ")
.append(Integer.toHexString(getStreamPos())).append("\n");
buffer.append(" .bucketsstoffset= ")
.append(Integer.toHexString(getBucketSSTOffset())).append("\n");
buffer.append(" .zero = ")
.append(Integer.toHexString(field_3_zero)).append("\n");
buffer.append("[/EXTSST]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putInt(data, 0 + offset, getStreamPos());
LittleEndian.putShort(data, 4 + offset, getBucketSSTOffset());
LittleEndian.putShort(data, 6 + offset, ( short ) 0);
return getRecordSize();
}
protected int getDataSize() {
return 4;
}
public short getSid()
{
return sid;
}
}

View File

@ -17,13 +17,10 @@
package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Extended Static String Table<P>
* Title: Extended Static String Table (0x00FF)<p/>
* Description: This record is used for a quick lookup into the SST record. This
* record breaks the SST table into a set of buckets. The offsets
* to these buckets within the SST record are kept as well as the
@ -31,101 +28,108 @@ import org.apache.poi.util.LittleEndian;
* REFERENCE: PG 313 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at apache dot org)
* @version 2.0-pre
*
* @see org.apache.poi.hssf.record.ExtSSTInfoSubRecord
*/
public final class ExtSSTRecord extends Record {
public final class ExtSSTRecord extends StandardRecord {
public final static short sid = 0x00FF;
public static final int DEFAULT_BUCKET_SIZE = 8;
//Can't seem to find this documented but from the biffviewer it is clear that
//Excel only records the indexes for the first 128 buckets.
public static final int MAX_BUCKETS = 128;
private short field_1_strings_per_bucket = DEFAULT_BUCKET_SIZE;
private List field_2_sst_info;
private static final class InfoSubRecord {
public static final int ENCODED_SIZE = 8;
private int field_1_stream_pos; // stream pointer to the SST record
private int field_2_bucket_sst_offset; // don't really understand this yet.
/** unused - supposed to be zero */
private short field_3_zero;
/** Creates new ExtSSTInfoSubRecord */
public InfoSubRecord(int streamPos, int bucketSstOffset) {
field_1_stream_pos = streamPos;
field_2_bucket_sst_offset = bucketSstOffset;
}
public InfoSubRecord(RecordInputStream in)
{
field_1_stream_pos = in.readInt();
field_2_bucket_sst_offset = in.readShort();
field_3_zero = in.readShort();
}
public int getStreamPos() {
return field_1_stream_pos;
}
public int getBucketSSTOffset() {
return field_2_bucket_sst_offset;
}
public void serialize(LittleEndianOutput out) {
out.writeInt(field_1_stream_pos);
out.writeShort(field_2_bucket_sst_offset);
out.writeShort(field_3_zero);
}
}
private short _stringsPerBucket;
private InfoSubRecord[] _sstInfos;
public ExtSSTRecord()
{
field_2_sst_info = new ArrayList();
public ExtSSTRecord() {
_stringsPerBucket = DEFAULT_BUCKET_SIZE;
_sstInfos = new InfoSubRecord[0];
}
public ExtSSTRecord(RecordInputStream in)
{
field_2_sst_info = new ArrayList();
field_1_strings_per_bucket = in.readShort();
while (in.remaining() > 0) {
ExtSSTInfoSubRecord rec = new ExtSSTInfoSubRecord(in);
field_2_sst_info.add(rec);
public ExtSSTRecord(RecordInputStream in) {
_stringsPerBucket = in.readShort();
int nInfos = in.remaining() / InfoSubRecord.ENCODED_SIZE;
_sstInfos = new InfoSubRecord[nInfos];
for (int i = 0; i < _sstInfos.length; i++) {
_sstInfos[i] = new InfoSubRecord(in);
}
}
public void setNumStringsPerBucket(short numStrings)
{
field_1_strings_per_bucket = numStrings;
public void setNumStringsPerBucket(short numStrings) {
_stringsPerBucket = numStrings;
}
public void addInfoRecord(ExtSSTInfoSubRecord rec)
{
field_2_sst_info.add(rec);
}
public short getNumStringsPerBucket()
{
return field_1_strings_per_bucket;
}
public int getNumInfoRecords()
{
return field_2_sst_info.size();
}
public ExtSSTInfoSubRecord getInfoRecordAt(int elem)
{
return ( ExtSSTInfoSubRecord ) field_2_sst_info.get(elem);
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[EXTSST]\n");
buffer.append(" .dsst = ")
.append(Integer.toHexString(getNumStringsPerBucket()))
.append(Integer.toHexString(_stringsPerBucket))
.append("\n");
buffer.append(" .numInfoRecords = ").append(getNumInfoRecords())
buffer.append(" .numInfoRecords = ").append(_sstInfos.length)
.append("\n");
for (int k = 0; k < getNumInfoRecords(); k++)
for (int k = 0; k < _sstInfos.length; k++)
{
buffer.append(" .inforecord = ").append(k).append("\n");
buffer.append(" .streampos = ")
.append(Integer
.toHexString(getInfoRecordAt(k).getStreamPos())).append("\n");
.toHexString(_sstInfos[k].getStreamPos())).append("\n");
buffer.append(" .sstoffset = ")
.append(Integer
.toHexString(getInfoRecordAt(k).getBucketSSTOffset()))
.toHexString(_sstInfos[k].getBucketSSTOffset()))
.append("\n");
}
buffer.append("[/EXTSST]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
LittleEndian.putShort(data, 4 + offset, field_1_strings_per_bucket);
int pos = 6;
for (int k = 0; k < getNumInfoRecords(); k++)
{
ExtSSTInfoSubRecord rec = getInfoRecordAt(k);
pos += rec.serialize(pos + offset, data);
public void serialize(LittleEndianOutput out) {
out.writeShort(_stringsPerBucket);
for (int k = 0; k < _sstInfos.length; k++) {
_sstInfos[k].serialize(out);
}
return pos;
}
protected int getDataSize() {
return 2 + 8*getNumInfoRecords();
return 2 + InfoSubRecord.ENCODED_SIZE*_sstInfos.length;
}
public static final int getNumberOfInfoRecsForStrings(int numStrings) {
@ -133,7 +137,7 @@ public final class ExtSSTRecord extends Record {
if ((numStrings % DEFAULT_BUCKET_SIZE) != 0)
infoRecs ++;
//Excel seems to max out after 128 info records.
//This isnt really documented anywhere...
//This isn't really documented anywhere...
if (infoRecs > MAX_BUCKETS)
infoRecs = MAX_BUCKETS;
return infoRecs;
@ -141,24 +145,18 @@ public final class ExtSSTRecord extends Record {
/** Given a number of strings (in the sst), returns the size of the extsst record*/
public static final int getRecordSizeForStrings(int numStrings) {
return 4 + 2 + (getNumberOfInfoRecsForStrings(numStrings) * 8);
return 4 + 2 + getNumberOfInfoRecsForStrings(numStrings) * 8;
}
public short getSid()
{
public short getSid() {
return sid;
}
public void setBucketOffsets( int[] bucketAbsoluteOffsets, int[] bucketRelativeOffsets )
{
this.field_2_sst_info = new ArrayList(bucketAbsoluteOffsets.length);
for ( int i = 0; i < bucketAbsoluteOffsets.length; i++ )
{
ExtSSTInfoSubRecord r = new ExtSSTInfoSubRecord();
r.setBucketRecordOffset((short)bucketRelativeOffsets[i]);
r.setStreamPos(bucketAbsoluteOffsets[i]);
field_2_sst_info.add(r);
public void setBucketOffsets(int[] bucketAbsoluteOffsets, int[] bucketRelativeOffsets) {
// TODO - replace no-arg constructor with this logic
_sstInfos = new InfoSubRecord[bucketAbsoluteOffsets.length];
for (int i = 0; i < bucketAbsoluteOffsets.length; i++) {
_sstInfos[i] = new InfoSubRecord(bucketAbsoluteOffsets[i], bucketRelativeOffsets[i]);
}
}
}

View File

@ -20,7 +20,7 @@ package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* EXTERNSHEET (0x0017)<br/>
@ -28,9 +28,9 @@ import org.apache.poi.util.LittleEndian;
*
* @author Libin Roman (Vista Portal LDT. Developer)
*/
public class ExternSheetRecord extends Record {
public class ExternSheetRecord extends StandardRecord {
public final static short sid = 0x0017;
private List _list;
private List<RefSubRecord> _list;
private final class RefSubRecord {
public static final int ENCODED_SIZE = 6;
@ -73,43 +73,27 @@ public class ExternSheetRecord extends Record {
return buffer.toString();
}
/**
* 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.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public void serialize(int offset, byte [] data) {
LittleEndian.putUShort(data, 0 + offset, _extBookIndex);
LittleEndian.putUShort(data, 2 + offset, _firstSheetIndex);
LittleEndian.putUShort(data, 4 + offset, _lastSheetIndex);
public void serialize(LittleEndianOutput out) {
out.writeShort(_extBookIndex);
out.writeShort(_firstSheetIndex);
out.writeShort(_lastSheetIndex);
}
}
public ExternSheetRecord() {
_list = new ArrayList();
_list = new ArrayList<RefSubRecord>();
}
/**
* called by the constructor, should set class level fields. Should throw
* runtime exception for bad/icomplete data.
*
* @param in the RecordInputstream to read the record from
*/
public ExternSheetRecord(RecordInputStream in) {
_list = new ArrayList();
_list = new ArrayList<RefSubRecord>();
int nItems = in.readShort();
for (int i = 0 ; i < nItems ; ++i) {
RefSubRecord rec = new RefSubRecord(in);
_list.add( rec);
_list.add(rec);
}
}
@ -157,35 +141,18 @@ public class ExternSheetRecord extends Record {
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE;
}
/**
* 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.
*
* @param offset to begin writing at
* @param data byte array containing instance data
* @return number of bytes written
*/
public int serialize(int offset, byte [] data) {
int dataSize = getDataSize();
public void serialize(LittleEndianOutput out) {
int nItems = _list.size();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, nItems);
int pos = 6 ;
out.writeShort(nItems);
for (int i = 0; i < nItems; i++) {
getRef(i).serialize(offset + pos, data);
pos +=6;
getRef(i).serialize(out);
}
return dataSize + 4;
}
private RefSubRecord getRef(int i) {
return (RefSubRecord) _list.get(i);
return _list.get(i);
}
/**

View File

@ -17,19 +17,19 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
* Title: FILESHARING<P>
* Title: FILESHARING (0x005B) <p/>
* Description: stores the encrypted readonly for a workbook (write protect)
* This functionality is accessed from the options dialog box available when performing 'Save As'.<p/>
* REFERENCE: PG 314 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p/>
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public final class FileSharingRecord extends Record {
public final class FileSharingRecord extends StandardRecord {
public final static short sid = 0x5b;
public final static short sid = 0x005B;
private short field_1_readonly;
private short field_2_password;
private byte field_3_username_unicode_options;
@ -103,12 +103,6 @@ public final class FileSharingRecord extends Record {
return field_2_password;
}
/**
* @return byte representing the length of the username field
*/
public short getUsernameLength() {
return (short) field_3_username_value.length();
}
/**
* @return username of the user that created the file
@ -139,22 +133,19 @@ public final class FileSharingRecord extends Record {
return buffer.toString();
}
public int serialize(int offset, byte [] data) {
public void serialize(LittleEndianOutput out) {
// TODO - junit
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize()-4));
LittleEndian.putShort(data, 4 + offset, getReadOnly());
LittleEndian.putShort(data, 6 + offset, getPassword());
LittleEndian.putShort(data, 8 + offset, getUsernameLength());
if(getUsernameLength() > 0) {
LittleEndian.putByte(data, 10 + offset, field_3_username_unicode_options);
StringUtil.putCompressedUnicode( getUsername(), data, 11 + offset );
out.writeShort(getReadOnly());
out.writeShort(getPassword());
out.writeShort(field_3_username_value.length());
if(field_3_username_value.length() > 0) {
out.writeByte(field_3_username_unicode_options);
StringUtil.putCompressedUnicode(getUsername(), out);
}
return getRecordSize();
}
protected int getDataSize() {
short nameLen = getUsernameLength();
int nameLen = field_3_username_value.length();
if (nameLen < 1) {
return 6;
}

View File

@ -17,18 +17,19 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
* Title: Font Record - descrbes a font in the workbook (index = 0-3,5-infinity - skip 4)<P>
* Title: Font Record (0x0031) <p/>
* - describes a font in the workbook (index = 0-3,5-infinity - skip 4)<P>
* Description: An element in the Font Table<P>
* REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public final class FontRecord extends Record {
public final class FontRecord extends StandardRecord {
public final static short sid = 0x0031; // docs are wrong (0x231 Microsoft Support site article Q184647)
public final static short SS_NONE = 0;
public final static short SS_SUPER = 1;
@ -42,16 +43,12 @@ public final class FontRecord extends Record {
private short field_2_attributes;
// 0 0x01 - Reserved bit must be 0
static final private BitField italic =
BitFieldFactory.getInstance(0x02); // is this font in italics
private static final BitField italic = BitFieldFactory.getInstance(0x02); // is this font in italics
// 2 0x04 - reserved bit must be 0
static final private BitField strikeout =
BitFieldFactory.getInstance(0x08); // is this font has a line through the center
static final private BitField macoutline = BitFieldFactory.getInstance(
0x10); // some weird macintosh thing....but who understands those mac people anyhow
static final private BitField macshadow = BitFieldFactory.getInstance(
0x20); // some weird macintosh thing....but who understands those mac people anyhow
private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center
private static final BitField macoutline = BitFieldFactory.getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow
// 7-6 - reserved bits must be 0
// the rest is unused
@ -62,15 +59,13 @@ public final class FontRecord extends Record {
private byte field_7_family; // ?? defined by windows api logfont structure?
private byte field_8_charset; // ?? defined by windows api logfont structure?
private byte field_9_zero = 0; // must be 0
private byte field_10_font_name_len; // length of the font name
/** possibly empty string never <code>null</code> */
private String field_11_font_name; // whoa...the font name
public FontRecord()
{
public FontRecord() {
}
public FontRecord(RecordInputStream in)
{
public FontRecord(RecordInputStream in) {
field_1_font_height = in.readShort();
field_2_attributes = in.readShort();
field_3_color_palette_index = in.readShort();
@ -80,17 +75,15 @@ public final class FontRecord extends Record {
field_7_family = in.readByte();
field_8_charset = in.readByte();
field_9_zero = in.readByte();
field_10_font_name_len = in.readByte();
if (field_10_font_name_len > 0)
{
if (in.readByte() == 0)
{ // is compressed unicode
field_11_font_name = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_font_name_len));
}
else
{ // is not compressed unicode
int field_10_font_name_len = in.readUByte();
if (field_10_font_name_len > 0) {
if (in.readByte() == 0) { // is compressed unicode
field_11_font_name = in.readCompressedUnicode(field_10_font_name_len);
} else { // is not compressed unicode
field_11_font_name = in.readUnicodeLEString(field_10_font_name_len);
}
} else {
field_11_font_name = "";
}
}
@ -244,17 +237,6 @@ public final class FontRecord extends Record {
field_8_charset = charset;
}
/**
* set the length of the fontname string
*
* @param len length of the font name
* @see #setFontName(String)
*/
public void setFontNameLength(byte len)
{
field_10_font_name_len = len;
}
/**
* set the name of the font
@ -415,18 +397,6 @@ public final class FontRecord extends Record {
return field_8_charset;
}
/**
* get the length of the fontname string
*
* @return length of the font name
* @see #getFontName()
*/
public byte getFontNameLength()
{
return field_10_font_name_len;
}
/**
* get the name of the font
*
@ -467,45 +437,46 @@ public final class FontRecord extends Record {
.append(Integer.toHexString(getFamily())).append("\n");
buffer.append(" .charset = ")
.append(Integer.toHexString(getCharset())).append("\n");
buffer.append(" .namelength = ")
.append(Integer.toHexString(getFontNameLength())).append("\n");
buffer.append(" .fontname = ").append(getFontName())
.append("\n");
buffer.append("[/FONT]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
int realflen = getFontNameLength() * 2;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(
data, 2 + offset,
( short ) (15 + realflen
+ 1)); // 19 - 4 (sid/len) + font name length = datasize
// undocumented single byte (1)
LittleEndian.putShort(data, 4 + offset, getFontHeight());
LittleEndian.putShort(data, 6 + offset, getAttributes());
LittleEndian.putShort(data, 8 + offset, getColorPaletteIndex());
LittleEndian.putShort(data, 10 + offset, getBoldWeight());
LittleEndian.putShort(data, 12 + offset, getSuperSubScript());
data[ 14 + offset ] = getUnderline();
data[ 15 + offset ] = getFamily();
data[ 16 + offset ] = getCharset();
data[ 17 + offset ] = field_9_zero;
data[ 18 + offset ] = getFontNameLength();
data[ 19 + offset ] = ( byte ) 1;
if (getFontName() != null) {
StringUtil.putUnicodeLE(getFontName(), data, 20 + offset);
}
return getRecordSize();
public void serialize(LittleEndianOutput out) {
out.writeShort(getFontHeight());
out.writeShort(getAttributes());
out.writeShort(getColorPaletteIndex());
out.writeShort(getBoldWeight());
out.writeShort(getSuperSubScript());
out.writeByte(getUnderline());
out.writeByte(getFamily());
out.writeByte(getCharset());
out.writeByte(field_9_zero);
int fontNameLen = field_11_font_name.length();
out.writeByte(fontNameLen);
if (fontNameLen > 0) {
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
out.writeByte(hasMultibyte ? 0x01 : 0x00);
if (hasMultibyte) {
StringUtil.putUnicodeLE(field_11_font_name, out);
} else {
StringUtil.putCompressedUnicode(field_11_font_name, out);
}
}
}
protected int getDataSize() {
// Note - no matter the original, we always
// re-serialise the font name as unicode
return 16 + getFontNameLength() * 2;
int size = 15; // 5 shorts + 5 bytes
int fontNameLen = field_11_font_name.length();
if (fontNameLen < 1) {
// options byte is not encoded if no character data
return size;
}
size ++; // options byte
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
return size + fontNameLen * (hasMultibyte ? 2 : 1);
}
public short getSid()
@ -528,7 +499,6 @@ public final class FontRecord extends Record {
field_7_family = source.field_7_family;
field_8_charset = source.field_8_charset;
field_9_zero = source.field_9_zero;
field_10_font_name_len = source.field_10_font_name_len;
field_11_font_name = source.field_11_font_name;
}
@ -548,7 +518,6 @@ public final class FontRecord extends Record {
result = prime * result + field_7_family;
result = prime * result + field_8_charset;
result = prime * result + field_9_zero;
result = prime * result + field_10_font_name_len;
return result;
}
@ -572,7 +541,6 @@ public final class FontRecord extends Record {
field_7_family == other.field_7_family &&
field_8_charset == other.field_8_charset &&
field_9_zero == other.field_9_zero &&
field_10_font_name_len == other.field_10_font_name_len &&
field_11_font_name.equals(other.field_11_font_name)
;
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -15,191 +14,61 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
/**
* Title: Footer Record <P>
* Title: Footer Record (0x0015) <p/>
* Description: Specifies the footer for a sheet<P>
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p/>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Shawn Laubach (slaubach at apache dot org) Modified 3/14/02
* @author Jason Height (jheight at chariot dot net dot au)
* @version 2.0-pre
*
*/
public final class FooterRecord extends HeaderFooterBase {
public final static short sid = 0x0015;
public class FooterRecord
extends Record
{
public final static short sid = 0x15;
private byte field_1_footer_len;
private byte field_2_reserved;
private byte field_3_unicode_flag;
private String field_4_footer;
public FooterRecord()
{
public FooterRecord(String text) {
super(text);
}
public FooterRecord(RecordInputStream in)
{
if (in.remaining() > 0)
{
field_1_footer_len = in.readByte();
/** These two fields are a bit odd. They are not documented*/
field_2_reserved = in.readByte();
field_3_unicode_flag = in.readByte(); // unicode
if(isMultibyte())
{
field_4_footer = in.readUnicodeLEString(LittleEndian.ubyteToInt( field_1_footer_len));
}
else
{
field_4_footer = in.readCompressedUnicode(LittleEndian.ubyteToInt( field_1_footer_len));
}
}
}
public FooterRecord(RecordInputStream in) {
super(in);
}
/**
* see the unicode flag
*
* @return boolean flag
* true:footer string has at least one multibyte character
*/
public boolean isMultibyte() {
return ((field_3_unicode_flag & 0xFF) == 1);
}
/**
* set the length of the footer string
*
* @param len length of the footer string
* @see #setFooter(String)
*/
public void setFooterLength(byte len)
{
field_1_footer_len = len;
}
/**
/**
* set the footer string
*
* @param footer string to display
* @see #setFooterLength(byte)
*/
public void setFooter(String footer)
{
field_4_footer = footer;
field_3_unicode_flag =
(byte) (StringUtil.hasMultibyte(field_4_footer) ? 1 : 0);
// Check it'll fit into the space in the record
if(field_4_footer == null) return;
if(field_3_unicode_flag == 1) {
if(field_4_footer.length() > 127) {
throw new IllegalArgumentException("Footer string too long (limit is 127 for unicode strings)");
}
} else {
if(field_4_footer.length() > 255) {
throw new IllegalArgumentException("Footer string too long (limit is 255 for non-unicode strings)");
}
}
}
/**
* get the length of the footer string
*
* @return length of the footer string
* @see #getFooter()
*/
public short getFooterLength()
{
return (short)(0xFF & field_1_footer_len); // [Shawn] Fixed needing unsigned byte
public void setFooter(String footer) {
setText(footer);
}
/**
* get the footer string
*
* @return footer string to display
* @see #getFooterLength()
*/
public String getFooter()
{
return field_4_footer;
public String getFooter() {
return getText();
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[FOOTER]\n");
buffer.append(" .footerlen = ")
.append(Integer.toHexString(getFooterLength())).append("\n");
buffer.append(" .footer = ").append(getFooter())
.append("\n");
buffer.append(" .footer = ").append(getText()).append("\n");
buffer.append("[/FOOTER]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
int len = 4;
if (getFooterLength() > 0)
{
len+=3; // [Shawn] Fixed for two null bytes in the length
}
short bytelen = (short)(isMultibyte() ?
getFooterLength()*2 : getFooterLength() );
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset,
( short ) ((len - 4) + bytelen ));
if (getFooterLength() > 0)
{
data[ 4 + offset ] = (byte)getFooterLength();
data[ 6 + offset ] = field_3_unicode_flag;
if(isMultibyte())
{
StringUtil.putUnicodeLE(getFooter(), data, 7 + offset);
}
else
{
StringUtil.putCompressedUnicode(getFooter(), data, 7 + offset); // [Shawn] Place the string in the correct offset
}
}
return getRecordSize();
}
protected int getDataSize() {
int retval = 0;
if (getFooterLength() > 0) {
retval+=3; // [Shawn] Fixed for two null bytes in the length
}
return retval + getFooterLength() * (isMultibyte() ? 2 : 1);
}
public short getSid()
{
public short getSid() {
return sid;
}
public Object clone() {
FooterRecord rec = new FooterRecord();
rec.field_1_footer_len = field_1_footer_len;
rec.field_2_reserved = field_2_reserved;
rec.field_3_unicode_flag = field_3_unicode_flag;
rec.field_4_footer = field_4_footer;
return rec;
return new FooterRecord(getText());
}
}

View File

@ -17,91 +17,41 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
* Title: Format Record<P>
* Description: describes a number format -- those goofy strings like $(#,###)<P>
* Title: Format Record (0x041E) <p/>
* Description: describes a number format -- those goofy strings like $(#,###)<p/>
*
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p/>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Shawn M. Laubach (slaubach at apache dot org)
* @author Shawn M. Laubach (slaubach at apache dot org)
*/
public final class FormatRecord extends Record {
public final class FormatRecord extends StandardRecord {
public final static short sid = 0x041E;
private short field_1_index_code;
private short field_3_unicode_len; // unicode string length
private boolean field_3_unicode_flag; // it is not undocumented - it is unicode flag
private String field_4_formatstring;
private final int field_1_index_code;
private final boolean field_3_hasMultibyte;
private final String field_4_formatstring;
public FormatRecord()
{
}
public FormatRecord(RecordInputStream in)
{
field_1_index_code = in.readShort();
field_3_unicode_len = in.readShort();
field_3_unicode_flag = ( in.readByte() & (byte)0x01 ) != 0;
if ( field_3_unicode_flag ) {
// unicode
field_4_formatstring = in.readUnicodeLEString( field_3_unicode_len );
}
else {
// not unicode
field_4_formatstring = in.readCompressedUnicode( field_3_unicode_len );
}
}
/**
* set the format index code (for built in formats)
*
* @param index the format index code
* @see org.apache.poi.hssf.model.Workbook
*/
public void setIndexCode(short index)
{
field_1_index_code = index;
}
/**
* set the format string length
*
* @param len the length of the format string
* @see #setFormatString(String)
*/
public void setFormatStringLength(byte len)
{
field_3_unicode_len = len;
}
/**
* set whether the string is unicode
*
* @param unicode flag for whether string is unicode
*/
public void setUnicodeFlag(boolean unicode) {
field_3_unicode_flag = unicode;
}
/**
* set the format string
*
* @param fs the format string
* @see #setFormatStringLength(byte)
*/
public void setFormatString(String fs)
{
public FormatRecord(int indexCode, String fs) {
field_1_index_code = indexCode;
field_4_formatstring = fs;
setUnicodeFlag(StringUtil.hasMultibyte(fs));
field_3_hasMultibyte = StringUtil.hasMultibyte(fs);
}
public FormatRecord(RecordInputStream in) {
field_1_index_code = in.readShort();
int field_3_unicode_len = in.readUShort();
field_3_hasMultibyte = (in.readByte() & 0x01) != 0;
if (field_3_hasMultibyte) {
field_4_formatstring = in.readUnicodeLEString(field_3_unicode_len);
} else {
field_4_formatstring = in.readCompressedUnicode(field_3_unicode_len);
}
}
/**
@ -110,95 +60,53 @@ public final class FormatRecord extends Record {
* @return the format index code
* @see org.apache.poi.hssf.model.Workbook
*/
public short getIndexCode()
{
public int getIndexCode() {
return field_1_index_code;
}
/**
* get the format string length
*
* @return the length of the format string
* @see #getFormatString()
*/
/* public short getFormatStringLength()
{
return field_3_unicode_flag ? field_3_unicode_len : field_2_formatstring_len;
}*/
/**
* get whether the string is unicode
*
* @return flag for whether string is unicode
*/
public boolean getUnicodeFlag() {
return field_3_unicode_flag;
}
/**
* get the format string
*
* @return the format string
*/
public String getFormatString()
{
public String getFormatString() {
return field_4_formatstring;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[FORMAT]\n");
buffer.append(" .indexcode = ")
.append(Integer.toHexString(getIndexCode())).append("\n");
/*
buffer.append(" .formatstringlen = ")
.append(Integer.toHexString(getFormatStringLength()))
.append("\n");
*/
buffer.append(" .unicode length = ")
.append(Integer.toHexString(field_3_unicode_len)).append("\n");
buffer.append(" .isUnicode = ")
.append( field_3_unicode_flag ).append("\n");
buffer.append(" .formatstring = ").append(getFormatString())
.append("\n");
buffer.append(" .indexcode = ").append(HexDump.shortToHex(getIndexCode())).append("\n");
buffer.append(" .isUnicode = ").append(field_3_hasMultibyte ).append("\n");
buffer.append(" .formatstring = ").append(getFormatString()).append("\n");
buffer.append("[/FORMAT]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)( 2 + 2 + 1 + ( (field_3_unicode_flag)
? 2 * field_3_unicode_len
: field_3_unicode_len ) ) );
// index + len + flag + format string length
LittleEndian.putShort(data, 4 + offset, getIndexCode());
LittleEndian.putShort(data, 6 + offset, field_3_unicode_len);
data[ 8 + offset ] = (byte)( (field_3_unicode_flag) ? 0x01 : 0x00 );
public void serialize(LittleEndianOutput out) {
String formatString = getFormatString();
out.writeShort(getIndexCode());
out.writeShort(formatString.length());
out.writeByte(field_3_hasMultibyte ? 0x01 : 0x00);
if ( field_3_unicode_flag ) {
// unicode
StringUtil.putUnicodeLE( getFormatString(), data, 9 + offset );
if ( field_3_hasMultibyte ) {
StringUtil.putUnicodeLE( formatString, out);
} else {
StringUtil.putCompressedUnicode( formatString, out);
}
else {
// not unicode
StringUtil.putCompressedUnicode( getFormatString(), data, 9 + offset );
}
return getRecordSize();
}
protected int getDataSize() {
return 5 + field_3_unicode_len * (field_3_unicode_flag ? 2 : 1);
return 5 // 2 shorts + 1 byte
+ getFormatString().length() * (field_3_hasMultibyte ? 2 : 1);
}
public short getSid()
{
public short getSid() {
return sid;
}
@Override
public Object clone() {
// immutable
return this;
}
}

View File

@ -0,0 +1,109 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
* Common header/footer base class
*
* @author Josh Micich
*/
abstract class HeaderFooterBase extends StandardRecord {
private boolean field_2_hasMultibyte;
private String field_3_text;
protected HeaderFooterBase(String text) {
setText(text);
}
protected HeaderFooterBase(RecordInputStream in) {
if (in.remaining() > 0) {
int field_1_footer_len = in.readShort();
field_2_hasMultibyte = in.readByte() != 0x00;
if (field_2_hasMultibyte) {
field_3_text = in.readUnicodeLEString(field_1_footer_len);
} else {
field_3_text = in.readCompressedUnicode(field_1_footer_len);
}
} else {
// Note - this is unusual: when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
field_3_text = "";
}
}
/**
* set the footer string
*
* @param text string to display
*/
public final void setText(String text) {
if (text == null) {
throw new IllegalArgumentException("text must not be null");
}
field_2_hasMultibyte = StringUtil.hasMultibyte(text);
field_3_text = text;
// Check it'll fit into the space in the record
if (field_2_hasMultibyte) {
if (field_3_text.length() > 127) {
throw new IllegalArgumentException(
"Footer string too long (limit is 127 for unicode strings)");
}
} else {
if (field_3_text.length() > 255) {
throw new IllegalArgumentException(
"Footer string too long (limit is 255 for non-unicode strings)");
}
}
}
/**
* get the length of the footer string
*
* @return length of the footer string
*/
private int getTextLength() {
return field_3_text.length();
}
public final String getText() {
return field_3_text;
}
public final void serialize(LittleEndianOutput out) {
if (getTextLength() > 0) {
out.writeShort(getTextLength());
out.writeByte(field_2_hasMultibyte ? 0x01 : 0x00);
if (field_2_hasMultibyte) {
StringUtil.putUnicodeLE(field_3_text, out);
} else {
StringUtil.putCompressedUnicode(field_3_text, out);
}
}
}
protected final int getDataSize() {
if (getTextLength() < 1) {
return 0;
}
return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1);
}
}

View File

@ -17,8 +17,6 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
/**
* Title: Header Record<P>
@ -28,172 +26,50 @@ import org.apache.poi.util.StringUtil;
* @author Shawn Laubach (slaubach at apache dot org) Modified 3/14/02
* @author Jason Height (jheight at chariot dot net dot au)
*/
public final class HeaderRecord extends Record {
public final class HeaderRecord extends HeaderFooterBase {
public final static short sid = 0x0014;
private byte field_1_header_len;
private byte field_2_reserved;
private byte field_3_unicode_flag;
private String field_4_header;
public HeaderRecord()
{
public HeaderRecord(String text) {
super(text);
}
public HeaderRecord(RecordInputStream in)
{
if (in.remaining() > 0)
{
field_1_header_len = in.readByte();
/** These two fields are a bit odd. They are not documented*/
field_2_reserved = in.readByte();
field_3_unicode_flag = in.readByte(); // unicode
if(isMultibyte())
{
field_4_header = in.readUnicodeLEString(LittleEndian.ubyteToInt( field_1_header_len));
}
else
{
field_4_header = in.readCompressedUnicode(LittleEndian.ubyteToInt( field_1_header_len));
}
}
}
/**
* see the unicode flag
*
* @return boolean flag
* true:footer string has at least one multibyte character
*/
public boolean isMultibyte() {
return ((field_3_unicode_flag & 0xFF) == 1);
}
/**
* set the length of the header string
*
* @param len length of the header string
* @see #setHeader(String)
*/
public void setHeaderLength(byte len)
{
field_1_header_len = len;
public HeaderRecord(RecordInputStream in) {
super(in);
}
/**
* set the header string
*
* @param header string to display
* @see #setHeaderLength(byte)
*/
public void setHeader(String header)
{
field_4_header = header;
field_3_unicode_flag =
(byte) (StringUtil.hasMultibyte(field_4_header) ? 1 : 0);
// Check it'll fit into the space in the record
if(field_4_header == null) return;
if(field_3_unicode_flag == 1) {
if(field_4_header.length() > 127) {
throw new IllegalArgumentException("Header string too long (limit is 127 for unicode strings)");
}
} else {
if(field_4_header.length() > 255) {
throw new IllegalArgumentException("Header string too long (limit is 255 for non-unicode strings)");
}
}
}
/**
* get the length of the header string
*
* @return length of the header string
* @see #getHeader()
*/
public short getHeaderLength()
{
return (short)(0xFF & field_1_header_len); // [Shawn] Fixed needing unsigned byte
public void setHeader(String header) {
setText(header);
}
/**
* get the header string
*
* @return header string to display
* @see #getHeaderLength()
*/
public String getHeader()
{
return field_4_header;
public String getHeader() {
return getText();
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[HEADER]\n");
buffer.append(" .length = ").append(getHeaderLength())
.append("\n");
buffer.append(" .header = ").append(getHeader())
.append("\n");
buffer.append(" .header = ").append(getText()).append("\n");
buffer.append("[/HEADER]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
int len = 4;
if (getHeaderLength() != 0)
{
len+=3; // [Shawn] Fixed for two null bytes in the length
}
short bytelen = (short)(isMultibyte() ?
getHeaderLength()*2 : getHeaderLength() );
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset,
( short ) ((len - 4) + bytelen));
if (getHeaderLength() > 0)
{
data[ 4 + offset ] = (byte)getHeaderLength();
data[ 6 + offset ] = field_3_unicode_flag;
if(isMultibyte())
{
StringUtil.putUnicodeLE(getHeader(), data, 7 + offset);
}
else
{
StringUtil.putCompressedUnicode(getHeader(), data, 7 + offset); // [Shawn] Place the string in the correct offset
}
}
return getRecordSize();
}
protected int getDataSize() {
int retval = 0;
if (getHeaderLength() != 0) {
retval+=3; // [Shawn] Fixed for two null bytes in the length
}
return retval + getHeaderLength() * (isMultibyte() ? 2 : 1);
}
public short getSid()
{
public short getSid() {
return sid;
}
public Object clone() {
HeaderRecord rec = new HeaderRecord();
rec.field_1_header_len = field_1_header_len;
rec.field_2_reserved = field_2_reserved;
rec.field_3_unicode_flag = field_3_unicode_flag;
rec.field_4_header = field_4_header;
return rec;
return new HeaderRecord(getText());
}
}

View File

@ -18,25 +18,23 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.IntList;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Index Record<P>
* Title: Index Record (0x020B)<p/>
* Description: Occurs right after BOF, tells you where the DBCELL records are for a sheet
* Important for locating cells<P>
* Important for locating cells<p/>
* NOT USED IN THIS RELEASE
* REFERENCE: PG 323 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* REFERENCE: PG 323 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p/>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class IndexRecord extends Record {
public final static short sid = 0x020B;
public final static int DBCELL_CAPACITY = 30;
public int field_1_zero; // reserved must be 0
public int field_2_first_row; // first row on the sheet
public int field_3_last_row_add1; // last row
public int field_4_zero; // reserved must be 0
public IntList field_5_dbcells; // array of offsets to DBCELL records
public class IndexRecord extends StandardRecord {
public final static short sid = 0x020B;
private int field_2_first_row; // first row on the sheet
private int field_3_last_row_add1; // last row
private int field_4_zero; // supposed to be zero
private IntList field_5_dbcells; // array of offsets to DBCELL records
public IndexRecord()
{
@ -44,16 +42,17 @@ public class IndexRecord extends Record {
public IndexRecord(RecordInputStream in)
{
field_5_dbcells =
new IntList(DBCELL_CAPACITY); // initial capacity of 30
field_1_zero = in.readInt();
int field_1_zero = in.readInt();
if (field_1_zero != 0) {
throw new RecordFormatException("Expected zero for field 1 but got " + field_1_zero);
}
field_2_first_row = in.readInt();
field_3_last_row_add1 = in.readInt();
field_4_zero = in.readInt();
while(in.remaining() > 0)
{
// System.out.println("getting " + k);
field_4_zero = in.readInt();
int nCells = in.remaining() / 4;
field_5_dbcells = new IntList(nCells);
for(int i=0; i<nCells; i++) {
field_5_dbcells.add(in.readInt());
}
}
@ -115,50 +114,43 @@ public class IndexRecord extends Record {
.append(Integer.toHexString(getFirstRow())).append("\n");
buffer.append(" .lastrowadd1 = ")
.append(Integer.toHexString(getLastRowAdd1())).append("\n");
for (int k = 0; k < getNumDbcells(); k++)
{
buffer.append(" .dbcell_" + k + " = ")
for (int k = 0; k < getNumDbcells(); k++) {
buffer.append(" .dbcell_").append(k).append(" = ")
.append(Integer.toHexString(getDbcellAt(k))).append("\n");
}
buffer.append("[/INDEX]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset,
( short ) (16 + (getNumDbcells() * 4)));
LittleEndian.putInt(data, 4 + offset, 0);
LittleEndian.putInt(data, 8 + offset, getFirstRow());
LittleEndian.putInt(data, 12 + offset, getLastRowAdd1());
LittleEndian.putInt(data, 16 + offset, 0);
for (int k = 0; k < getNumDbcells(); k++)
{
LittleEndian.putInt(data, (k * 4) + 20 + offset, getDbcellAt(k));
public void serialize(LittleEndianOutput out) {
out.writeInt(0);
out.writeInt(getFirstRow());
out.writeInt(getLastRowAdd1());
out.writeInt(field_4_zero);
for (int k = 0; k < getNumDbcells(); k++) {
out.writeInt(getDbcellAt(k));
}
return getRecordSize();
}
protected int getDataSize() {
return 16 + (getNumDbcells() * 4);
return 16 // 4 ints
+ getNumDbcells() * 4;
}
/** Returns the size of an INdexRecord when it needs to index the specified number of blocks
*
*/
public static int getRecordSizeForBlockCount(int blockCount) {
return 20 + (4 * blockCount);
}
/**
* @return the size of an INdexRecord when it needs to index the specified number of blocks
*/
public static int getRecordSizeForBlockCount(int blockCount) {
return 20 + 4 * blockCount;
}
public short getSid()
{
public short getSid() {
return sid;
}
public Object clone() {
IndexRecord rec = new IndexRecord();
rec.field_1_zero = field_1_zero;
rec.field_2_first_row = field_2_first_row;
rec.field_3_last_row_add1 = field_3_last_row_add1;
rec.field_4_zero = field_4_zero;

View File

@ -1,91 +0,0 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.util.LittleEndian;
/**
* Not implemented yet. May commit it anyway just so people can see
* where I'm heading.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class LinkedDataFormulaField {
private Ptg[] formulaTokens;
public int getSize()
{
return 2 + Ptg.getEncodedSize(formulaTokens);
}
public int fillField( RecordInputStream in )
{
int tokenSize = in.readUShort();
formulaTokens = Ptg.readTokens(tokenSize, in);
return tokenSize + 2;
}
public void toString( StringBuffer buffer )
{
for ( int k = 0; k < formulaTokens.length; k++ )
{
Ptg ptg = formulaTokens[k];
buffer.append( "Formula " )
.append( k )
.append( "=" )
.append(ptg.toString() )
.append( "\n" )
.append(ptg.toString())
.append( "\n" );
}
}
public String toString()
{
StringBuffer b = new StringBuffer();
toString( b );
return b.toString();
}
public int serializeField( int offset, byte[] data )
{
int size = getSize();
LittleEndian.putUShort(data, offset, size - 2);
int pos = offset + 2;
pos += Ptg.serializePtgs(formulaTokens, data, pos);
return size;
}
public void setFormulaTokens(Ptg[] ptgs)
{
this.formulaTokens = (Ptg[])ptgs.clone();
}
public Ptg[] getFormulaTokens()
{
return (Ptg[])this.formulaTokens.clone();
}
public LinkedDataFormulaField copy() {
LinkedDataFormulaField result = new LinkedDataFormulaField();
result.formulaTokens = getFormulaTokens();
return result;
}
}

View File

@ -17,17 +17,19 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Describes a linked data record. This record referes to the series data or text.<p/>
* Describes a linked data record. This record refers to the series data or text.<p/>
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class LinkedDataRecord extends Record {
public final class LinkedDataRecord extends StandardRecord {
public final static short sid = 0x1051;
private static final BitField customNumberFormat= BitFieldFactory.getInstance(0x1);
@ -44,7 +46,7 @@ public final class LinkedDataRecord extends Record {
public final static byte REFERENCE_TYPE_ERROR_REPORTED = 4;
private short field_3_options;
private short field_4_indexNumberFmtRecord;
private LinkedDataFormulaField field_5_formulaOfLink;
private Formula field_5_formulaOfLink;
public LinkedDataRecord()
@ -58,8 +60,8 @@ public final class LinkedDataRecord extends Record {
field_2_referenceType = in.readByte();
field_3_options = in.readShort();
field_4_indexNumberFmtRecord = in.readShort();
field_5_formulaOfLink = new LinkedDataFormulaField();
field_5_formulaOfLink.fillField(in);
int encodedTokenLen = in.readUShort();
field_5_formulaOfLink = Formula.read(encodedTokenLen, in);
}
public String toString()
@ -92,28 +94,19 @@ public final class LinkedDataRecord extends Record {
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
data[ 4 + offset + pos ] = field_1_linkType;
data[ 5 + offset + pos ] = field_2_referenceType;
LittleEndian.putShort(data, 6 + offset + pos, field_3_options);
LittleEndian.putShort(data, 8 + offset + pos, field_4_indexNumberFmtRecord);
pos += field_5_formulaOfLink.serializeField( pos + 10 + offset, data );
return getRecordSize();
public void serialize(LittleEndianOutput out) {
out.writeByte(field_1_linkType);
out.writeByte(field_2_referenceType);
out.writeShort(field_3_options);
out.writeShort(field_4_indexNumberFmtRecord);
field_5_formulaOfLink.serialize(out);
}
protected int getDataSize() {
return 1 + 1 + 2 + 2 + field_5_formulaOfLink.getSize();
return 1 + 1 + 2 + 2 + field_5_formulaOfLink.getEncodedSize();
}
public short getSid()
{
public short getSid() {
return sid;
}
@ -224,17 +217,16 @@ public final class LinkedDataRecord extends Record {
/**
* Get the formula of link field for the LinkedData record.
*/
public LinkedDataFormulaField getFormulaOfLink()
{
return field_5_formulaOfLink;
public Ptg[] getFormulaOfLink() {
return field_5_formulaOfLink.getTokens();
}
/**
* Set the formula of link field for the LinkedData record.
*/
public void setFormulaOfLink(LinkedDataFormulaField field_5_formulaOfLink)
public void setFormulaOfLink(Ptg[] ptgs)
{
this.field_5_formulaOfLink = field_5_formulaOfLink;
this.field_5_formulaOfLink = Formula.create(ptgs);
}
/**

View File

@ -19,18 +19,15 @@ package org.apache.poi.hssf.record;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Merged Cells Record (0x00E5)
* <br/>
* Description: Optional record defining a square area of cells to "merged" into
* one cell. <br>
* REFERENCE: NONE (UNDOCUMENTED PRESENTLY) <br>
* Description: Optional record defining a square area of cells to "merged" into one cell. <br>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
*/
public final class MergeCellsRecord extends Record {
public final class MergeCellsRecord extends StandardRecord {
public final static short sid = 0x00E5;
/** sometimes the regions array is shared with other MergedCellsRecords */
private CellRangeAddress[] _regions;
@ -80,37 +77,26 @@ public final class MergeCellsRecord extends Record {
return sid;
}
public int serialize(int offset, byte [] data) {
int dataSize = CellRangeAddressList.getEncodedSize(_numberOfRegions);
LittleEndian.putUShort(data, offset + 0, sid);
LittleEndian.putUShort(data, offset + 2, dataSize);
public void serialize(LittleEndianOutput out) {
int nItems = _numberOfRegions;
LittleEndian.putUShort(data, offset + 4, nItems);
int pos = 6;
out.writeShort(nItems);
for (int i = 0; i < _numberOfRegions; i++) {
pos += _regions[_startIndex + i].serialize(offset+pos, data);
_regions[_startIndex + i].serialize(out);
}
return 4 + dataSize;
}
public String toString() {
StringBuffer retval = new StringBuffer();
retval.append("[MERGEDCELLS]").append("\n");
retval.append(" .numregions =").append(getNumAreas())
.append("\n");
retval.append(" .numregions =").append(getNumAreas()).append("\n");
for (int k = 0; k < _numberOfRegions; k++) {
CellRangeAddress region = _regions[_startIndex + k];
CellRangeAddress r = _regions[_startIndex + k];
retval.append(" .rowfrom =").append(region.getFirstRow())
.append("\n");
retval.append(" .rowto =").append(region.getLastRow())
.append("\n");
retval.append(" .colfrom =").append(region.getFirstColumn())
.append("\n");
retval.append(" .colto =").append(region.getLastColumn())
.append("\n");
retval.append(" .rowfrom =").append(r.getFirstRow()).append("\n");
retval.append(" .rowto =").append(r.getLastRow()).append("\n");
retval.append(" .colfrom =").append(r.getFirstColumn()).append("\n");
retval.append(" .colto =").append(r.getLastColumn()).append("\n");
}
retval.append("[MERGEDCELLS]").append("\n");
return retval.toString();

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Multiple Blank cell record(0x00BE) <P/>
* Description: Represents a set of columns in a row with no value but with styling.
@ -27,7 +29,7 @@ package org.apache.poi.hssf.record;
* @author Glen Stampoultzis (glens at apache.org)
* @see BlankRecord
*/
public final class MulBlankRecord extends Record {
public final class MulBlankRecord extends StandardRecord {
public final static short sid = 0x00BE;
private int field_1_row;
@ -124,7 +126,7 @@ public final class MulBlankRecord extends Record {
return sid;
}
public int serialize(int offset, byte [] data) {
public void serialize(LittleEndianOutput out) {
throw new RecordFormatException( "Sorry, you can't serialize MulBlank in this release");
}
protected int getDataSize() {

View File

@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
import org.apache.poi.hssf.util.RKUtil;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
/**
* MULRK (0x00BD) <p/>
@ -29,7 +30,7 @@ import org.apache.poi.util.HexDump;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
*/
public final class MulRKRecord extends Record {
public final class MulRKRecord extends StandardRecord {
public final static short sid = 0x00BD;
private int field_1_row;
@ -113,7 +114,7 @@ public final class MulRKRecord extends Record {
return sid;
}
public int serialize(int offset, byte [] data) {
public void serialize(LittleEndianOutput out) {
throw new RecordFormatException( "Sorry, you can't serialize MulRK in this release");
}
protected int getDataSize() {

View File

@ -23,7 +23,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* <p>Record that contains the functionality page breaks (horizontal and vertical)</p>
@ -36,11 +36,11 @@ import org.apache.poi.util.LittleEndian;
* @see VerticalPageBreakRecord
* @author Danny Mui (dmui at apache dot org)
*/
public abstract class PageBreakRecord extends Record {
public abstract class PageBreakRecord extends StandardRecord {
private static final int[] EMPTY_INT_ARRAY = { };
private List _breaks;
private Map _breakMap;
private List<Break> _breaks;
private Map<Integer, Break> _breakMap;
/**
* Since both records store 2byte integers (short), no point in
@ -49,7 +49,7 @@ public abstract class PageBreakRecord extends Record {
* The subs (rows or columns, don't seem to be able to set but excel sets
* them automatically)
*/
public class Break {
public static final class Break {
public static final int ENCODED_SIZE = 6;
public int main;
@ -69,24 +69,23 @@ public abstract class PageBreakRecord extends Record {
subTo = in.readUShort();
}
public int serialize(int offset, byte[] data) {
LittleEndian.putUShort(data, offset + 0, main + 1);
LittleEndian.putUShort(data, offset + 2, subFrom);
LittleEndian.putUShort(data, offset + 4, subTo);
return ENCODED_SIZE;
public void serialize(LittleEndianOutput out) {
out.writeShort(main + 1);
out.writeShort(subFrom);
out.writeShort(subTo);
}
}
protected PageBreakRecord() {
_breaks = new ArrayList();
_breakMap = new HashMap();
_breaks = new ArrayList<Break>();
_breakMap = new HashMap<Integer, Break>();
}
public PageBreakRecord(RecordInputStream in)
{
int nBreaks = in.readShort();
_breaks = new ArrayList(nBreaks + 2);
_breakMap = new HashMap();
_breaks = new ArrayList<Break>(nBreaks + 2);
_breakMap = new HashMap<Integer, Break>();
for(int k = 0; k < nBreaks; k++) {
Break br = new Break(in);
@ -103,34 +102,25 @@ public abstract class PageBreakRecord extends Record {
return 2 + _breaks.size() * Break.ENCODED_SIZE;
}
public final int serialize(int offset, byte data[]) {
public final void serialize(LittleEndianOutput out) {
int nBreaks = _breaks.size();
int dataSize = getDataSize();
LittleEndian.putUShort(data, offset + 0, getSid());
LittleEndian.putUShort(data, offset + 2, dataSize);
LittleEndian.putUShort(data, offset + 4, nBreaks);
int pos = 6;
out.writeShort(nBreaks);
for (int i=0; i<nBreaks; i++) {
Break br = (Break)_breaks.get(i);
pos += br.serialize(offset+pos, data);
_breaks.get(i).serialize(out);
}
return 4 + dataSize;
}
public int getNumBreaks() {
return _breaks.size();
}
public final Iterator getBreaksIterator() {
public final Iterator<Break> getBreaksIterator() {
return _breaks.iterator();
}
public String toString()
{
public String toString() {
StringBuffer retval = new StringBuffer();
String label;
String mainLabel;
String subLabel;
@ -148,10 +138,10 @@ public abstract class PageBreakRecord extends Record {
retval.append("["+label+"]").append("\n");
retval.append(" .sid =").append(getSid()).append("\n");
retval.append(" .numbreaks =").append(getNumBreaks()).append("\n");
Iterator iterator = getBreaksIterator();
Iterator<Break> iterator = getBreaksIterator();
for(int k = 0; k < getNumBreaks(); k++)
{
Break region = (Break)iterator.next();
Break region = iterator.next();
retval.append(" .").append(mainLabel).append(" (zero-based) =").append(region.main).append("\n");
retval.append(" .").append(subLabel).append("From =").append(region.subFrom).append("\n");
@ -171,7 +161,7 @@ public abstract class PageBreakRecord extends Record {
public void addBreak(int main, int subFrom, int subTo) {
Integer key = new Integer(main);
Break region = (Break)_breakMap.get(key);
Break region = _breakMap.get(key);
if(region == null) {
region = new Break(main, subFrom, subTo);
_breakMap.put(key, region);
@ -189,7 +179,7 @@ public abstract class PageBreakRecord extends Record {
*/
public final void removeBreak(int main) {
Integer rowKey = new Integer(main);
Break region = (Break)_breakMap.get(rowKey);
Break region = _breakMap.get(rowKey);
_breaks.remove(region);
_breakMap.remove(rowKey);
}
@ -201,7 +191,7 @@ public abstract class PageBreakRecord extends Record {
*/
public final Break getBreak(int main) {
Integer rowKey = new Integer(main);
return (Break)_breakMap.get(rowKey);
return _breakMap.get(rowKey);
}
public final int[] getBreaks() {
@ -211,7 +201,7 @@ public abstract class PageBreakRecord extends Record {
}
int[] result = new int[count];
for (int i=0; i<count; i++) {
Break breakItem = (Break)_breaks.get(i);
Break breakItem = _breaks.get(i);
result[i] = breakItem.main;
}
return result;

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -15,52 +14,44 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* PaletteRecord - Supports custom palettes.
* PaletteRecord (0x0092) - Supports custom palettes.
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Brian Sanders (bsanders at risklabs dot com) - custom palette editing
* @version 2.0-pre
*
*/
public class PaletteRecord
extends Record
{
public final static short sid = 0x92;
public final class PaletteRecord extends StandardRecord {
public final static short sid = 0x0092;
/** The standard size of an XLS palette */
public final static byte STANDARD_PALETTE_SIZE = (byte) 56;
/** The byte index of the first color */
public final static short FIRST_COLOR_INDEX = (short) 0x8;
private short field_1_numcolors;
private List field_2_colors;
private List<PColor> field_2_colors;
public PaletteRecord()
{
createDefaultPalette();
PColor[] defaultPalette = createDefaultPalette();
field_2_colors = new ArrayList<PColor>(defaultPalette.length);
for (int i = 0; i < defaultPalette.length; i++) {
field_2_colors.add(defaultPalette[i]);
}
}
public PaletteRecord(RecordInputStream in)
{
field_1_numcolors = in.readShort();
field_2_colors = new ArrayList(field_1_numcolors);
int field_1_numcolors = in.readShort();
field_2_colors = new ArrayList<PColor>(field_1_numcolors);
for (int k = 0; k < field_1_numcolors; k++) {
field_2_colors.add(new PColor(
in.readByte(),
in.readByte(),
in.readByte()
)
);
//Read unused byte.
in.readByte();
field_2_colors.add(new PColor(in));
}
}
@ -69,35 +60,27 @@ public class PaletteRecord
StringBuffer buffer = new StringBuffer();
buffer.append("[PALETTE]\n");
buffer.append(" numcolors = ").append(field_1_numcolors)
.append('\n');
for (int k = 0; k < field_1_numcolors; k++) {
PColor c = (PColor) field_2_colors.get(k);
buffer.append("* colornum = ").append(k)
.append('\n');
buffer.append(c.toString());
buffer.append("/*colornum = ").append(k)
.append('\n');
buffer.append(" numcolors = ").append(field_2_colors.size()).append('\n');
for (int i = 0; i < field_2_colors.size(); i++) {
PColor c = field_2_colors.get(i);
buffer.append("* colornum = ").append(i).append('\n');
buffer.append(c.toString());
buffer.append("/*colornum = ").append(i).append('\n');
}
buffer.append("[/PALETTE]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
public void serialize(LittleEndianOutput out)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short) (getRecordSize() - 4));
LittleEndian.putShort(data, 4 + offset, field_1_numcolors);
for (int k = 0; k < field_1_numcolors; k++) {
PColor c = (PColor)field_2_colors.get(k);
c.serialize(data, (6+offset+(k*4)));
out.writeShort(field_2_colors.size());
for (int i = 0; i < field_2_colors.size(); i++) {
field_2_colors.get(i).serialize(out);
}
return getRecordSize();
}
protected int getDataSize() {
return 2 + (field_1_numcolors * 4);
return 2 + field_2_colors.size() * PColor.ENCODED_SIZE;
}
public short getSid()
@ -108,17 +91,16 @@ public class PaletteRecord
/**
* Returns the color value at a given index
*
* @return the RGB triplet for the color, or null if the specified index
* @return the RGB triplet for the color, or <code>null</code> if the specified index
* does not exist
*/
public byte[] getColor(short byteIndex)
{
public byte[] getColor(short byteIndex) {
int i = byteIndex - FIRST_COLOR_INDEX;
if (i < 0 || i >= field_2_colors.size())
{
return null;
}
PColor color = (PColor) field_2_colors.get(i);
PColor color = field_2_colors.get(i);
return new byte[] { color.red, color.green, color.blue };
}
@ -138,9 +120,9 @@ public class PaletteRecord
{
return;
}
while (field_2_colors.size() <= i)
{
field_2_colors.add(new PColor((byte) 0, (byte) 0, (byte) 0));
// may need to grow - fill intervening pallette entries with black
while (field_2_colors.size() <= i) {
field_2_colors.add(new PColor(0, 0, 0));
}
PColor custColor = new PColor(red, green, blue);
field_2_colors.set(i, custColor);
@ -151,100 +133,99 @@ public class PaletteRecord
*
* @see org.apache.poi.hssf.model.Workbook#createPalette
*/
private void createDefaultPalette()
private static PColor[] createDefaultPalette()
{
field_1_numcolors = STANDARD_PALETTE_SIZE;
field_2_colors = new ArrayList(field_1_numcolors);
byte[] palette = new byte[]
{
(byte) 0, (byte) 0, (byte) 0, (byte) 0, //color 0...
(byte) 255, (byte) 255, (byte) 255, (byte) 0,
(byte) 255, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 255, (byte) 0, (byte) 0,
(byte) 0, (byte) 0, (byte) 255, (byte) 0,
(byte) 255, (byte) 255, (byte) 0, (byte) 0,
(byte) 255, (byte) 0, (byte) 255, (byte) 0,
(byte) 0, (byte) 255, (byte) 255, (byte) 0,
(byte) 128, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 128, (byte) 0, (byte) 0,
(byte) 0, (byte) 0, (byte) 128, (byte) 0,
(byte) 128, (byte) 128, (byte) 0, (byte) 0,
(byte) 128, (byte) 0, (byte) 128, (byte) 0,
(byte) 0, (byte) 128, (byte) 128, (byte) 0,
(byte) 192, (byte) 192, (byte) 192, (byte) 0,
(byte) 128, (byte) 128, (byte) 128, (byte) 0,
(byte) 153, (byte) 153, (byte) 255, (byte) 0,
(byte) 153, (byte) 51, (byte) 102, (byte) 0,
(byte) 255, (byte) 255, (byte) 204, (byte) 0,
(byte) 204, (byte) 255, (byte) 255, (byte) 0,
(byte) 102, (byte) 0, (byte) 102, (byte) 0,
(byte) 255, (byte) 128, (byte) 128, (byte) 0,
(byte) 0, (byte) 102, (byte) 204, (byte) 0,
(byte) 204, (byte) 204, (byte) 255, (byte) 0,
(byte) 0, (byte) 0, (byte) 128, (byte) 0,
(byte) 255, (byte) 0, (byte) 255, (byte) 0,
(byte) 255, (byte) 255, (byte) 0, (byte) 0,
(byte) 0, (byte) 255, (byte) 255, (byte) 0,
(byte) 128, (byte) 0, (byte) 128, (byte) 0,
(byte) 128, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 128, (byte) 128, (byte) 0,
(byte) 0, (byte) 0, (byte) 255, (byte) 0,
(byte) 0, (byte) 204, (byte) 255, (byte) 0,
(byte) 204, (byte) 255, (byte) 255, (byte) 0,
(byte) 204, (byte) 255, (byte) 204, (byte) 0,
(byte) 255, (byte) 255, (byte) 153, (byte) 0,
(byte) 153, (byte) 204, (byte) 255, (byte) 0,
(byte) 255, (byte) 153, (byte) 204, (byte) 0,
(byte) 204, (byte) 153, (byte) 255, (byte) 0,
(byte) 255, (byte) 204, (byte) 153, (byte) 0,
(byte) 51, (byte) 102, (byte) 255, (byte) 0,
(byte) 51, (byte) 204, (byte) 204, (byte) 0,
(byte) 153, (byte) 204, (byte) 0, (byte) 0,
(byte) 255, (byte) 204, (byte) 0, (byte) 0,
(byte) 255, (byte) 153, (byte) 0, (byte) 0,
(byte) 255, (byte) 102, (byte) 0, (byte) 0,
(byte) 102, (byte) 102, (byte) 153, (byte) 0,
(byte) 150, (byte) 150, (byte) 150, (byte) 0,
(byte) 0, (byte) 51, (byte) 102, (byte) 0,
(byte) 51, (byte) 153, (byte) 102, (byte) 0,
(byte) 0, (byte) 51, (byte) 0, (byte) 0,
(byte) 51, (byte) 51, (byte) 0, (byte) 0,
(byte) 153, (byte) 51, (byte) 0, (byte) 0,
(byte) 153, (byte) 51, (byte) 102, (byte) 0,
(byte) 51, (byte) 51, (byte) 153, (byte) 0,
(byte) 51, (byte) 51, (byte) 51, (byte) 0
return new PColor[] {
pc(0, 0, 0),
pc(255, 255, 255),
pc(255, 0, 0),
pc(0, 255, 0),
pc(0, 0, 255),
pc(255, 255, 0),
pc(255, 0, 255),
pc(0, 255, 255),
pc(128, 0, 0),
pc(0, 128, 0),
pc(0, 0, 128),
pc(128, 128, 0),
pc(128, 0, 128),
pc(0, 128, 128),
pc(192, 192, 192),
pc(128, 128, 128),
pc(153, 153, 255),
pc(153, 51, 102),
pc(255, 255, 204),
pc(204, 255, 255),
pc(102, 0, 102),
pc(255, 128, 128),
pc(0, 102, 204),
pc(204, 204, 255),
pc(0, 0, 128),
pc(255, 0, 255),
pc(255, 255, 0),
pc(0, 255, 255),
pc(128, 0, 128),
pc(128, 0, 0),
pc(0, 128, 128),
pc(0, 0, 255),
pc(0, 204, 255),
pc(204, 255, 255),
pc(204, 255, 204),
pc(255, 255, 153),
pc(153, 204, 255),
pc(255, 153, 204),
pc(204, 153, 255),
pc(255, 204, 153),
pc(51, 102, 255),
pc(51, 204, 204),
pc(153, 204, 0),
pc(255, 204, 0),
pc(255, 153, 0),
pc(255, 102, 0),
pc(102, 102, 153),
pc(150, 150, 150),
pc(0, 51, 102),
pc(51, 153, 102),
pc(0, 51, 0),
pc(51, 51, 0),
pc(153, 51, 0),
pc(153, 51, 102),
pc(51, 51, 153),
pc(51, 51, 51),
};
for (int k = 0; k < field_1_numcolors; k++) {
field_2_colors.add(new PColor(
palette[k*4],
palette[k*4+1],
palette[k*4+2]
)
);
}
}
}
private static PColor pc(int r, int g, int b) {
return new PColor(r, g, b);
}
/**
* PColor - element in the list of colors - consider it a "struct"
*/
class PColor {
private static final class PColor {
public static final short ENCODED_SIZE = 4;
public byte red;
public byte green;
public byte blue;
public PColor(byte red, byte green, byte blue) {
this.red=red;
this.green=green;
this.blue=blue;
public PColor(int red, int green, int blue) {
this.red=(byte) red;
this.green=(byte) green;
this.blue=(byte) blue;
}
public void serialize(byte[] data, int offset) {
data[offset + 0] = red;
data[offset + 1] = green;
data[offset + 2] = blue;
data[offset + 3] = 0;
public PColor(RecordInputStream in) {
red=in.readByte();
green=in.readByte();
blue=in.readByte();
in.readByte(); // unused
}
public void serialize(LittleEndianOutput out) {
out.writeByte(red);
out.writeByte(green);
out.writeByte(blue);
out.writeByte(0);
}
public String toString() {
@ -255,3 +236,4 @@ class PColor {
return buffer.toString();
}
}
}

View File

@ -19,15 +19,16 @@ package org.apache.poi.hssf.record;
import org.apache.poi.hssf.util.RKUtil;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: RK Record (0x027E)
* Title: RK Record (0x027E)<p/>
* Description: An internal 32 bit number with the two most significant bits
* storing the type. This is part of a bizarre scheme to save disk
* space and memory (gee look at all the other whole records that
* are in the file just "cause"..,far better to waste processor
* cycles on this then leave on of those "valuable" records out).<P>
* We support this in READ-ONLY mode. HSSF converts these to NUMBER records<P>
* cycles on this then leave on of those "valuable" records out).<p/>
* We support this in READ-ONLY mode. HSSF converts these to NUMBER records<p/>
*
*
*
@ -36,7 +37,7 @@ import org.apache.poi.util.HexDump;
* @author Jason Height (jheight at chariot dot net dot au)
* @see org.apache.poi.hssf.record.NumberRecord
*/
public final class RKRecord extends Record implements CellValueRecordInterface {
public final class RKRecord extends StandardRecord implements CellValueRecordInterface {
public final static short sid = 0x027E;
public final static short RK_IEEE_NUMBER = 0;
public final static short RK_IEEE_NUMBER_TIMES_100 = 1;
@ -47,7 +48,7 @@ public final class RKRecord extends Record implements CellValueRecordInterface {
private int field_3_xf_index;
private int field_4_rk_number;
public RKRecord()
private RKRecord()
{
}
@ -133,7 +134,7 @@ public final class RKRecord extends Record implements CellValueRecordInterface {
return sb.toString();
}
public int serialize(int offset, byte [] data) {
public void serialize(LittleEndianOutput out) {
throw new RecordFormatException( "Sorry, you can't serialize RK in this release");
}
protected int getDataSize() {

View File

@ -17,10 +17,11 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Recalc Id Record<P>
* Title: Recalc Id Record (0x01C1)<p/>
* Description: This record contains an ID that marks when a worksheet was last
* recalculated. It's an optimization Excel uses to determine if it
* needs to recalculate the spreadsheet when it's opened. So far, only
@ -28,100 +29,51 @@ import org.apache.poi.util.LittleEndian;
* (do not recalculate) and <code>0xC1 0x01 0x00 0x00 0x60 0x69 0x01
* 0x00</code> have been seen. If the field <code>isNeeded</code> is
* set to false (default), then this record is swallowed during the
* serialization process<P>
* REFERENCE: http://chicago.sourceforge.net/devel/docs/excel/biff8.html<P>
* serialization process<p/>
* REFERENCE: http://chicago.sourceforge.net/devel/docs/excel/biff8.html<p/>
* @author Luc Girardin (luc dot girardin at macrofocus dot com)
* @version 2.0-pre
*
* @see org.apache.poi.hssf.model.Workbook
*/
public final class RecalcIdRecord extends StandardRecord {
public final static short sid = 0x01C1;
private final int _reserved0;
private final int _engineId;
public final class RecalcIdRecord extends Record {
public final static short sid = 0x1c1;
public short[] field_1_recalcids;
private boolean isNeeded = true;
public RecalcIdRecord()
{
}
public RecalcIdRecord(RecordInputStream in)
{
field_1_recalcids = new short[ in.remaining() / 2 ];
for (int k = 0; k < field_1_recalcids.length; k++)
{
field_1_recalcids[ k ] = in.readShort();
}
}
/**
* set the recalc array.
* @param array of recalc id's
*/
public void setRecalcIdArray(short [] array)
{
field_1_recalcids = array;
}
/**
* get the recalc array.
* @return array of recalc id's
*/
public short [] getRecalcIdArray()
{
return field_1_recalcids;
}
public void setIsNeeded(boolean isNeeded) {
this.isNeeded = isNeeded;
public RecalcIdRecord(RecordInputStream in) {
int rt = in.readUShort();
if (rt != sid) {
throw new RecordFormatException("expected " + sid + " but got " + rt);
}
_reserved0 = in.readUShort();
_engineId = in.readInt();
}
public boolean isNeeded() {
return isNeeded;
return true;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[RECALCID]\n");
buffer.append(" .elements = ").append(field_1_recalcids.length)
.append("\n");
for (int k = 0; k < field_1_recalcids.length; k++)
{
buffer.append(" .element_" + k + " = ")
.append(field_1_recalcids[ k ]).append("\n");
}
buffer.append(" .reserved = ").append(HexDump.shortToHex(_reserved0));
buffer.append(" .engineId = ").append(HexDump.intToHex(_engineId));
buffer.append("[/RECALCID]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
short[] tabids = getRecalcIdArray();
short length = ( short ) (tabids.length * 2);
int byteoffset = 4;
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, length);
// 2 (num bytes in a short)
for (int k = 0; k < (length / 2); k++)
{
LittleEndian.putShort(data, byteoffset + offset, tabids[ k ]);
byteoffset += 2;
}
return getRecordSize();
public void serialize(LittleEndianOutput out) {
out.writeShort(sid);
out.writeShort(_reserved0);
out.writeInt(_engineId);
}
protected int getDataSize() {
return (getRecalcIdArray().length * 2);
return 8;
}
public short getSid()
{
public short getSid() {
return sid;
}
}

View File

@ -18,7 +18,9 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Selection Record (0x001D)<P>
@ -30,7 +32,7 @@ import org.apache.poi.util.LittleEndian;
* @author Jason Height (jheight at chariot dot net dot au)
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class SelectionRecord extends Record {
public final class SelectionRecord extends StandardRecord {
public final static short sid = 0x001D;
private byte field_1_pane;
private int field_2_row_active_cell;
@ -123,45 +125,35 @@ public final class SelectionRecord extends Record {
* @return ref number of active cell
*/
public int getActiveCellRef() {
return (short)field_4_active_cell_ref_index;
return field_4_active_cell_ref_index;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
StringBuffer sb = new StringBuffer();
buffer.append("[SELECTION]\n");
buffer.append(" .pane = ")
.append(Integer.toHexString(getPane())).append("\n");
buffer.append(" .activecellrow = ")
.append(Integer.toHexString(getActiveCellRow())).append("\n");
buffer.append(" .activecellcol = ")
.append(Integer.toHexString(getActiveCellCol())).append("\n");
buffer.append(" .activecellref = ")
.append(Integer.toHexString(getActiveCellRef())).append("\n");
buffer.append(" .numrefs = ")
.append(Integer.toHexString(field_6_refs.length)).append("\n");
buffer.append("[/SELECTION]\n");
return buffer.toString();
sb.append("[SELECTION]\n");
sb.append(" .pane = ").append(HexDump.byteToHex(getPane())).append("\n");
sb.append(" .activecellrow = ").append(HexDump.shortToHex(getActiveCellRow())).append("\n");
sb.append(" .activecellcol = ").append(HexDump.shortToHex(getActiveCellCol())).append("\n");
sb.append(" .activecellref = ").append(HexDump.shortToHex(getActiveCellRef())).append("\n");
sb.append(" .numrefs = ").append(HexDump.shortToHex(field_6_refs.length)).append("\n");
sb.append("[/SELECTION]\n");
return sb.toString();
}
protected int getDataSize() {
return 9 // 1 byte + 4 shorts
+ CellRangeAddress8Bit.getEncodedSize(field_6_refs.length);
}
public int serialize(int offset, byte [] data) {
int dataSize = getDataSize();
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putByte(data, 4 + offset, getPane());
LittleEndian.putUShort(data, 5 + offset, getActiveCellRow());
LittleEndian.putUShort(data, 7 + offset, getActiveCellCol());
LittleEndian.putUShort(data, 9 + offset, getActiveCellRef());
public void serialize(LittleEndianOutput out) {
out.writeByte(getPane());
out.writeShort(getActiveCellRow());
out.writeShort(getActiveCellCol());
out.writeShort(getActiveCellRef());
int nRefs = field_6_refs.length;
LittleEndian.putUShort(data, 11 + offset, nRefs);
out.writeShort(nRefs);
for (int i = 0; i < field_6_refs.length; i++) {
CellRangeAddress8Bit r = field_6_refs[i];
r.serialize(offset + 13 + i * CellRangeAddress8Bit.ENCODED_SIZE, data);
field_6_refs[i].serialize(out);
}
return 4 + dataSize;
}
public short getSid() {

View File

@ -17,16 +17,19 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* SERIESLIST (0x1016)
*
* The series list record defines the series displayed as an overlay to the main chart record.<br/>
* TODO - does this record (0x1016) really exist. It doesn't seem to be referenced in either the OOO or MS doc
* This record doesn't seem to be referenced in either the OOO or MS doc, but this page mentions it
* http://ooxmlisdefectivebydesign.blogspot.com/2008/03/bad-surprise-in-microsoft-office-binary.html
*
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class SeriesListRecord extends Record {
public final class SeriesListRecord extends StandardRecord {
public final static short sid = 0x1016;
private short[] field_1_seriesNumbers;
@ -55,23 +58,13 @@ public final class SeriesListRecord extends Record {
return buffer.toString();
}
public int serialize(int offset, byte[] data) {
public void serialize(LittleEndianOutput out) {
int nItems = field_1_seriesNumbers.length;
int dataSize = 2 + 2 * nItems;
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, nItems);
int pos = offset + 6;
out.writeShort(nItems);
for (int i = 0; i < nItems; i++) {
LittleEndian.putUShort(data, pos, field_1_seriesNumbers[i]);
pos += 2;
out.writeShort(field_1_seriesNumbers[i]);
}
return 4 + dataSize;
}
protected int getDataSize() {
@ -84,7 +77,7 @@ public final class SeriesListRecord extends Record {
}
public Object clone() {
return new SeriesListRecord((short[]) field_1_seriesNumbers.clone());
return new SeriesListRecord(field_1_seriesNumbers.clone());
}
/**

View File

@ -20,7 +20,7 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
@ -30,11 +30,9 @@ import org.apache.poi.util.StringUtil;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author aviks : string fixes for UserDefined Style
*/
public final class StyleRecord extends Record {
public final class StyleRecord extends StandardRecord {
public final static short sid = 0x0293;
private static final BitField is16BitUnicodeFlag = BitFieldFactory.getInstance(0x01);
private static final BitField styleIndexMask = BitFieldFactory.getInstance(0x0FFF);
private static final BitField isBuiltinFlag = BitFieldFactory.getInstance(0x8000);
@ -46,7 +44,7 @@ public final class StyleRecord extends Record {
private int field_3_outline_style_level;
// only for user defined styles
private int field_3_string_options;
private boolean field_3_stringHasMultibyte;
private String field_4_name;
/**
@ -74,8 +72,8 @@ public final class StyleRecord extends Record {
field_4_name = "";
} else {
int is16BitUnicode = in.readByte();
if (is16BitUnicodeFlag.isSet(is16BitUnicode)) {
field_3_stringHasMultibyte = in.readByte() != 0x00;
if (field_3_stringHasMultibyte) {
field_4_name = StringUtil.readUnicodeLE(in, field_2_name_length);
} else {
field_4_name = StringUtil.readCompressedUnicode(in, field_2_name_length);
@ -107,7 +105,7 @@ public final class StyleRecord extends Record {
*/
public void setName(String name) {
field_4_name = name;
field_3_string_options = StringUtil.hasMultibyte(name) ? 0x01 : 0x00;
field_3_stringHasMultibyte = StringUtil.hasMultibyte(name);
field_1_xf_index = isBuiltinFlag.clear(field_1_xf_index);
}
@ -162,34 +160,24 @@ public final class StyleRecord extends Record {
if (isBuiltin()) {
return 4; // short, byte, byte
}
int size = 2 + 3; // short
if (is16BitUnicodeFlag.isSet(field_3_string_options)) {
size += 2 * field_4_name.length();
} else {
size += field_4_name.length();
}
return size;
return 2 // short xf index
+ 3 // str len + flag
+ field_4_name.length() * (field_3_stringHasMultibyte ? 2 : 1);
}
public int serialize(int offset, byte [] data) {
int dataSize = getDataSize();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, field_1_xf_index);
public void serialize(LittleEndianOutput out) {
out.writeShort(field_1_xf_index);
if (isBuiltin()) {
LittleEndian.putByte(data, 6 + offset, field_2_builtin_style);
LittleEndian.putByte(data, 7 + offset, field_3_outline_style_level);
out.writeByte(field_2_builtin_style);
out.writeByte(field_3_outline_style_level);
} else {
LittleEndian.putUShort(data, 6 + offset, field_4_name.length());
LittleEndian.putByte(data, 8 + offset, field_3_string_options);
StringUtil.putCompressedUnicode(getName(), data, 9 + offset);
out.writeShort(field_4_name.length());
out.writeByte(field_3_stringHasMultibyte ? 0x01 : 0x00);
StringUtil.putCompressedUnicode(getName(), out);
}
return 4+dataSize;
}
public short getSid()
{
public short getSid() {
return sid;
}
}

View File

@ -17,30 +17,31 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Sheet Tab Index Array Record<P>
* Title: Sheet Tab Index Array Record (0x013D)<p/>
* Description: Contains an array of sheet id's. Sheets always keep their ID
* regardless of what their name is.<P>
* REFERENCE: PG 412 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* regardless of what their name is.<p/>
* REFERENCE: PG 412 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<p/>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
*
*/
public final class TabIdRecord extends Record {
public final class TabIdRecord extends StandardRecord {
public final static short sid = 0x13d;
public short[] field_1_tabids;
private static final short[] EMPTY_SHORT_ARRAY = { };
public short[] _tabids;
public TabIdRecord()
{
public TabIdRecord() {
_tabids = EMPTY_SHORT_ARRAY;
}
public TabIdRecord(RecordInputStream in)
{
field_1_tabids = new short[ in.remaining() / 2 ];
for (int k = 0; k < field_1_tabids.length; k++)
{
field_1_tabids[ k ] = in.readShort();
public TabIdRecord(RecordInputStream in) {
int nTabs = in.remaining() / 2;
_tabids = new short[nTabs];
for (int k = 0; k < _tabids.length; k++) {
_tabids[ k ] = in.readShort();
}
}
@ -48,62 +49,36 @@ public final class TabIdRecord extends Record {
* set the tab array. (0,1,2).
* @param array of tab id's {0,1,2}
*/
public void setTabIdArray(short [] array)
{
field_1_tabids = array;
public void setTabIdArray(short[] array) {
_tabids = array;
}
/**
* get the tab array. (0,1,2).
* @return array of tab id's {0,1,2}
*/
public short [] getTabIdArray()
{
return field_1_tabids;
}
public String toString()
{
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[TABID]\n");
buffer.append(" .elements = ").append(field_1_tabids.length)
.append("\n");
for (int k = 0; k < field_1_tabids.length; k++)
buffer.append(" .elements = ").append(_tabids.length).append("\n");
for (int k = 0; k < _tabids.length; k++)
{
buffer.append(" .element_" + k + " = ")
.append(field_1_tabids[ k ]).append("\n");
buffer.append(" .element_").append(k).append(" = ").append(_tabids[ k ]).append("\n");
}
buffer.append("[/TABID]\n");
return buffer.toString();
}
public int serialize(int offset, byte [] data)
{
short[] tabids = getTabIdArray();
int length = tabids.length * 2;
int byteoffset = 4;
public void serialize(LittleEndianOutput out) {
short[] tabids = _tabids;
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, length); // nubmer tabids *
// 2 (num bytes in a short)
for (int k = 0; k < (length / 2); k++)
{
LittleEndian.putShort(data, byteoffset + offset, tabids[ k ]);
byteoffset += 2;
for (int k = 0; k < tabids.length; k++) {
out.writeShort(tabids[ k ]);
}
return getRecordSize();
}
protected int getDataSize() {
return (getTabIdArray().length * 2);
return _tabids.length * 2;
}
public short getSid()
{
public short getSid() {
return sid;
}
}

View File

@ -18,19 +18,19 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
/**
* Title: Unknown Record (for debugging)<P>
* Title: Unknown Record (for debugging)<p/>
* Description: Unknown record just tells you the sid so you can figure out
* what records you are missing. Also helps us read/modify sheets we
* don't know all the records to. (HSSF leaves these alone!) <P>
* don't know all the records to. (HSSF leaves these alone!) <p/>
* Company: SuperLink Software, Inc.<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class UnknownRecord extends Record {
public final class UnknownRecord extends StandardRecord {
/*
* Some Record IDs used by POI as 'milestones' in the record stream
@ -79,12 +79,8 @@ public final class UnknownRecord extends Record {
/**
* spit the record out AS IS. no interpretation or identification
*/
public final int serialize(int offset, byte[] data) {
LittleEndian.putUShort(data, 0 + offset, _sid);
int dataSize = _rawData.length;
LittleEndian.putUShort(data, 2 + offset, dataSize);
System.arraycopy(_rawData, 0, data, 4 + offset, dataSize);
return 4 + dataSize;
public void serialize(LittleEndianOutput out) {
out.write(_rawData);
}
protected int getDataSize() {
@ -94,7 +90,7 @@ public final class UnknownRecord extends Record {
/**
* print a sort of string representation ([UNKNOWN RECORD] id = x [/UNKNOWN RECORD])
*/
public final String toString() {
public String toString() {
String biffName = getBiffName(_sid);
if (biffName == null) {
biffName = "UNKNOWNRECORD";
@ -110,7 +106,7 @@ public final class UnknownRecord extends Record {
return sb.toString();
}
public final short getSid() {
public short getSid() {
return (short) _sid;
}
@ -267,8 +263,8 @@ public final class UnknownRecord extends Record {
return false;
}
public final Object clone() {
// immutable - ok to return this
public Object clone() {
// immutable - OK to return this
return this;
}
}

View File

@ -19,7 +19,7 @@ package org.apache.poi.hssf.record;
import java.util.Arrays;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;
/**
@ -33,9 +33,10 @@ import org.apache.poi.util.StringUtil;
*
* @author Andrew C. Oliver (acoliver at apache dot org)
*/
public final class WriteAccessRecord extends Record {
private static final byte PAD_CHAR = (byte) ' ';
public final class WriteAccessRecord extends StandardRecord {
public final static short sid = 0x005C;
private static final byte PAD_CHAR = (byte) ' ';
private static final int DATA_SIZE = 112;
private String field_1_username;
/** this record is always padded to a constant length */
@ -113,24 +114,18 @@ public final class WriteAccessRecord extends Record {
return buffer.toString();
}
public int serialize(int offset, byte[] data) {
public void serialize(LittleEndianOutput out) {
String username = getUsername();
boolean is16bit = StringUtil.hasMultibyte(username);
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, DATA_SIZE);
LittleEndian.putUShort(data, 4 + offset, username.length());
LittleEndian.putByte(data, 6 + offset, is16bit ? 0x01 : 0x00);
int pos = offset + 7;
out.writeShort(username.length());
out.writeByte(is16bit ? 0x01 : 0x00);
if (is16bit) {
StringUtil.putUnicodeLE(username, data, pos);
pos += username.length() * 2;
StringUtil.putUnicodeLE(username, out);
} else {
StringUtil.putCompressedUnicode(username, data, pos);
pos += username.length();
StringUtil.putCompressedUnicode(username, out);
}
System.arraycopy(padding, 0, data, pos, padding.length);
return 4 + DATA_SIZE;
out.write(padding);
}
protected int getDataSize() {

View File

@ -51,8 +51,8 @@ public final class PageSettingsBlock extends RecordAggregate {
// (The whole PageSettingsBlock may not be present)
private PageBreakRecord _rowBreaksRecord;
private PageBreakRecord _columnBreaksRecord;
private HeaderRecord header;
private FooterRecord footer;
private HeaderRecord _header;
private FooterRecord _footer;
private HCenterRecord _hCenter;
private VCenterRecord _vCenter;
private LeftMarginRecord _leftMargin;
@ -77,8 +77,8 @@ public final class PageSettingsBlock extends RecordAggregate {
public PageSettingsBlock() {
_rowBreaksRecord = new HorizontalPageBreakRecord();
_columnBreaksRecord = new VerticalPageBreakRecord();
header = createHeader();
footer = createFooter();
_header = new HeaderRecord("");
_footer = new FooterRecord("");
_hCenter = createHCenter();
_vCenter = createVCenter();
printSetup = createPrintSetup();
@ -117,10 +117,10 @@ public final class PageSettingsBlock extends RecordAggregate {
_columnBreaksRecord = (PageBreakRecord) rs.getNext();
break;
case HeaderRecord.sid:
header = (HeaderRecord) rs.getNext();
_header = (HeaderRecord) rs.getNext();
break;
case FooterRecord.sid:
footer = (FooterRecord) rs.getNext();
_footer = (FooterRecord) rs.getNext();
break;
case HCenterRecord.sid:
_hCenter = (HCenterRecord) rs.getNext();
@ -193,8 +193,8 @@ public final class PageSettingsBlock extends RecordAggregate {
public void visitContainedRecords(RecordVisitor rv) {
visitIfPresent(_rowBreaksRecord, rv);
visitIfPresent(_columnBreaksRecord, rv);
visitIfPresent(header, rv);
visitIfPresent(footer, rv);
visitIfPresent(_header, rv);
visitIfPresent(_footer, rv);
visitIfPresent(_hCenter, rv);
visitIfPresent(_vCenter, rv);
visitIfPresent(_leftMargin, rv);
@ -220,28 +220,6 @@ public final class PageSettingsBlock extends RecordAggregate {
}
}
/**
* creates the Header Record and sets it to nothing/0 length
*/
private static HeaderRecord createHeader() {
HeaderRecord retval = new HeaderRecord();
retval.setHeaderLength(( byte ) 0);
retval.setHeader(null);
return retval;
}
/**
* creates the Footer Record and sets it to nothing/0 length
*/
private static FooterRecord createFooter() {
FooterRecord retval = new FooterRecord();
retval.setFooterLength(( byte ) 0);
retval.setFooter(null);
return retval;
}
/**
* creates the HCenter Record and sets it to false (don't horizontally center)
*/
@ -292,7 +270,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public HeaderRecord getHeader ()
{
return header;
return _header;
}
/**
@ -301,7 +279,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public void setHeader (HeaderRecord newHeader)
{
header = newHeader;
_header = newHeader;
}
/**
@ -310,7 +288,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public FooterRecord getFooter ()
{
return footer;
return _footer;
}
/**
@ -319,7 +297,7 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
public void setFooter (FooterRecord newFooter)
{
footer = newFooter;
_footer = newFooter;
}
/**
@ -419,11 +397,11 @@ public final class PageSettingsBlock extends RecordAggregate {
*/
private static void shiftBreaks(PageBreakRecord breaks, int start, int stop, int count) {
Iterator iterator = breaks.getBreaksIterator();
List shiftedBreak = new ArrayList();
Iterator<PageBreakRecord.Break> iterator = breaks.getBreaksIterator();
List<PageBreakRecord.Break> shiftedBreak = new ArrayList<PageBreakRecord.Break>();
while(iterator.hasNext())
{
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
PageBreakRecord.Break breakItem = iterator.next();
int breakLocation = breakItem.main;
boolean inStart = (breakLocation >= start);
boolean inEnd = (breakLocation <= stop);
@ -433,7 +411,7 @@ public final class PageSettingsBlock extends RecordAggregate {
iterator = shiftedBreak.iterator();
while (iterator.hasNext()) {
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
PageBreakRecord.Break breakItem = iterator.next();
breaks.removeBreak(breakItem.main);
breaks.addBreak((short)(breakItem.main+count), breakItem.subFrom, breakItem.subTo);
}

View File

@ -250,7 +250,7 @@ public final class RowRecordsAggregate extends RecordAggregate {
// Serialize a block of cells for those rows
final int startRowNumber = getStartRowNumberForBlock(blockIndex);
final int endRowNumber = getEndRowNumberForBlock(blockIndex);
DBCellRecord cellRecord = new DBCellRecord();
DBCellRecord.Builder dbcrBuilder = new DBCellRecord.Builder();
// Note: Cell references start from the second row...
int cellRefOffset = (rowBlockSize - RowRecord.ENCODED_SIZE);
for (int row = startRowNumber; row <= endRowNumber; row++) {
@ -261,13 +261,12 @@ public final class RowRecordsAggregate extends RecordAggregate {
pos += rowCellSize;
// Add the offset to the first cell for the row into the
// DBCellRecord.
cellRecord.addCellOffset((short) cellRefOffset);
dbcrBuilder.addCellOffset(cellRefOffset);
cellRefOffset = rowCellSize;
}
}
// Calculate Offset from the start of a DBCellRecord to the first Row
cellRecord.setRowOffset(pos);
rv.visitRecord(cellRecord);
rv.visitRecord(dbcrBuilder.build(pos));
}
for (int i=0; i< _unknownRecords.size(); i++) {
// Potentially breaking the file here since we don't know exactly where to write these records

View File

@ -1015,9 +1015,7 @@ public class HSSFCellStyle implements CellStyle
if(workbook != source.workbook) {
// Then we need to clone the format string,
// and update the format record for this
short fmt = workbook.createFormat(
source.getDataFormatString()
);
short fmt = (short)workbook.createFormat(source.getDataFormatString() );
setDataFormat(fmt);
// Finally we need to clone the font,

View File

@ -15,12 +15,6 @@
limitations under the License.
==================================================================== */
/*
* HSSFFont.java
*
* Created on December 9, 2001, 10:34 AM
*/
package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.FontRecord;
@ -29,16 +23,13 @@ import org.apache.poi.ss.usermodel.Font;
/**
* Represents a Font used in a workbook.
*
* @version 1.0-pre
*
* @author Andrew C. Oliver
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createFont()
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getFontAt(short)
* @see org.apache.poi.hssf.usermodel.HSSFCellStyle#setFont(HSSFFont)
*/
public class HSSFFont implements Font
{
public final class HSSFFont implements Font {
private FontRecord font;
private short index;
@ -60,7 +51,6 @@ public class HSSFFont implements Font
public void setFontName(String name)
{
font.setFontName(name);
font.setFontNameLength(( byte ) name.length());
}
/**

View File

@ -86,7 +86,6 @@ public class HSSFFooter extends HeaderFooter implements Footer {
"&C" + (center == null ? "" : center) +
"&L" + (left == null ? "" : left) +
"&R" + (right == null ? "" : right));
footerRecord.setFooterLength((byte)footerRecord.getFooter().length());
}
}

View File

@ -92,7 +92,6 @@ public class HSSFHeader extends HeaderFooter implements Header {
headerRecord.setHeader( "&C" + ( center == null ? "" : center ) +
"&L" + ( left == null ? "" : left ) +
"&R" + ( right == null ? "" : right ) );
headerRecord.setHeaderLength( (byte) headerRecord.getHeader().length() );
}
}

View File

@ -47,12 +47,12 @@ import org.apache.poi.hssf.record.HCenterRecord;
import org.apache.poi.hssf.record.HeaderRecord;
import org.apache.poi.hssf.record.LegendRecord;
import org.apache.poi.hssf.record.LineFormatRecord;
import org.apache.poi.hssf.record.LinkedDataFormulaField;
import org.apache.poi.hssf.record.LinkedDataRecord;
import org.apache.poi.hssf.record.PlotAreaRecord;
import org.apache.poi.hssf.record.PlotGrowthRecord;
import org.apache.poi.hssf.record.PrintSetupRecord;
import org.apache.poi.hssf.record.ProtectRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.SeriesIndexRecord;
@ -96,12 +96,12 @@ public final class HSSFChart {
public void createBarChart( HSSFWorkbook workbook, HSSFSheet sheet )
{
List records = new ArrayList();
List<Record> records = new ArrayList<Record>();
records.add( createMSDrawingObjectRecord() );
records.add( createOBJRecord() );
records.add( createBOFRecord() );
records.add( createHeaderRecord() );
records.add( createFooterRecord() );
records.add(new HeaderRecord(""));
records.add(new FooterRecord(""));
records.add( createHCenterRecord() );
records.add( createVCenterRecord() );
records.add( createPrintSetupRecord() );
@ -340,20 +340,6 @@ public final class HSSFChart {
return r;
}
private FooterRecord createFooterRecord()
{
FooterRecord r = new FooterRecord();
r.setFooter(null);
return r;
}
private HeaderRecord createHeaderRecord()
{
HeaderRecord r = new HeaderRecord();
r.setHeader(null);
return r;
}
private BOFRecord createBOFRecord()
{
BOFRecord r = new BOFRecord();
@ -447,7 +433,7 @@ public final class HSSFChart {
r.setReferenceType(LinkedDataRecord.REFERENCE_TYPE_DIRECT);
r.setCustomNumberFormat(false);
r.setIndexNumberFmtRecord((short)0);
r.setFormulaOfLink( new LinkedDataFormulaField() );
r.setFormulaOfLink(null);
return r;
}
@ -647,7 +633,7 @@ public final class HSSFChart {
r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT );
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
r.setFormulaOfLink( new LinkedDataFormulaField() );
r.setFormulaOfLink(null);
return r;
}
@ -758,11 +744,9 @@ public final class HSSFChart {
r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET );
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
LinkedDataFormulaField formula = new LinkedDataFormulaField();
Area3DPtg p = new Area3DPtg(0, 31, 1, 1,
false, false, false, false, 0);
formula.setFormulaTokens(new Ptg[] { p, });
r.setFormulaOfLink( formula );
r.setFormulaOfLink(new Ptg[] { p, });
return r;
}
@ -773,11 +757,9 @@ public final class HSSFChart {
r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET );
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
LinkedDataFormulaField formula = new LinkedDataFormulaField();
Area3DPtg p = new Area3DPtg(0, 31, 0, 0,
false, false, false, false, 0);
formula.setFormulaTokens(new Ptg[] { p, });
r.setFormulaOfLink( formula );
r.setFormulaOfLink(new Ptg[] { p, });
return r;
}
@ -788,7 +770,7 @@ public final class HSSFChart {
r.setReferenceType( LinkedDataRecord.REFERENCE_TYPE_DIRECT );
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
r.setFormulaOfLink( new LinkedDataFormulaField() );
r.setFormulaOfLink(null);
return r;
}

View File

@ -14,58 +14,52 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import junit.framework.TestCase;
/**
* Tests the serialization and deserialization of the FontRecord
* class works correctly. Test data taken directly from a real
* Excel file.
* Tests the serialization and deserialization of the {@link FontRecord}
* class works correctly. Test data taken directly from a real Excel file.
*/
public final class TestFontRecord extends TestCase {
byte[] header = new byte[] {
0x31, 00, 0x1a, 00, // sid=31, 26 bytes long
};
byte[] data = new byte[] {
0xC8-256, 00, // font height = xc8
00, 00, // attrs = 0
0xFF-256, 0x7F, // colour palette = x7fff
0x90-256, 0x01, // bold weight = x190
00, 00, // supersubscript
00, 00, // underline, family
00, 00, // charset, padding
05, 01, // name length, unicode flag
0x41, 0x00, 0x72, 0x00, 0x69, // Arial, as unicode
0x00, 0x61, 0x00, 0x6C, 0x00
private static final byte[] data = {
0xC8-256, 00, // font height = xc8
00, 00, // attrs = 0
0xFF-256, 0x7F, // colour palette = x7fff
0x90-256, 0x01, // bold weight = x190
00, 00, // supersubscript
00, 00, // underline, family
00, 00, // charset, padding
05, 00, // name length, unicode flag
0x41, 0x72, 0x69, 0x61, 0x6C, // Arial, as unicode
};
public void testLoad() {
FontRecord record = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
assertEquals( 0xc8, record.getFontHeight());
assertEquals( 0x00, record.getAttributes());
assertFalse( record.isItalic());
assertFalse( record.isStruckout());
assertFalse( record.isMacoutlined());
assertFalse( record.isMacshadowed());
assertEquals( 0x7fff, record.getColorPaletteIndex());
assertEquals( 0x190, record.getBoldWeight());
assertEquals( 0x00, record.getSuperSubScript());
assertEquals( 0x00, record.getUnderline());
assertEquals( 0x00, record.getFamily());
assertEquals( 0x00, record.getCharset());
assertEquals( 0x05, record.getFontNameLength());
assertEquals( "Arial", record.getFontName());
assertEquals(0xc8, record.getFontHeight());
assertEquals(0x00, record.getAttributes());
assertFalse(record.isItalic());
assertFalse(record.isStruckout());
assertFalse(record.isMacoutlined());
assertFalse(record.isMacshadowed());
assertEquals(0x7fff, record.getColorPaletteIndex());
assertEquals(0x190, record.getBoldWeight());
assertEquals(0x00, record.getSuperSubScript());
assertEquals(0x00, record.getUnderline());
assertEquals(0x00, record.getFamily());
assertEquals(0x00, record.getCharset());
assertEquals("Arial", record.getFontName());
assertEquals( 26 + 4, record.getRecordSize() );
assertEquals(21 + 4, record.getRecordSize());
}
public void testStore()
{
public void testStore() {
// .fontheight = c8
// .attributes = 0
// .italic = false
@ -90,7 +84,6 @@ public final class TestFontRecord extends TestCase {
record.setUnderline((byte)0);
record.setFamily((byte)0);
record.setCharset((byte)0);
record.setFontNameLength((byte)5);
record.setFontName("Arial");
byte [] recordBytes = record.serialize();
@ -98,10 +91,10 @@ public final class TestFontRecord extends TestCase {
for (int i = 0; i < data.length; i++)
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
}
public void testCloneOnto() throws Exception {
public void testCloneOnto() {
FontRecord base = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
FontRecord other = new FontRecord();
other.cloneStyleFrom(base);
@ -110,18 +103,18 @@ public final class TestFontRecord extends TestCase {
for (int i = 0; i < data.length; i++)
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
}
public void testSameProperties() throws Exception {
FontRecord f1 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
FontRecord f2 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
assertTrue(f1.sameProperties(f2));
f2.setFontName("Arial2");
assertFalse(f1.sameProperties(f2));
f2.setFontName("Arial");
assertTrue(f1.sameProperties(f2));
f2.setFontHeight((short)11);
assertFalse(f1.sameProperties(f2));
f2.setFontHeight((short)0xc8);

View File

@ -167,7 +167,7 @@ recordid = 0x1051, size =8
Area3DPtg ptgExpected = new Area3DPtg(0, 7936, 0, 0,
false, false, false, false, 0);
Object ptgActual = record.getFormulaOfLink().getFormulaTokens()[0];
Ptg ptgActual = record.getFormulaOfLink()[0];
assertEquals(ptgExpected.toString(), ptgActual.toString());
assertEquals( data.length + 4, record.getRecordSize() );
@ -182,9 +182,7 @@ recordid = 0x1051, size =8
record.setIndexNumberFmtRecord( (short)0 );
Area3DPtg ptg = new Area3DPtg(0, 7936, 0, 0,
false, false, false, false, 0);
LinkedDataFormulaField formulaOfLink = new LinkedDataFormulaField();
formulaOfLink.setFormulaTokens(new Ptg[] { ptg, });
record.setFormulaOfLink(formulaOfLink );
record.setFormulaOfLink(new Ptg[] { ptg, } );
byte [] recordBytes = record.serialize();
assertEquals(recordBytes.length - 4, data.length);