Fix for bug 46693 - serialization errors in CHARTFORMAT, SHTPROPS, SXVD and SXVDEX records

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@743601 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-02-12 02:28:43 +00:00
parent ffe6fd7a23
commit 8edb507a89
15 changed files with 451 additions and 290 deletions

View File

@ -37,6 +37,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.5-beta6" date="2008-??-??"> <release version="3.5-beta6" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46693 - Fixed bugs serialization bugs in records: CHARTFORMAT, SHTPROPS, SXVD and SXVDEX</action>
<action dev="POI-DEVELOPERS" type="fix">46627 - Fixed offset of added images if Pictures stream contains pictures with zero length</action> <action dev="POI-DEVELOPERS" type="fix">46627 - Fixed offset of added images if Pictures stream contains pictures with zero length</action>
</release> </release>
<release version="3.5-beta5" date="2008-02-19"> <release version="3.5-beta5" date="2008-02-19">

View File

@ -34,6 +34,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.5-beta6" date="2008-??-??"> <release version="3.5-beta6" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">46693 - Fixed bugs serialization bugs in records: CHARTFORMAT, SHTPROPS, SXVD and SXVDEX</action>
<action dev="POI-DEVELOPERS" type="fix">46627 - Fixed offset of added images if Pictures stream contains pictures with zero length</action> <action dev="POI-DEVELOPERS" type="fix">46627 - Fixed offset of added images if Pictures stream contains pictures with zero length</action>
</release> </release>
<release version="3.5-beta5" date="2008-02-19"> <release version="3.5-beta5" date="2008-02-19">

View File

@ -21,14 +21,16 @@ import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Class ChartFormatRecord * Class ChartFormatRecord (0x1014)<p/>
* *
* (As with all chart related records, documentation is lacking.
* See {@link ChartRecord} for more details)
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
* @version %I%, %G%
*/ */
public final class ChartFormatRecord extends StandardRecord { public final class ChartFormatRecord extends StandardRecord {
public static final short sid = 0x1014; public static final short sid = 0x1014;
@ -36,40 +38,35 @@ public final class ChartFormatRecord extends StandardRecord {
private static final BitField varyDisplayPattern = BitFieldFactory.getInstance(0x01); private static final BitField varyDisplayPattern = BitFieldFactory.getInstance(0x01);
// ignored? // ignored?
private int field1_x_position; // lower left private int field1_x_position; // lower left
private int field2_y_position; // lower left private int field2_y_position; // lower left
private int field3_width; private int field3_width;
private int field4_height; private int field4_height;
private short field5_grbit; private int field5_grbit;
private int field6_unknown;
public ChartFormatRecord() public ChartFormatRecord() {
{ // fields uninitialised
} }
public ChartFormatRecord(RecordInputStream in) public ChartFormatRecord(RecordInputStream in) {
{
field1_x_position = in.readInt(); field1_x_position = in.readInt();
field2_y_position = in.readInt(); field2_y_position = in.readInt();
field3_width = in.readInt(); field3_width = in.readInt();
field4_height = in.readInt(); field4_height = in.readInt();
field5_grbit = in.readShort(); field5_grbit = in.readUShort();
field6_unknown = in.readUShort();
} }
public String toString() public String toString() {
{
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[CHARTFORMAT]\n"); buffer.append("[CHARTFORMAT]\n");
buffer.append(" .xPosition = ").append(getXPosition()) buffer.append(" .xPosition = ").append(getXPosition()).append("\n");
.append("\n"); buffer.append(" .yPosition = ").append(getYPosition()).append("\n");
buffer.append(" .yPosition = ").append(getYPosition()) buffer.append(" .width = ").append(getWidth()).append("\n");
.append("\n"); buffer.append(" .height = ").append(getHeight()).append("\n");
buffer.append(" .width = ").append(getWidth()) buffer.append(" .grBit = ").append(HexDump.intToHex(field5_grbit)).append("\n");
.append("\n");
buffer.append(" .height = ").append(getHeight())
.append("\n");
buffer.append(" .grBit = ")
.append(Integer.toHexString(field5_grbit)).append("\n");
buffer.append("[/CHARTFORMAT]\n"); buffer.append("[/CHARTFORMAT]\n");
return buffer.toString(); return buffer.toString();
} }
@ -80,65 +77,54 @@ public final class ChartFormatRecord extends StandardRecord {
out.writeInt(getWidth()); out.writeInt(getWidth());
out.writeInt(getHeight()); out.writeInt(getHeight());
out.writeShort(field5_grbit); out.writeShort(field5_grbit);
out.writeShort(field6_unknown);
} }
protected int getDataSize() { protected int getDataSize() {
return 18; return 20; // 4 ints and 2 shorts
} }
public short getSid() public short getSid() {
{
return sid; return sid;
} }
public int getXPosition() public int getXPosition() {
{
return field1_x_position; return field1_x_position;
} }
public void setXPosition(int xPosition) public void setXPosition(int xPosition) {
{ field1_x_position = xPosition;
this.field1_x_position = xPosition;
} }
public int getYPosition() public int getYPosition() {
{
return field2_y_position; return field2_y_position;
} }
public void setYPosition(int yPosition) public void setYPosition(int yPosition) {
{ field2_y_position = yPosition;
this.field2_y_position = yPosition;
} }
public int getWidth() public int getWidth() {
{
return field3_width; return field3_width;
} }
public void setWidth(int width) public void setWidth(int width) {
{ field3_width = width;
this.field3_width = width;
} }
public int getHeight() public int getHeight() {
{
return field4_height; return field4_height;
} }
public void setHeight(int height) public void setHeight(int height) {
{ field4_height = height;
this.field4_height = height;
} }
public boolean getVaryDisplayPattern() public boolean getVaryDisplayPattern() {
{
return varyDisplayPattern.isSet(field5_grbit); return varyDisplayPattern.isSet(field5_grbit);
} }
public void setVaryDisplayPattern(boolean value) public void setVaryDisplayPattern(boolean value) {
{ field5_grbit = varyDisplayPattern.setBoolean(field5_grbit, value);
field5_grbit = varyDisplayPattern.setShortBoolean(field5_grbit,
value);
} }
} }

View File

@ -19,58 +19,56 @@ package org.apache.poi.hssf.record.chart;
import org.apache.poi.hssf.record.RecordInputStream; import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.StandardRecord; import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* The chart record is used to define the location and size of a chart. * CHART (0x1002) <p/>
*
* The chart record is used to define the location and size of a chart.<p/>
*
* Chart related records don't seem to be covered in either the
* <A HREF="http://sc.openoffice.org/excelfileformat.pdf">OOO</A>
* or the
* <A HREF="http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-4342ED7AD886/Excel97-2007BinaryFileFormat(xls)Specification.pdf">MS</A>
* documentation.
*
* The book "Microsoft Excel 97 Developer's Kit" ISBN: (1-57231-498-2) seems to have an entire
* chapter (10) devoted to Chart records. One
* <A HREF="http://ooxmlisdefectivebydesign.blogspot.com/2008/03/bad-surprise-in-microsoft-office-binary.html">blog</A>
* suggests that some documentation for these records is available in "MSDN Library, Feb 1998",
* but no later.
*
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public final class ChartRecord extends StandardRecord { public final class ChartRecord extends StandardRecord {
public final static short sid = 0x1002; public final static short sid = 0x1002;
private int field_1_x; private int field_1_x;
private int field_2_y; private int field_2_y;
private int field_3_width; private int field_3_width;
private int field_4_height; private int field_4_height;
public ChartRecord() public ChartRecord() {
{ // fields uninitialised
} }
public ChartRecord(RecordInputStream in) public ChartRecord(RecordInputStream in) {
{ field_1_x = in.readInt();
field_1_x = in.readInt(); field_2_y = in.readInt();
field_2_y = in.readInt(); field_3_width = in.readInt();
field_3_width = in.readInt(); field_4_height = in.readInt();
field_4_height = in.readInt();
} }
public String toString() public String toString() {
{ StringBuffer sb = new StringBuffer();
StringBuffer buffer = new StringBuffer();
buffer.append("[CHART]\n"); sb.append("[CHART]\n");
buffer.append(" .x = ") sb.append(" .x = ").append(getX()).append('\n');
.append("0x").append(HexDump.toHex( getX ())) sb.append(" .y = ").append(getY()).append('\n');
.append(" (").append( getX() ).append(" )"); sb.append(" .width = ").append(getWidth()).append('\n');
buffer.append(System.getProperty("line.separator")); sb.append(" .height= ").append(getHeight()).append('\n');
buffer.append(" .y = ") sb.append("[/CHART]\n");
.append("0x").append(HexDump.toHex( getY ())) return sb.toString();
.append(" (").append( getY() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .width = ")
.append("0x").append(HexDump.toHex( getWidth ()))
.append(" (").append( getWidth() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .height = ")
.append("0x").append(HexDump.toHex( getHeight ()))
.append(" (").append( getHeight() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append("[/CHART]\n");
return buffer.toString();
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
@ -105,64 +103,56 @@ public final class ChartRecord extends StandardRecord {
/** /**
* Get the x field for the Chart record. * Get the x field for the Chart record.
*/ */
public int getX() public int getX() {
{
return field_1_x; return field_1_x;
} }
/** /**
* Set the x field for the Chart record. * Set the x field for the Chart record.
*/ */
public void setX(int field_1_x) public void setX(int x) {
{ field_1_x = x;
this.field_1_x = field_1_x;
} }
/** /**
* Get the y field for the Chart record. * Get the y field for the Chart record.
*/ */
public int getY() public int getY() {
{
return field_2_y; return field_2_y;
} }
/** /**
* Set the y field for the Chart record. * Set the y field for the Chart record.
*/ */
public void setY(int field_2_y) public void setY(int y) {
{ field_2_y = y;
this.field_2_y = field_2_y;
} }
/** /**
* Get the width field for the Chart record. * Get the width field for the Chart record.
*/ */
public int getWidth() public int getWidth() {
{
return field_3_width; return field_3_width;
} }
/** /**
* Set the width field for the Chart record. * Set the width field for the Chart record.
*/ */
public void setWidth(int field_3_width) public void setWidth(int width) {
{ field_3_width = width;
this.field_3_width = field_3_width;
} }
/** /**
* Get the height field for the Chart record. * Get the height field for the Chart record.
*/ */
public int getHeight() public int getHeight() {
{
return field_4_height; return field_4_height;
} }
/** /**
* Set the height field for the Chart record. * Set the height field for the Chart record.
*/ */
public void setHeight(int field_4_height) public void setHeight(int height) {
{ field_4_height = height;
this.field_4_height = field_4_height;
} }
} }

View File

@ -22,12 +22,12 @@ import org.apache.poi.hssf.record.StandardRecord;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* SERIESLIST (0x1016) * SERIESLIST (0x1016)<p/>
* *
* The series list record defines the series displayed as an overlay to the main chart record.<br/> * The series list record defines the series displayed as an overlay to the main chart record.<br/>
* 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
* *
* (As with all chart related records, documentation is lacking.
* See {@link ChartRecord} for more details)
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
@ -73,8 +73,7 @@ public final class SeriesListRecord extends StandardRecord {
return field_1_seriesNumbers.length * 2 + 2; return field_1_seriesNumbers.length * 2 + 2;
} }
public short getSid() public short getSid() {
{
return sid; return sid;
} }
@ -88,14 +87,4 @@ public final class SeriesListRecord extends StandardRecord {
public short[] getSeriesNumbers() { public short[] getSeriesNumbers() {
return field_1_seriesNumbers; return field_1_seriesNumbers;
} }
/**
* Set the series numbers field for the SeriesList record.
*/
public void setSeriesNumbers(short[] field_1_seriesNumbers) {
this.field_1_seriesNumbers = field_1_seriesNumbers;
}
} }

View File

@ -25,8 +25,11 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Describes a chart sheet properties record.<p/> * Describes a chart sheet properties record. SHTPROPS (0x1044) <p/>
* *
* (As with all chart related records, documentation is lacking.
* See {@link ChartRecord} for more details)
*
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public final class SheetPropertiesRecord extends StandardRecord { public final class SheetPropertiesRecord extends StandardRecord {
@ -38,42 +41,33 @@ public final class SheetPropertiesRecord extends StandardRecord {
private static final BitField defaultPlotDimensions = BitFieldFactory.getInstance(0x08); private static final BitField defaultPlotDimensions = BitFieldFactory.getInstance(0x08);
private static final BitField autoPlotArea = BitFieldFactory.getInstance(0x10); private static final BitField autoPlotArea = BitFieldFactory.getInstance(0x10);
private short field_1_flags; private int field_1_flags;
private byte field_2_empty; private int field_2_empty;
public final static byte EMPTY_NOT_PLOTTED = 0; public final static byte EMPTY_NOT_PLOTTED = 0;
public final static byte EMPTY_ZERO = 1; public final static byte EMPTY_ZERO = 1;
public final static byte EMPTY_INTERPOLATED = 2; public final static byte EMPTY_INTERPOLATED = 2;
public SheetPropertiesRecord() public SheetPropertiesRecord() {
{ // fields uninitialised
} }
public SheetPropertiesRecord(RecordInputStream in) public SheetPropertiesRecord(RecordInputStream in) {
{ field_1_flags = in.readUShort();
field_1_flags = in.readShort(); field_2_empty = in.readUShort();
field_2_empty = in.readByte();
} }
public String toString() public String toString() {
{
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[SHTPROPS]\n"); buffer.append("[SHTPROPS]\n");
buffer.append(" .flags = ") buffer.append(" .flags = ").append(HexDump.shortToHex(field_1_flags)).append('\n');
.append("0x").append(HexDump.toHex( getFlags ())) buffer.append(" .chartTypeManuallyFormatted= ").append(isChartTypeManuallyFormatted()).append('\n');
.append(" (").append( getFlags() ).append(" )"); buffer.append(" .plotVisibleOnly = ").append(isPlotVisibleOnly()).append('\n');
buffer.append(System.getProperty("line.separator")); buffer.append(" .doNotSizeWithWindow = ").append(isDoNotSizeWithWindow()).append('\n');
buffer.append(" .chartTypeManuallyFormatted = ").append(isChartTypeManuallyFormatted()).append('\n');
buffer.append(" .plotVisibleOnly = ").append(isPlotVisibleOnly()).append('\n');
buffer.append(" .doNotSizeWithWindow = ").append(isDoNotSizeWithWindow()).append('\n');
buffer.append(" .defaultPlotDimensions = ").append(isDefaultPlotDimensions()).append('\n'); buffer.append(" .defaultPlotDimensions = ").append(isDefaultPlotDimensions()).append('\n');
buffer.append(" .autoPlotArea = ").append(isAutoPlotArea()).append('\n'); buffer.append(" .autoPlotArea = ").append(isAutoPlotArea()).append('\n');
buffer.append(" .empty = ") buffer.append(" .empty = ").append(HexDump.shortToHex(field_2_empty)).append('\n');
.append("0x").append(HexDump.toHex( getEmpty ()))
.append(" (").append( getEmpty() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append("[/SHTPROPS]\n"); buffer.append("[/SHTPROPS]\n");
return buffer.toString(); return buffer.toString();
@ -81,15 +75,14 @@ public final class SheetPropertiesRecord extends StandardRecord {
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.writeShort(field_1_flags); out.writeShort(field_1_flags);
out.writeByte(field_2_empty); out.writeShort(field_2_empty);
} }
protected int getDataSize() { protected int getDataSize() {
return 2 + 1; return 2 + 2;
} }
public short getSid() public short getSid() {
{
return sid; return sid;
} }
@ -101,25 +94,13 @@ public final class SheetPropertiesRecord extends StandardRecord {
return rec; return rec;
} }
/** /**
* Get the flags field for the SheetProperties record. * Get the flags field for the SheetProperties record.
*/ */
public short getFlags() public int getFlags() {
{
return field_1_flags; return field_1_flags;
} }
/**
* Set the flags field for the SheetProperties record.
*/
public void setFlags(short field_1_flags)
{
this.field_1_flags = field_1_flags;
}
/** /**
* Get the empty field for the SheetProperties record. * Get the empty field for the SheetProperties record.
* *
@ -128,40 +109,36 @@ public final class SheetPropertiesRecord extends StandardRecord {
* EMPTY_ZERO * EMPTY_ZERO
* EMPTY_INTERPOLATED * EMPTY_INTERPOLATED
*/ */
public byte getEmpty() public int getEmpty() {
{
return field_2_empty; return field_2_empty;
} }
/** /**
* Set the empty field for the SheetProperties record. * Set the empty field for the SheetProperties record.
* *
* @param field_2_empty * @param empty
* One of * One of
* EMPTY_NOT_PLOTTED * EMPTY_NOT_PLOTTED
* EMPTY_ZERO * EMPTY_ZERO
* EMPTY_INTERPOLATED * EMPTY_INTERPOLATED
*/ */
public void setEmpty(byte field_2_empty) public void setEmpty(byte empty) {
{ this.field_2_empty = empty;
this.field_2_empty = field_2_empty;
} }
/** /**
* Sets the chart type manually formatted field value. * Sets the chart type manually formatted field value.
* Has the chart type been manually formatted? * Has the chart type been manually formatted?
*/ */
public void setChartTypeManuallyFormatted(boolean value) public void setChartTypeManuallyFormatted(boolean value) {
{ field_1_flags = chartTypeManuallyFormatted.setBoolean(field_1_flags, value);
field_1_flags = chartTypeManuallyFormatted.setShortBoolean(field_1_flags, value);
} }
/** /**
* Has the chart type been manually formatted? * Has the chart type been manually formatted?
* @return the chart type manually formatted field value. * @return the chart type manually formatted field value.
*/ */
public boolean isChartTypeManuallyFormatted() public boolean isChartTypeManuallyFormatted() {
{
return chartTypeManuallyFormatted.isSet(field_1_flags); return chartTypeManuallyFormatted.isSet(field_1_flags);
} }
@ -169,17 +146,15 @@ public final class SheetPropertiesRecord extends StandardRecord {
* Sets the plot visible only field value. * Sets the plot visible only field value.
* Only show visible cells on the chart. * Only show visible cells on the chart.
*/ */
public void setPlotVisibleOnly(boolean value) public void setPlotVisibleOnly(boolean value) {
{ field_1_flags = plotVisibleOnly.setBoolean(field_1_flags, value);
field_1_flags = plotVisibleOnly.setShortBoolean(field_1_flags, value);
} }
/** /**
* Only show visible cells on the chart. * Only show visible cells on the chart.
* @return the plot visible only field value. * @return the plot visible only field value.
*/ */
public boolean isPlotVisibleOnly() public boolean isPlotVisibleOnly() {
{
return plotVisibleOnly.isSet(field_1_flags); return plotVisibleOnly.isSet(field_1_flags);
} }
@ -187,17 +162,15 @@ public final class SheetPropertiesRecord extends StandardRecord {
* Sets the do not size with window field value. * Sets the do not size with window field value.
* Do not size the chart when the window changes size * Do not size the chart when the window changes size
*/ */
public void setDoNotSizeWithWindow(boolean value) public void setDoNotSizeWithWindow(boolean value) {
{ field_1_flags = doNotSizeWithWindow.setBoolean(field_1_flags, value);
field_1_flags = doNotSizeWithWindow.setShortBoolean(field_1_flags, value);
} }
/** /**
* Do not size the chart when the window changes size * Do not size the chart when the window changes size
* @return the do not size with window field value. * @return the do not size with window field value.
*/ */
public boolean isDoNotSizeWithWindow() public boolean isDoNotSizeWithWindow() {
{
return doNotSizeWithWindow.isSet(field_1_flags); return doNotSizeWithWindow.isSet(field_1_flags);
} }
@ -205,17 +178,15 @@ public final class SheetPropertiesRecord extends StandardRecord {
* Sets the default plot dimensions field value. * Sets the default plot dimensions field value.
* Indicates that the default area dimensions should be used. * Indicates that the default area dimensions should be used.
*/ */
public void setDefaultPlotDimensions(boolean value) public void setDefaultPlotDimensions(boolean value) {
{ field_1_flags = defaultPlotDimensions.setBoolean(field_1_flags, value);
field_1_flags = defaultPlotDimensions.setShortBoolean(field_1_flags, value);
} }
/** /**
* Indicates that the default area dimensions should be used. * Indicates that the default area dimensions should be used.
* @return the default plot dimensions field value. * @return the default plot dimensions field value.
*/ */
public boolean isDefaultPlotDimensions() public boolean isDefaultPlotDimensions() {
{
return defaultPlotDimensions.isSet(field_1_flags); return defaultPlotDimensions.isSet(field_1_flags);
} }
@ -223,17 +194,15 @@ public final class SheetPropertiesRecord extends StandardRecord {
* Sets the auto plot area field value. * Sets the auto plot area field value.
* ?? * ??
*/ */
public void setAutoPlotArea(boolean value) public void setAutoPlotArea(boolean value) {
{ field_1_flags = autoPlotArea.setBoolean(field_1_flags, value);
field_1_flags = autoPlotArea.setShortBoolean(field_1_flags, value);
} }
/** /**
* ?? * ??
* @return the auto plot area field value. * @return the auto plot area field value.
*/ */
public boolean isAutoPlotArea() public boolean isAutoPlotArea() {
{
return autoPlotArea.isSet(field_1_flags); return autoPlotArea.isSet(field_1_flags);
} }
} }

View File

@ -31,61 +31,60 @@ import org.apache.poi.util.StringUtil;
public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord { public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord {
public static final short sid = 0x0100; public static final short sid = 0x0100;
/** the value of the <tt>cchSubName</tt> field when the subName is not present */ /** the value of the subname length when the {@link #_subName} is not present */
private static final int STRING_NOT_PRESENT_LEN = -1; private static final int STRING_NOT_PRESENT_LEN = 0xFFFF;
private int grbit1; private int _grbit1;
private int grbit2; private int _grbit2;
private int citmShow; private int _citmShow;
private int isxdiSort; private int _isxdiSort;
private int isxdiShow; private int _isxdiShow;
private int reserved1; private int _reserved1;
private int reserved2; private int _reserved2;
private String subName; private String _subName;
public ExtendedPivotTableViewFieldsRecord(RecordInputStream in) { public ExtendedPivotTableViewFieldsRecord(RecordInputStream in) {
grbit1 = in.readInt(); _grbit1 = in.readInt();
grbit2 = in.readUByte(); _grbit2 = in.readUByte();
citmShow = in.readUByte(); _citmShow = in.readUByte();
isxdiSort = in.readUShort(); _isxdiSort = in.readUShort();
isxdiShow = in.readUShort(); _isxdiShow = in.readUShort();
int cchSubName = in.readUShort(); int cchSubName = in.readUShort();
reserved1 = in.readInt(); _reserved1 = in.readInt();
reserved2 = in.readInt(); _reserved2 = in.readInt();
if (cchSubName != STRING_NOT_PRESENT_LEN) { if (cchSubName != STRING_NOT_PRESENT_LEN) {
subName = in.readUnicodeLEString(cchSubName); _subName = in.readUnicodeLEString(cchSubName);
} }
} }
@Override @Override
protected void serialize(LittleEndianOutput out) { protected void serialize(LittleEndianOutput out) {
out.writeInt(grbit1); out.writeInt(_grbit1);
out.writeByte(grbit2); out.writeByte(_grbit2);
out.writeByte(citmShow); out.writeByte(_citmShow);
out.writeShort(isxdiSort); out.writeShort(_isxdiSort);
out.writeShort(isxdiShow); out.writeShort(_isxdiShow);
if (subName == null) { if (_subName == null) {
out.writeShort(STRING_NOT_PRESENT_LEN); out.writeShort(STRING_NOT_PRESENT_LEN);
} else { } else {
out.writeShort(subName.length()); out.writeShort(_subName.length());
} }
out.writeInt(reserved1); out.writeInt(_reserved1);
out.writeInt(reserved2); out.writeInt(_reserved2);
if (subName != null) { if (_subName != null) {
StringUtil.putUnicodeLE(subName, out); StringUtil.putUnicodeLE(_subName, out);
} }
} }
@Override @Override
protected int getDataSize() { protected int getDataSize() {
return 4 + 1 + 1 + 2 + 2 + 2 + 4 + 4 + return 4 + 1 + 1 + 2 + 2 + 2 + 4 + 4 +
(subName == null ? 0 : (2*subName.length())); // in unicode (_subName == null ? 0 : (2*_subName.length())); // in unicode
} }
@Override @Override
@ -99,12 +98,12 @@ public final class ExtendedPivotTableViewFieldsRecord extends StandardRecord {
buffer.append("[SXVDEX]\n"); buffer.append("[SXVDEX]\n");
buffer.append(" .grbit1 =").append(HexDump.intToHex(grbit1)).append("\n"); buffer.append(" .grbit1 =").append(HexDump.intToHex(_grbit1)).append("\n");
buffer.append(" .grbit2 =").append(HexDump.byteToHex(grbit2)).append("\n"); buffer.append(" .grbit2 =").append(HexDump.byteToHex(_grbit2)).append("\n");
buffer.append(" .citmShow =").append(HexDump.byteToHex(citmShow)).append("\n"); buffer.append(" .citmShow =").append(HexDump.byteToHex(_citmShow)).append("\n");
buffer.append(" .isxdiSort =").append(HexDump.shortToHex(isxdiSort)).append("\n"); buffer.append(" .isxdiSort =").append(HexDump.shortToHex(_isxdiSort)).append("\n");
buffer.append(" .isxdiShow =").append(HexDump.shortToHex(isxdiShow)).append("\n"); buffer.append(" .isxdiShow =").append(HexDump.shortToHex(_isxdiShow)).append("\n");
buffer.append(" .subName =").append(subName).append("\n"); buffer.append(" .subName =").append(_subName).append("\n");
buffer.append("[/SXVDEX]\n"); buffer.append("[/SXVDEX]\n");
return buffer.toString(); return buffer.toString();
} }

View File

@ -31,18 +31,20 @@ import org.apache.poi.util.StringUtil;
public final class ViewFieldsRecord extends StandardRecord { public final class ViewFieldsRecord extends StandardRecord {
public static final short sid = 0x00B1; public static final short sid = 0x00B1;
/** the value of the <tt>cchName</tt> field when the name is not present */ /** the value of the <tt>cchName</tt> field when the {@link #_name} is not present */
private static final int STRING_NOT_PRESENT_LEN = -1; private static final int STRING_NOT_PRESENT_LEN = 0xFFFF;
/** 5 shorts */
private static final int BASE_SIZE = 10;
private int sxaxis; private int _sxaxis;
private int cSub; private int _cSub;
private int grbitSub; private int _grbitSub;
private int cItm; private int _cItm;
private String name = null; private String _name;
/** /**
* values for the {@link ViewFieldsRecord#sxaxis} field * values for the {@link ViewFieldsRecord#_sxaxis} field
*/ */
private static final class Axis { private static final class Axis {
public static final int NO_AXIS = 0; public static final int NO_AXIS = 0;
@ -53,27 +55,32 @@ public final class ViewFieldsRecord extends StandardRecord {
} }
public ViewFieldsRecord(RecordInputStream in) { public ViewFieldsRecord(RecordInputStream in) {
sxaxis = in.readShort(); _sxaxis = in.readShort();
cSub = in.readShort(); _cSub = in.readShort();
grbitSub = in.readShort(); _grbitSub = in.readShort();
cItm = in.readShort(); _cItm = in.readShort();
int cchName = in.readShort(); int cchName = in.readUShort();
if (cchName != STRING_NOT_PRESENT_LEN) { if (cchName != STRING_NOT_PRESENT_LEN) {
name = in.readCompressedUnicode(cchName); int flag = in.readByte();
if ((flag & 0x01) != 0) {
_name = in.readUnicodeLEString(cchName);
} else {
_name = in.readCompressedUnicode(cchName);
}
} }
} }
@Override @Override
protected void serialize(LittleEndianOutput out) { protected void serialize(LittleEndianOutput out) {
out.writeShort(sxaxis); out.writeShort(_sxaxis);
out.writeShort(cSub); out.writeShort(_cSub);
out.writeShort(grbitSub); out.writeShort(_grbitSub);
out.writeShort(cItm); out.writeShort(_cItm);
if (name != null) { if (_name != null) {
StringUtil.writeUnicodeString(out, name); StringUtil.writeUnicodeString(out, _name);
} else { } else {
out.writeShort(STRING_NOT_PRESENT_LEN); out.writeShort(STRING_NOT_PRESENT_LEN);
} }
@ -81,12 +88,12 @@ public final class ViewFieldsRecord extends StandardRecord {
@Override @Override
protected int getDataSize() { protected int getDataSize() {
if (_name == null) {
int cchName = 0; return BASE_SIZE;
if (name != null) {
cchName = name.length();
} }
return 2 +2 + 2 + 2 + 2 + cchName; return BASE_SIZE
+ 1 // unicode flag
+ _name.length() * (StringUtil.hasMultibyte(_name) ? 2 : 1);
} }
@Override @Override
@ -98,11 +105,11 @@ public final class ViewFieldsRecord extends StandardRecord {
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("[SXVD]\n"); buffer.append("[SXVD]\n");
buffer.append(" .sxaxis = ").append(HexDump.shortToHex(sxaxis)).append('\n'); buffer.append(" .sxaxis = ").append(HexDump.shortToHex(_sxaxis)).append('\n');
buffer.append(" .cSub = ").append(HexDump.shortToHex(cSub)).append('\n'); buffer.append(" .cSub = ").append(HexDump.shortToHex(_cSub)).append('\n');
buffer.append(" .grbitSub = ").append(HexDump.shortToHex(grbitSub)).append('\n'); buffer.append(" .grbitSub = ").append(HexDump.shortToHex(_grbitSub)).append('\n');
buffer.append(" .cItm = ").append(HexDump.shortToHex(cItm)).append('\n'); buffer.append(" .cItm = ").append(HexDump.shortToHex(_cItm)).append('\n');
buffer.append(" .name = ").append(name).append('\n'); buffer.append(" .name = ").append(_name).append('\n');
buffer.append("[/SXVD]\n"); buffer.append("[/SXVD]\n");
return buffer.toString(); return buffer.toString();

View File

@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.cf.TestCellRange;
import org.apache.poi.hssf.record.chart.AllChartRecordTests; import org.apache.poi.hssf.record.chart.AllChartRecordTests;
import org.apache.poi.hssf.record.constant.TestConstantValueParser; import org.apache.poi.hssf.record.constant.TestConstantValueParser;
import org.apache.poi.hssf.record.formula.AllFormulaTests; import org.apache.poi.hssf.record.formula.AllFormulaTests;
import org.apache.poi.hssf.record.pivot.AllPivotRecordTests;
/** /**
* Collects all tests for package <tt>org.apache.poi.hssf.record</tt> and sub-packages. * Collects all tests for package <tt>org.apache.poi.hssf.record</tt> and sub-packages.
@ -38,6 +39,7 @@ public final class AllRecordTests {
result.addTest(AllChartRecordTests.suite()); result.addTest(AllChartRecordTests.suite());
result.addTest(AllFormulaTests.suite()); result.addTest(AllFormulaTests.suite());
result.addTest(AllPivotRecordTests.suite());
result.addTest(AllRecordAggregateTests.suite()); result.addTest(AllRecordAggregateTests.suite());
result.addTestSuite(TestBOFRecord.class); result.addTestSuite(TestBOFRecord.class);

View File

@ -39,6 +39,7 @@ public final class AllChartRecordTests {
result.addTestSuite(TestAxisUsedRecord.class); result.addTestSuite(TestAxisUsedRecord.class);
result.addTestSuite(TestBarRecord.class); result.addTestSuite(TestBarRecord.class);
result.addTestSuite(TestCategorySeriesAxisRecord.class); result.addTestSuite(TestCategorySeriesAxisRecord.class);
result.addTestSuite(TestChartFormatRecord.class);
result.addTestSuite(TestChartRecord.class); result.addTestSuite(TestChartRecord.class);
result.addTestSuite(TestChartTitleFormatRecord.class); result.addTestSuite(TestChartTitleFormatRecord.class);
result.addTestSuite(TestDatRecord.class); result.addTestSuite(TestDatRecord.class);

View File

@ -0,0 +1,61 @@
/* ====================================================================
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.chart;
import java.util.Arrays;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.util.HexRead;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests for {@link ChartFormatRecord} Test data taken directly from a real
* Excel file.
*
* @author Josh Micich
*/
public final class TestChartFormatRecord extends TestCase {
/**
* This rather uninteresting data came from attachment 23347 of bug 46693 at
* offsets 0x6BB2 and 0x7BAF
*/
private static final byte[] data = HexRead.readFromString(
"14 10 14 00 " // BIFF header
+ "00 00 00 00 00 00 00 00 "
+ "00 00 00 00 00 00 00 00 "
+ "00 00 00 00");
/**
* The correct size of a {@link ChartFormatRecord} is 20 bytes (not including header).
*/
public void testLoad() {
RecordInputStream in = TestcaseRecordInputStream.create(data);
ChartFormatRecord record = new ChartFormatRecord(in);
if (in.remaining() == 2) {
throw new AssertionFailedError("Identified bug 44693d");
}
assertEquals(0, in.remaining());
assertEquals(24, record.getRecordSize());
byte[] data2 = record.serialize();
assertTrue(Arrays.equals(data, data2));
}
}

View File

@ -18,27 +18,32 @@
package org.apache.poi.hssf.record.chart; package org.apache.poi.hssf.record.chart;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream; import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
* Tests the serialization and deserialization of the SheetPropertiesRecord * Tests for {@link SheetPropertiesRecord}
* class works correctly. Test data taken directly from a real * Test data taken directly from a real Excel file.
* Excel file.
* *
* @author Glen Stampoultzis (glens at apache.org) * @author Glen Stampoultzis (glens at apache.org)
*/ */
public final class TestSheetPropertiesRecord extends TestCase { public final class TestSheetPropertiesRecord extends TestCase {
byte[] data = new byte[] { private static final byte[] data = {
(byte)0x0A,(byte)0x00, (byte)0x0A,(byte)0x00,
(byte)0x00 (byte)0x00,
//,(byte)0x00 // not sure where that last byte comes from (byte)0x00, // not sure where that last byte comes from
}; };
public void testLoad() { public void testLoad() {
SheetPropertiesRecord record = new SheetPropertiesRecord(TestcaseRecordInputStream.create(0x1044, data)); RecordInputStream in = TestcaseRecordInputStream.create(0x1044, data);
SheetPropertiesRecord record = new SheetPropertiesRecord(in);
if (in.remaining() == 1) {
throw new AssertionFailedError("Identified bug 44693c");
}
assertEquals(0, in.remaining());
assertEquals( 10, record.getFlags()); assertEquals( 10, record.getFlags());
assertEquals( false, record.isChartTypeManuallyFormatted() ); assertEquals( false, record.isChartTypeManuallyFormatted() );
assertEquals( true, record.isPlotVisibleOnly() ); assertEquals( true, record.isPlotVisibleOnly() );
@ -47,12 +52,10 @@ public final class TestSheetPropertiesRecord extends TestCase {
assertEquals( false, record.isAutoPlotArea() ); assertEquals( false, record.isAutoPlotArea() );
assertEquals( 0, record.getEmpty()); assertEquals( 0, record.getEmpty());
assertEquals( 8, record.getRecordSize() );
assertEquals( 7, record.getRecordSize() );
} }
public void testStore() public void testStore() {
{
SheetPropertiesRecord record = new SheetPropertiesRecord(); SheetPropertiesRecord record = new SheetPropertiesRecord();
record.setChartTypeManuallyFormatted( false ); record.setChartTypeManuallyFormatted( false );
record.setPlotVisibleOnly( true ); record.setPlotVisibleOnly( true );
@ -63,8 +66,6 @@ public final class TestSheetPropertiesRecord extends TestCase {
byte [] recordBytes = record.serialize(); byte [] recordBytes = record.serialize();
assertEquals(recordBytes.length - 4, data.length); TestcaseRecordInputStream.confirmRecordEncoding(SheetPropertiesRecord.sid, data, recordBytes);
for (int i = 0; i < data.length; i++)
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
} }
} }

View File

@ -0,0 +1,36 @@
/* ====================================================================
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.pivot;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Collects all tests for <tt>org.apache.poi.hssf.record.pivot</tt>.
*
* @author Josh Micich
*/
public final class AllPivotRecordTests {
public static Test suite() {
TestSuite result = new TestSuite(AllPivotRecordTests.class.getName());
result.addTestSuite(TestExtendedPivotTableViewFieldsRecord.class);
return result;
}
}

View File

@ -0,0 +1,54 @@
/* ====================================================================
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.pivot;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.pivottable.ExtendedPivotTableViewFieldsRecord;
import org.apache.poi.util.HexRead;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests for {@link ExtendedPivotTableViewFieldsRecord}
*
* @author Josh Micich
*/
public final class TestExtendedPivotTableViewFieldsRecord extends TestCase {
public void testSubNameNotPresent_bug46693() {
// This data came from attachment 23347 of bug 46693 at offset 0xAA43
byte[] data = HexRead.readFromString(
"00 01 14 00" + // BIFF header
"1E 14 00 0A FF FF FF FF 00 00 FF FF 00 00 00 00 00 00 00 00");
RecordInputStream in = TestcaseRecordInputStream.create(data);
ExtendedPivotTableViewFieldsRecord rec;
try {
rec = new ExtendedPivotTableViewFieldsRecord(in);
} catch (RecordFormatException e) {
if (e.getMessage().equals("Expected to find a ContinueRecord in order to read remaining 65535 of 65535 chars")) {
throw new AssertionFailedError("Identified bug 46693a");
}
throw e;
}
assertEquals(data.length, rec.getRecordSize());
}
}

View File

@ -0,0 +1,64 @@
/* ====================================================================
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.pivot;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.pivottable.ViewFieldsRecord;
import org.apache.poi.util.HexRead;
/**
* Tests for {@link ViewFieldsRecord}
*
* @author Josh Micich
*/
public final class TestViewFieldsRecord extends TestCase {
public void testUnicodeFlag_bug46693() {
byte[] data = HexRead.readFromString("01 00 01 00 01 00 04 00 05 00 00 6D 61 72 63 6F");
RecordInputStream in = TestcaseRecordInputStream.create(ViewFieldsRecord.sid, data);
ViewFieldsRecord rec = new ViewFieldsRecord(in);
if (in.remaining() == 1) {
throw new AssertionFailedError("Identified bug 46693b");
}
assertEquals(0, in.remaining());
assertEquals(4+data.length, rec.getRecordSize());
}
public void testSerialize() {
// This hex data was produced by changing the 'Custom Name' property,
// available under 'Field Settings' from the 'PivotTable Field List' (Excel 2007)
confirmSerialize("00 00 01 00 01 00 00 00 FF FF");
confirmSerialize("01 00 01 00 01 00 04 00 05 00 00 6D 61 72 63 6F");
confirmSerialize("01 00 01 00 01 00 04 00 0A 00 01 48 00 69 00 73 00 74 00 6F 00 72 00 79 00 2D 00 82 69 81 89");
}
private static ViewFieldsRecord confirmSerialize(String hexDump) {
byte[] data = HexRead.readFromString(hexDump);
RecordInputStream in = TestcaseRecordInputStream.create(ViewFieldsRecord.sid, data);
ViewFieldsRecord rec = new ViewFieldsRecord(in);
assertEquals(0, in.remaining());
assertEquals(4+data.length, rec.getRecordSize());
byte[] data2 = rec.serialize();
TestcaseRecordInputStream.confirmRecordEncoding(ViewFieldsRecord.sid, data, data2);
return rec;
}
}