From d45b6acef35de59083f62ca4b1b8669db48acfcf Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 7 Nov 2013 21:56:49 +0000 Subject: [PATCH] Patch from Andreas Beeker from bug #49237 - HSSF Row Style XfIndex is 12 not 16 bits of data git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1539837 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/hssf/record/RowRecord.java | 94 ++++++++++++++++-- .../apache/poi/hssf/usermodel/TestBugs.java | 9 ++ test-data/spreadsheet/49237.xls | Bin 0 -> 19968 bytes 3 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 test-data/spreadsheet/49237.xls diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java index a3e0c24d3..75d3f99b1 100644 --- a/src/java/org/apache/poi/hssf/record/RowRecord.java +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -36,7 +36,7 @@ public final class RowRecord extends StandardRecord { public static final int ENCODED_SIZE = 20; private static final int OPTION_BITS_ALWAYS_SET = 0x0100; - private static final int DEFAULT_HEIGHT_BIT = 0x8000; + //private static final int DEFAULT_HEIGHT_BIT = 0x8000; private int field_1_row_number; private int field_2_first_col; @@ -49,13 +49,19 @@ public final class RowRecord extends StandardRecord { /** 16 bit options flags */ private int field_7_option_flags; private static final BitField outlineLevel = BitFieldFactory.getInstance(0x07); - // bit 3 reserved private static final BitField colapsed = BitFieldFactory.getInstance(0x10); private static final BitField zeroHeight = BitFieldFactory.getInstance(0x20); private static final BitField badFontHeight = BitFieldFactory.getInstance(0x40); private static final BitField formatted = BitFieldFactory.getInstance(0x80); - private short field_8_xf_index; // only if isFormatted + + /** 16 bit options flags */ + private int field_8_option_flags; // only if isFormatted + private static final BitField xfIndex = BitFieldFactory.getInstance(0xFFF); + private static final BitField topBorder = BitFieldFactory.getInstance(0x1000); + private static final BitField bottomBorder = BitFieldFactory.getInstance(0x2000); + private static final BitField phoeneticGuide = BitFieldFactory.getInstance(0x4000); + // bit 15 is unused public RowRecord(int rowNumber) { field_1_row_number = rowNumber; @@ -64,7 +70,7 @@ public final class RowRecord extends StandardRecord { field_6_reserved = ( short ) 0; field_7_option_flags = OPTION_BITS_ALWAYS_SET; // seems necessary for outlining - field_8_xf_index = ( short ) 0xf; + field_8_option_flags = ( short ) 0xf; setEmpty(); } @@ -76,7 +82,7 @@ public final class RowRecord extends StandardRecord { field_5_optimize = in.readShort(); field_6_reserved = in.readShort(); field_7_option_flags = in.readShort(); - field_8_xf_index = in.readShort(); + field_8_option_flags = in.readShort(); } /** @@ -180,9 +186,37 @@ public final class RowRecord extends StandardRecord { * @param index to the XF record */ public void setXFIndex(short index) { - field_8_xf_index = index; + field_8_option_flags = xfIndex.setValue(field_8_option_flags, index); } + /** + * bit that specifies whether any cell in the row has a thick top border, or any + * cell in the row directly above the current row has a thick bottom border. + * @param f has thick top border + */ + public void setTopBorder(boolean f) { + field_8_option_flags = topBorder.setBoolean(field_8_option_flags, f); + } + + /** + * A bit that specifies whether any cell in the row has a medium or thick + * bottom border, or any cell in the row directly below the current row has + * a medium or thick top border. + * @param f has thick bottom border + */ + public void setBottomBorder(boolean f) { + field_8_option_flags = bottomBorder.setBoolean(field_8_option_flags, f); + } + + /** + * A bit that specifies whether the phonetic guide feature is enabled for + * any cell in this row. + * @param f use phoenetic guide + */ + public void setPhoeneticGuide(boolean f) { + field_8_option_flags = phoeneticGuide.setBoolean(field_8_option_flags, f); + } + /** * get the logical row number for this row (0 based index) * @return row - the row number @@ -281,15 +315,51 @@ public final class RowRecord extends StandardRecord { // end bitfields + /** + * gets the 2nd option bitmask. (use the individual bit setters that refer to this + * method) + * @return options - the bitmask + */ + public short getOptionFlags2() { + return (short)field_8_option_flags; + } + /** * if the row is formatted then this is the index to the extended format record * @see org.apache.poi.hssf.record.ExtendedFormatRecord * @return index to the XF record or bogus value (undefined) if isn't formatted */ public short getXFIndex() { - return field_8_xf_index; + return xfIndex.getShortValue((short)field_8_option_flags); } + /** + * A bit that specifies whether any cell in the row has a thick top border, or any + * cell in the row directly above the current row has a thick bottom border. + * @return has cells with a thick top border + */ + public boolean getTopBorder() { + return topBorder.isSet(field_8_option_flags); + } + + /** + * A bit that specifies whether any cell in the row has a medium or thick bottom border, + * or any cell in the row directly below the current row has a medium or thick top border. + * @return has cells with a thick bottom border + */ + public boolean getBottomBorder() { + return bottomBorder.isSet(field_8_option_flags); + } + + /** + * A bit that specifies whether the phonetic guide feature is enabled for + * any cell in this row. + * @return has phoentic guide + */ + public boolean getPhoeneticGuide() { + return phoeneticGuide.isSet(field_8_option_flags); + } + public String toString() { StringBuffer sb = new StringBuffer(); @@ -307,7 +377,11 @@ public final class RowRecord extends StandardRecord { sb.append(" .zeroheight = ").append(getZeroHeight()).append("\n"); sb.append(" .badfontheig= ").append(getBadFontHeight()).append("\n"); sb.append(" .formatted = ").append(getFormatted()).append("\n"); - sb.append(" .xfindex = ").append(Integer.toHexString(getXFIndex())).append("\n"); + sb.append(" .optionsflags2 = ").append(HexDump.shortToHex(getOptionFlags2())).append("\n"); + sb.append(" .xfindex = ").append(Integer.toHexString(getXFIndex())).append("\n"); + sb.append(" .topBorder = ").append(getTopBorder()).append("\n"); + sb.append(" .bottomBorder = ").append(getBottomBorder()).append("\n"); + sb.append(" .phoeneticGuide= ").append(getPhoeneticGuide()).append("\n"); sb.append("[/ROW]\n"); return sb.toString(); } @@ -320,7 +394,7 @@ public final class RowRecord extends StandardRecord { out.writeShort(getOptimize()); out.writeShort(field_6_reserved); out.writeShort(getOptionFlags()); - out.writeShort(getXFIndex()); + out.writeShort(getOptionFlags2()); } protected int getDataSize() { @@ -339,7 +413,7 @@ public final class RowRecord extends StandardRecord { rec.field_5_optimize = field_5_optimize; rec.field_6_reserved = field_6_reserved; rec.field_7_option_flags = field_7_option_flags; - rec.field_8_xf_index = field_8_xf_index; + rec.field_8_option_flags = field_8_option_flags; return rec; } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java index f392a4da2..d5684d84a 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -2319,4 +2319,13 @@ if(1==2) { HSSFWorkbook wb = openSample("54016.xls"); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); } + + /** Row style information is 12 not 16 bits */ + public void testFile() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49237.xls"); + HSSFSheet sheet = wb.getSheetAt(0); + HSSFRow row = sheet.getRow(0); + HSSFCellStyle rstyle = row.getRowStyle(); + assertEquals(rstyle.getBorderBottom(), HSSFCellStyle.BORDER_DOUBLE); + } } diff --git a/test-data/spreadsheet/49237.xls b/test-data/spreadsheet/49237.xls new file mode 100644 index 0000000000000000000000000000000000000000..bb525fda25b19fd7716621b288cb67e5178ef2bb GIT binary patch literal 19968 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 SBk