diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 0f17e7cc3..bac5f0a16 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -36,6 +36,7 @@ + 43399 - [PATCH] - Fix for Cell References for rows > 32678 43410 - [PATCH] - Improved Formula Parser support for numbers and ranges When writing HSLF files out, optionally preserve all OLE2 nodes (default is just the HSLF related nodes) 43323 - [PATCH] - Support for adding Pictures to ShapeGroups in HSLF. diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 9a3a8d6fa..9ab70b7fd 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -33,6 +33,7 @@ + 43399 - [PATCH] - Fix for Cell References for rows > 32678 43410 - [PATCH] - Improved Formula Parser support for numbers and ranges When writing HSLF files out, optionally preserve all OLE2 nodes (default is just the HSLF related nodes) 43323 - [PATCH] - Support for adding Pictures to ShapeGroups in HSLF. diff --git a/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java b/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java index 7e8758d6f..df3e5a70b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java @@ -35,8 +35,18 @@ public class ReferencePtg extends Ptg { private final static int SIZE = 5; public final static byte sid = 0x24; + private final static int MAX_ROW_NUMBER = 65536; //public final static byte sid = 0x44; + + /** + * The row number, between 0 and 65535, but stored as a signed + * short between -32767 and 32768. + * Take care about which version you fetch back! + */ private short field_1_row; + /** + * The column number, between 0 and ?? + */ private short field_2_col; private BitField rowRelative = BitFieldFactory.getInstance(0x8000); private BitField colRelative = BitFieldFactory.getInstance(0x4000); @@ -93,6 +103,7 @@ public class ReferencePtg extends Ptg public void writeBytes(byte [] array, int offset) { array[offset] = (byte) (sid + ptgClass); + LittleEndian.putShort(array,offset+1,field_1_row); LittleEndian.putShort(array,offset+3,field_2_col); } @@ -101,11 +112,38 @@ public class ReferencePtg extends Ptg { field_1_row = row; } + public void setRow(int row) + { + if(row < 0 || row >= MAX_ROW_NUMBER) { + throw new IllegalArgumentException("The row number, when specified as an integer, must be between 0 and " + MAX_ROW_NUMBER); + } + + // Save, wrapping as needed + if(row > Short.MAX_VALUE) { + field_1_row = (short)(row - MAX_ROW_NUMBER); + } else { + field_1_row = (short)row; + } + } + /** + * Returns the row number as a short, which will be + * wrapped (negative) for values between 32769 and 65535 + */ public short getRow() { return field_1_row; } + /** + * Returns the row number as an int, between 0 and 65535 + */ + public int getRowAsInt() + { + if(field_1_row < 0) { + return field_1_row + MAX_ROW_NUMBER; + } + return field_1_row; + } public boolean isRowRelative() { @@ -153,7 +191,7 @@ public class ReferencePtg extends Ptg public String toFormulaString(Workbook book) { //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe! - return (new CellReference(getRow(),getColumn(),!isRowRelative(),!isColRelative())).toString(); + return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).toString(); } public byte getDefaultOperandClass() { diff --git a/src/testcases/org/apache/poi/hssf/data/ReferencePtg.xls b/src/testcases/org/apache/poi/hssf/data/ReferencePtg.xls new file mode 100644 index 000000000..d415034d1 Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/ReferencePtg.xls differ diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java new file mode 100644 index 000000000..226b14400 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java @@ -0,0 +1,77 @@ + +/* ==================================================================== + 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.formula; + +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +/** + * Tests for {@link ReferencePtg}. + */ +public class TestReferencePtg extends AbstractPtgTestCase +{ + /** + * Tests reading a file containing this ptg. + */ + public void testReading() throws Exception + { + HSSFWorkbook workbook = loadWorkbook("ReferencePtg.xls"); + HSSFSheet sheet = workbook.getSheetAt(0); + + // First row + assertEquals("Wrong numeric value for original number", 55.0, + sheet.getRow(0).getCell((short) 0).getNumericCellValue(), 0.0); + assertEquals("Wrong numeric value for referemce", 55.0, + sheet.getRow(0).getCell((short) 1).getNumericCellValue(), 0.0); + assertEquals("Wrong formula string for reference", "A1", + sheet.getRow(0).getCell((short) 1).getCellFormula()); + + // Now moving over the 2**15 boundary + // (Remember that excel row (n) is poi row (n-1) + assertEquals("Wrong numeric value for original number", 32767.0, + sheet.getRow(32766).getCell((short) 0).getNumericCellValue(), 0.0); + assertEquals("Wrong numeric value for referemce", 32767.0, + sheet.getRow(32766).getCell((short) 1).getNumericCellValue(), 0.0); + assertEquals("Wrong formula string for reference", "A32767", + sheet.getRow(32766).getCell((short) 1).getCellFormula()); + + assertEquals("Wrong numeric value for original number", 32768.0, + sheet.getRow(32767).getCell((short) 0).getNumericCellValue(), 0.0); + assertEquals("Wrong numeric value for referemce", 32768.0, + sheet.getRow(32767).getCell((short) 1).getNumericCellValue(), 0.0); + assertEquals("Wrong formula string for reference", "A32768", + sheet.getRow(32767).getCell((short) 1).getCellFormula()); + + assertEquals("Wrong numeric value for original number", 32769.0, + sheet.getRow(32768).getCell((short) 0).getNumericCellValue(), 0.0); + assertEquals("Wrong numeric value for referemce", 32769.0, + sheet.getRow(32768).getCell((short) 1).getNumericCellValue(), 0.0); + assertEquals("Wrong formula string for reference", "A32769", + sheet.getRow(32768).getCell((short) 1).getCellFormula()); + + assertEquals("Wrong numeric value for original number", 32770.0, + sheet.getRow(32769).getCell((short) 0).getNumericCellValue(), 0.0); + assertEquals("Wrong numeric value for referemce", 32770.0, + sheet.getRow(32769).getCell((short) 1).getNumericCellValue(), 0.0); + assertEquals("Wrong formula string for reference", "A32770", + sheet.getRow(32769).getCell((short) 1).getCellFormula()); + } +} + +