diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 58f29dd78..cd5b4fd67 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF 46951 - Fixed formula parser to better handle range operators and whole row/column refs. 46948 - Fixed evaluation of range operator to allow for area-ref operands 46918 - Fixed ExtendedPivotTableViewFieldsRecord(SXVDEX) to allow shorter format diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 45e451845..1fd834463 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 46832 - Allow merged regions with columns greater than 255 or rows bigger than 65536 in XSSF 46951 - Fixed formula parser to better handle range operators and whole row/column refs. 46948 - Fixed evaluation of range operator to allow for area-ref operands 46918 - Fixed ExtendedPivotTableViewFieldsRecord(SXVDEX) to allow shorter format diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java index a2f1e22de..a3e0c24d3 100644 --- a/src/java/org/apache/poi/hssf/record/RowRecord.java +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -38,11 +38,6 @@ public final class RowRecord extends StandardRecord { private static final int OPTION_BITS_ALWAYS_SET = 0x0100; private static final int DEFAULT_HEIGHT_BIT = 0x8000; - /** The maximum row number that excel can handle (zero based) ie 65536 rows is - * max number of rows. - */ - public final static int MAX_ROW_NUMBER = 65535; - private int field_1_row_number; private int field_2_first_col; private int field_3_last_col; // plus 1 diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java index f3601f6f9..1d10332cb 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -39,6 +39,7 @@ import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.TableRecord; import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.ss.SpreadsheetVersion; /** * @@ -138,8 +139,9 @@ public final class RowRecordsAggregate extends RecordAggregate { } public RowRecord getRow(int rowIndex) { - if (rowIndex < 0 || rowIndex > 65535) { - throw new IllegalArgumentException("The row number must be between 0 and 65535"); + int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex(); + if (rowIndex < 0 || rowIndex > maxrow) { + throw new IllegalArgumentException("The row number must be between 0 and " + maxrow); } return _rowRecords.get(new Integer(rowIndex)); } diff --git a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java index 33e131515..205dd0ddf 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java @@ -22,6 +22,7 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.ss.SpreadsheetVersion; /** * ReferencePtgBase - handles references (such as A1, A2, IA4) @@ -31,7 +32,7 @@ import org.apache.poi.util.LittleEndianOutput; */ public abstract class RefPtgBase extends OperandPtg { - private final static int MAX_ROW_NUMBER = 65536; + private final static int MAX_ROW_NUMBER = SpreadsheetVersion.EXCEL97.getMaxRows(); /** The row index - zero based unsigned 16 bit value */ private int field_1_row; @@ -73,7 +74,7 @@ public abstract class RefPtgBase extends OperandPtg { } /** - * @return the row number as an int, between 0 and 65535 + * @return the row number as an int */ public final int getRow() { return field_1_row; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 65736aa9f..d985216c9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -55,6 +55,7 @@ import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.SpreadsheetVersion; /** * High level representation of a cell in a row of a spreadsheet. @@ -79,8 +80,8 @@ public class HSSFCell implements Cell { /** * The maximum number of columns in BIFF8 */ - public static final int LAST_COLUMN_NUMBER = 255; // 2^8 - 1 - private static final String LAST_COLUMN_NAME = "IV"; + public static final int LAST_COLUMN_NUMBER = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); // 2^8 - 1 + private static final String LAST_COLUMN_NAME = SpreadsheetVersion.EXCEL97.getLastColumnName(); public final static short ENCODING_UNCHANGED = -1; public final static short ENCODING_COMPRESSED_UNICODE = 0; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java index 50483d908..53938cf82 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.ExtendedFormatRecord; import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.SpreadsheetVersion; /** * High level representation of a row of a spreadsheet. @@ -222,9 +223,10 @@ public final class HSSFRow implements Row { * @throws IndexOutOfBoundsException if the row number is not within the range 0-65535. */ public void setRowNum(int rowIndex) { - if ((rowIndex < 0) || (rowIndex > RowRecord.MAX_ROW_NUMBER)) { + int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex(); + if ((rowIndex < 0) || (rowIndex > maxrow)) { throw new IllegalArgumentException("Invalid row number (" + rowIndex - + ") outside allowable range (0.." + RowRecord.MAX_ROW_NUMBER + ")"); + + ") outside allowable range (0.." + maxrow + ")"); } rowNum = rowIndex; if (row != null) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index 4fdbfd00f..cf81a8568 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -51,6 +51,7 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -558,6 +559,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { */ public int addMergedRegion(CellRangeAddress region) { + region.validate(SpreadsheetVersion.EXCEL97); return _sheet.addMergedRegion( region.getFirstRow(), region.getFirstColumn(), region.getLastRow(), @@ -1256,7 +1258,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { } } } - if ( endRow == _lastrow || endRow + n > _lastrow ) _lastrow = Math.min( endRow + n, 65535 ); + if ( endRow == _lastrow || endRow + n > _lastrow ) _lastrow = Math.min( endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex() ); if ( startRow == _firstrow || startRow + n < _firstrow ) _firstrow = Math.max( startRow + n, 0 ); // Update any formulas on this sheet that point to @@ -1291,8 +1293,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @param leftmostColumn Left column visible in right pane. */ public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) { - if (colSplit < 0 || colSplit > 255) throw new IllegalArgumentException("Column must be between 0 and 255"); - if (rowSplit < 0 || rowSplit > 65535) throw new IllegalArgumentException("Row must be between 0 and 65535"); + validateColumn(colSplit); + validateRow(rowSplit); if (leftmostColumn < colSplit) throw new IllegalArgumentException("leftmostColumn parameter must not be less than colSplit parameter"); if (topRow < rowSplit) throw new IllegalArgumentException("topRow parameter must not be less than leftmostColumn parameter"); getSheet().createFreezePane( colSplit, rowSplit, topRow, leftmostColumn ); @@ -1426,7 +1428,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { */ public void setColumnBreak(int column) { validateColumn((short)column); - _sheet.getPageSettings().setColumnBreak((short)column, (short)0, (short)65535); + _sheet.getPageSettings().setColumnBreak((short)column, (short)0, (short) SpreadsheetVersion.EXCEL97.getLastRowIndex()); } /** @@ -1451,7 +1453,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @param row */ protected void validateRow(int row) { - if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535"); + int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex(); + if (row > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow); if (row < 0) throw new IllegalArgumentException("Minumum row number is 0"); } @@ -1459,8 +1462,9 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Runs a bounds check for column numbers * @param column */ - protected void validateColumn(short column) { - if (column > 255) throw new IllegalArgumentException("Maximum column number is 255"); + protected void validateColumn(int column) { + int maxcol = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); + if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol); if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java index f3c93611e..ce6235a1a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java @@ -23,6 +23,7 @@ import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.ss.util.Region; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.SpreadsheetVersion; /** * The 'Conditional Formatting' facet of HSSFSheet @@ -120,7 +121,9 @@ public final class HSSFSheetConditionalFormatting { if (regions == null) { throw new IllegalArgumentException("regions must not be null"); } - if (cfRules == null) { + for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97); + + if (cfRules == null) { throw new IllegalArgumentException("cfRules must not be null"); } if (cfRules.length == 0) { diff --git a/src/java/org/apache/poi/hssf/util/CellRangeAddress.java b/src/java/org/apache/poi/hssf/util/CellRangeAddress.java index 72c493021..da8d56c09 100644 --- a/src/java/org/apache/poi/hssf/util/CellRangeAddress.java +++ b/src/java/org/apache/poi/hssf/util/CellRangeAddress.java @@ -28,23 +28,11 @@ import org.apache.poi.hssf.record.SelectionRecord; * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) */ public class CellRangeAddress extends org.apache.poi.ss.util.CellRangeAddress { - /* - * TODO - replace org.apache.poi.hssf.util.Region - */ - public static final int ENCODED_SIZE = 8; public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) { super(firstRow, lastRow, firstCol, lastCol); } public CellRangeAddress(RecordInputStream in) { - super(readUShortAndCheck(in), in.readUShort(), in.readUShort(), in.readUShort()); - } - - private static int readUShortAndCheck(RecordInputStream in) { - if (in.remaining() < ENCODED_SIZE) { - // Ran out of data - throw new RuntimeException("Ran out of data reading CellRangeAddress"); - } - return in.readUShort(); + super(in); } } diff --git a/src/java/org/apache/poi/ss/SpreadsheetVersion.java b/src/java/org/apache/poi/ss/SpreadsheetVersion.java index 754fbdbb6..4a7b2bbe4 100755 --- a/src/java/org/apache/poi/ss/SpreadsheetVersion.java +++ b/src/java/org/apache/poi/ss/SpreadsheetVersion.java @@ -25,8 +25,6 @@ import org.apache.poi.ss.util.CellReference; * discernable to the user. It is not intended to deal with low-level issues like file formats. *

* - * For internal POI use only - * * @author Josh Micich * @author Yegor Kozlov */ diff --git a/src/java/org/apache/poi/ss/util/AreaReference.java b/src/java/org/apache/poi/ss/util/AreaReference.java index c3b383edf..ffa0c8888 100644 --- a/src/java/org/apache/poi/ss/util/AreaReference.java +++ b/src/java/org/apache/poi/ss/util/AreaReference.java @@ -17,6 +17,8 @@ package org.apache.poi.ss.util; +import org.apache.poi.ss.SpreadsheetVersion; + import java.util.ArrayList; import java.util.StringTokenizer; @@ -176,7 +178,7 @@ public class AreaReference { // C$1:C$65535 or D$1:F$0 // i.e. absolute from 1st row to 0th one if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() && - botRight.getRow() == 65535 && botRight.isRowAbsolute()) { + botRight.getRow() == SpreadsheetVersion.EXCEL97.getLastRowIndex() && botRight.isRowAbsolute()) { return true; } return false; diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java index 3caf5df31..0b732a298 100644 --- a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java +++ b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java @@ -17,6 +17,8 @@ package org.apache.poi.ss.util; +import org.apache.poi.ss.SpreadsheetVersion; + /** * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'

@@ -27,49 +29,58 @@ package org.apache.poi.ss.util; */ public abstract class CellRangeAddressBase { - /** max 65536 rows in BIFF8 */ - private static final int LAST_ROW_INDEX = 0x00FFFF; - /** max 256 columns in BIFF8 */ - private static final int LAST_COLUMN_INDEX = 0x00FF; - private int _firstRow; private int _firstCol; private int _lastRow; private int _lastCol; protected CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) { - if(!isValid(firstRow, lastRow, firstCol, lastCol)) { - throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow - + ", " + firstCol + ", " + lastCol + ")"); - } _firstRow = firstRow; - _lastRow =lastRow; + _lastRow = lastRow; _firstCol = firstCol; _lastCol = lastCol; } - private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn) { - if(lastRow < 0 || lastRow > LAST_ROW_INDEX) { - return false; - } - if(firstRow < 0 || firstRow > LAST_ROW_INDEX) { - return false; - } - - if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) { - return false; - } - if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) { - return false; - } - return true; - } - - public final boolean isFullColumnRange() { - return _firstRow == 0 && _lastRow == LAST_ROW_INDEX; + /** + * Validate the range limits against the supplied version of Excel + * + * @param ssVersion the version of Excel to validate against + * @throws IllegalArgumentException if the range limits are outside of the allowed range + */ + public void validate(SpreadsheetVersion ssVersion) { + validateRow(_firstRow, ssVersion); + validateRow(_lastRow, ssVersion); + validateColumn(_firstCol, ssVersion); + validateColumn(_lastCol, ssVersion); } + /** + * Runs a bounds check for row numbers + * @param row + */ + private static void validateRow(int row, SpreadsheetVersion ssVersion) { + int maxrow = ssVersion.getLastRowIndex(); + if (row > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow); + if (row < 0) throw new IllegalArgumentException("Minumum row number is 0"); + } + + /** + * Runs a bounds check for column numbers + * @param column + */ + private static void validateColumn(int column, SpreadsheetVersion ssVersion) { + int maxcol = ssVersion.getLastColumnIndex(); + if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol); + if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); + } + + + //TODO use the correct SpreadsheetVersion + public final boolean isFullColumnRange() { + return _firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex(); + } + //TODO use the correct SpreadsheetVersion public final boolean isFullRowRange() { - return _firstCol == 0 && _lastCol == LAST_COLUMN_INDEX; + return _firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex(); } /** diff --git a/src/java/org/apache/poi/ss/util/CellReference.java b/src/java/org/apache/poi/ss/util/CellReference.java index 63d80f1c5..1b19f594a 100644 --- a/src/java/org/apache/poi/ss/util/CellReference.java +++ b/src/java/org/apache/poi/ss/util/CellReference.java @@ -21,6 +21,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.poi.hssf.record.formula.SheetNameFormatter; +import org.apache.poi.ss.SpreadsheetVersion; /** * @@ -61,9 +62,9 @@ public class CellReference { * digits or dot. (They can even end in dot). */ private static final Pattern NAMED_RANGE_NAME_PATTERN = Pattern.compile("[_A-Za-z][_.A-Za-z0-9]*"); - private static final String BIFF8_LAST_COLUMN = "IV"; + private static final String BIFF8_LAST_COLUMN = SpreadsheetVersion.EXCEL97.getLastColumnName(); private static final int BIFF8_LAST_COLUMN_TEXT_LEN = BIFF8_LAST_COLUMN.length(); - private static final String BIFF8_LAST_ROW = String.valueOf(0x10000); + private static final String BIFF8_LAST_ROW = String.valueOf(SpreadsheetVersion.EXCEL97.getMaxRows()); private static final int BIFF8_LAST_ROW_TEXT_LEN = BIFF8_LAST_ROW.length(); private final int _rowIndex; diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index b51724619..07d09fdbe 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -30,6 +30,7 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.util.POILogger; @@ -56,13 +57,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType; public final class XSSFCell implements Cell { private static POILogger logger = POILogFactory.getLogger(XSSFCell.class); - private static final String FILE_FORMAT_NAME = "BIFF12"; - /** - * The maximum number of columns in SpreadsheetML - */ - public static final int LAST_COLUMN_NUMBER = 16384-1; //2^14-1 - private static final String LAST_COLUMN_NAME = "XFD"; - private static final String FALSE_AS_STRING = "0"; private static final String TRUE_AS_STRING = "1"; @@ -791,10 +785,12 @@ public final class XSSFCell implements Cell { * @throws RuntimeException if the bounds are exceeded. */ private static void checkBounds(int cellIndex) { - if (cellIndex < 0 || cellIndex > LAST_COLUMN_NUMBER) { + SpreadsheetVersion v = SpreadsheetVersion.EXCEL2007; + int maxcol = SpreadsheetVersion.EXCEL2007.getLastColumnIndex(); + if (cellIndex < 0 || cellIndex > maxcol) { throw new IllegalArgumentException("Invalid column index (" + cellIndex - + "). Allowable column range for " + FILE_FORMAT_NAME + " is (0.." - + LAST_COLUMN_NUMBER + ") or ('A'..'" + LAST_COLUMN_NAME + "')"); + + "). Allowable column range for " + v.name() + " is (0.." + + maxcol + ") or ('A'..'" + v.getLastColumnName() + "')"); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index 20cbcf367..4cc3db4e5 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -25,6 +25,7 @@ import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.xssf.model.CalculationChain; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.FormulaShifter; @@ -41,12 +42,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; public class XSSFRow implements Row, Comparable { private static final POILogger logger = POILogFactory.getLogger(XSSFRow.class); - private static final String FILE_FORMAT_NAME = "BIFF12"; - /** - * The maximum number of rows in SpreadsheetML - */ - public static final int MAX_ROW_NUMBER = 1048575; //2 ^ 20 - 1 - /** * the xml bean containing all cell definitions for this row */ @@ -328,12 +323,13 @@ public class XSSFRow implements Row, Comparable { * Set the row number of this row. * * @param rowIndex the row number (0-based) - * @throws IllegalArgumentException if rowNum < 0 or greater than {@link #MAX_ROW_NUMBER} + * @throws IllegalArgumentException if rowNum < 0 or greater than 1048575 */ public void setRowNum(int rowIndex) { - if (rowIndex < 0 || rowIndex > MAX_ROW_NUMBER) { + int maxrow = SpreadsheetVersion.EXCEL2007.getLastRowIndex(); + if (rowIndex < 0 || rowIndex > maxrow) { throw new IllegalArgumentException("Invalid row number (" + rowIndex - + ") outside allowable range (0.." + MAX_ROW_NUMBER + ")"); + + ") outside allowable range (0.." + maxrow + ")"); } row.setR(rowIndex + 1); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 8bf5172bd..80d383d75 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -34,6 +34,7 @@ import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.formula.FormulaParser; import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.CalculationChain; import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; @@ -235,6 +236,8 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * @return index of this region */ public int addMergedRegion(CellRangeAddress cra) { + cra.validate(SpreadsheetVersion.EXCEL2007); + CTMergeCells ctMergeCells = worksheet.isSetMergeCells() ? worksheet.getMergeCells() : worksheet.addNewMergeCells(); CTMergeCell ctMergeCell = ctMergeCells.addNewMergeCell(); ctMergeCell.setRef(cra.formatAsString()); @@ -764,9 +767,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { CTMergeCell ctMergeCell = ctMergeCells.getMergeCellArray(index); String ref = ctMergeCell.getRef(); - CellReference cell1 = new CellReference(ref.substring(0, ref.indexOf(":"))); - CellReference cell2 = new CellReference(ref.substring(ref.indexOf(":") + 1)); - return new CellRangeAddress(cell1.getRow(), cell2.getRow(), cell1.getCol(), cell2.getCol()); + return CellRangeAddress.valueOf(ref); } /** diff --git a/src/ooxml/testcases/org/apache/poi/xssf/XSSFITestDataProvider.java b/src/ooxml/testcases/org/apache/poi/xssf/XSSFITestDataProvider.java index fac88830a..6a3a9d119 100755 --- a/src/ooxml/testcases/org/apache/poi/xssf/XSSFITestDataProvider.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/XSSFITestDataProvider.java @@ -17,6 +17,7 @@ package org.apache.poi.xssf; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.hssf.HSSFTestDataSamples; @@ -46,6 +47,10 @@ public final class XSSFITestDataProvider implements ITestDataProvider { return HSSFTestDataSamples.getTestDataFileContent(fileName); } + public SpreadsheetVersion getSpreadsheetVersion(){ + return SpreadsheetVersion.EXCEL2007; + } + private XSSFITestDataProvider(){} private static XSSFITestDataProvider inst = new XSSFITestDataProvider(); public static XSSFITestDataProvider getInstance(){ diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java index 7da2f6228..11a430a47 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java @@ -24,6 +24,7 @@ import java.util.Iterator; import junit.framework.TestCase; import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFITestDataProvider; @@ -43,10 +44,10 @@ public final class TestXSSFRow extends BaseTestRow { } public void testRowBounds() { - baseTestRowBounds(XSSFRow.MAX_ROW_NUMBER); + baseTestRowBounds(SpreadsheetVersion.EXCEL2007.getLastRowIndex()); } public void testCellBounds() { - baseTestCellBounds(XSSFCell.LAST_COLUMN_NUMBER); + baseTestCellBounds(SpreadsheetVersion.EXCEL2007.getLastColumnIndex()); } } diff --git a/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java b/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java index a86bd099e..926ed3d38 100755 --- a/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java +++ b/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Workbook; /** @@ -46,6 +47,10 @@ public final class HSSFITestDataProvider implements ITestDataProvider { return HSSFTestDataSamples.getTestDataFileContent(fileName); } + public SpreadsheetVersion getSpreadsheetVersion(){ + return SpreadsheetVersion.EXCEL2007; + } + private HSSFITestDataProvider(){} private static HSSFITestDataProvider inst = new HSSFITestDataProvider(); public static HSSFITestDataProvider getInstance(){ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java index 1b63f9f23..3c5a0911c 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java @@ -25,6 +25,7 @@ import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.record.BlankRecord; import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.ss.usermodel.BaseTestRow; +import org.apache.poi.ss.SpreadsheetVersion; /** * Test HSSFRow is okay. @@ -39,11 +40,11 @@ public final class TestHSSFRow extends BaseTestRow { } public void testRowBounds() { - baseTestRowBounds(RowRecord.MAX_ROW_NUMBER); + baseTestRowBounds(SpreadsheetVersion.EXCEL97.getLastRowIndex()); } public void testCellBounds() { - baseTestCellBounds(HSSFCell.LAST_COLUMN_NUMBER); + baseTestCellBounds(SpreadsheetVersion.EXCEL97.getLastColumnIndex()); } public void testLastAndFirstColumns_bug46654() { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 65f2f7689..af5395782 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -17,21 +17,17 @@ package org.apache.poi.hssf.usermodel; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import junit.framework.AssertionFailedError; -import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.record.*; -import org.apache.poi.ss.util.Region; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.usermodel.BaseTestSheet; import org.apache.poi.ddf.EscherDgRecord; diff --git a/src/testcases/org/apache/poi/ss/ITestDataProvider.java b/src/testcases/org/apache/poi/ss/ITestDataProvider.java index 983147691..db31b8f39 100755 --- a/src/testcases/org/apache/poi/ss/ITestDataProvider.java +++ b/src/testcases/org/apache/poi/ss/ITestDataProvider.java @@ -50,4 +50,6 @@ public interface ITestDataProvider { * @return an open InputStream for the specified sample file */ byte[] getTestDataFileContent(String fileName); + + SpreadsheetVersion getSpreadsheetVersion(); } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java index c119ce05f..9c51656dd 100755 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java @@ -19,6 +19,7 @@ package org.apache.poi.ss.usermodel; import junit.framework.TestCase; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.util.CellRangeAddress; import java.util.Iterator; @@ -195,6 +196,46 @@ public abstract class BaseTestSheet extends TestCase { assertEquals(3, sheetP.getPrintSetup().getCopies()); } + /** + * Test adding merged regions. If the region's bounds are outside of the allowed range + * then an IllegalArgumentException should be thrown + * + */ + public void testAddMerged() { + Workbook wb = getTestDataProvider().createWorkbook(); + Sheet sheet = wb.createSheet(); + assertEquals(0, sheet.getNumMergedRegions()); + SpreadsheetVersion ssVersion = getTestDataProvider().getSpreadsheetVersion(); + + CellRangeAddress region = new CellRangeAddress(0, 1, 0, 1); + sheet.addMergedRegion(region); + assertEquals(1, sheet.getNumMergedRegions()); + + try { + region = new CellRangeAddress(-1, -1, -1, -1); + sheet.addMergedRegion(region); + fail("Expected exception"); + } catch (IllegalArgumentException e){ + ; + } + try { + region = new CellRangeAddress(0, 0, 0, ssVersion.getLastColumnIndex() + 1); + sheet.addMergedRegion(region); + fail("Expected exception"); + } catch (IllegalArgumentException e){ + ; + } + try { + region = new CellRangeAddress(0, ssVersion.getLastRowIndex() + 1, 0, 1); + sheet.addMergedRegion(region); + fail("Expected exception"); + } catch (IllegalArgumentException e){ + ; + } + assertEquals(1, sheet.getNumMergedRegions()); + + } + /** * When removing one merged region, it would break * diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestWorkbook.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestWorkbook.java index 1a556dc0e..ca1f174b4 100755 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestWorkbook.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestWorkbook.java @@ -108,6 +108,12 @@ public abstract class BaseTestWorkbook extends TestCase { assertEquals("sheet3", workbook.getSheetName(0)); workbook.removeSheetAt(0); assertEquals(0, workbook.getNumberOfSheets()); + + //re-create the sheets + workbook.createSheet("sheet1"); + workbook.createSheet("sheet2"); + workbook.createSheet("sheet3"); + assertEquals(3, workbook.getNumberOfSheets()); } public void testDefaultValues() {