diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 8dd956c16..acf5cfeab 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + Support for specifying a policy to HSSF on missing / blank cells when fetching 44937 - Partial support for extracting Escher images from HWPF files 44824 - Avoid an infinite loop when reading some HWPF pictures 44898 - Correctly handle short last blocks in POIFS diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 796e2e203..41b47b996 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + Support for specifying a policy to HSSF on missing / blank cells when fetching 44937 - Partial support for extracting Escher images from HWPF files 44824 - Avoid an infinite loop when reading some HWPF pictures 44898 - Correctly handle short last blocks in POIFS diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java index def79f6d3..f833b7f44 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -300,6 +300,36 @@ public final class HSSFRow implements Comparable { if(cellnum<0||cellnum>=cells.length) return null; return cells[cellnum]; } + + /** + * Get the hssfcell representing a given column (logical cell) + * 0-based. If you ask for a cell that is not defined, then + * your supplied policy says what to do + * + * @param cellnum 0 based column number + * @param policy Policy on blank / missing cells + * @return representing that column or null if undefined + policy allows. + */ + public HSSFCell getCell(int cellnum, MissingCellPolicy policy) { + HSSFCell cell = getCell(cellnum); + if(policy == RETURN_NULL_AND_BLANK) { + return cell; + } + if(policy == RETURN_BLANK_AS_NULL) { + if(cell == null) return cell; + if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) { + return null; + } + return cell; + } + if(policy == CREATE_NULL_AS_BLANK) { + if(cell == null) { + return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK); + } + return cell; + } + throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")"); + } /** * get the number of the first cell contained in this row. @@ -466,6 +496,26 @@ public final class HSSFRow implements Comparable { return cellnum; } + /** + * Used to specify the different possible policies + * if for the case of null and blank cells + */ + public static class MissingCellPolicy { + private static int NEXT_ID = 1; + private final int id; + private MissingCellPolicy() { + this.id = NEXT_ID++; + } + } + + /** Missing cells are returned as null, Blank cells are returned as normal */ + public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy(); + /** Missing cells are returned as null, as are blank cells */ + public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy(); + /** A new, blank cell is created for missing cells. Blank cells are returned as normal */ + public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy(); + + /** * @return cell iterator of the physically defined cells. * Note that the 4th element might well not be cell 4, as the iterator @@ -484,6 +534,9 @@ public final class HSSFRow implements Comparable { return cellIterator(); } + /** + * An iterator over the (physical) cells in the row. + */ private class CellIterator implements Iterator { int thisId=-1; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java index 7611abb51..d307a0e25 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java @@ -204,4 +204,64 @@ public final class TestHSSFRow extends TestCase { row.createCell((short) 255); assertEquals(256, row.getLastCellNum()); } + + /** + * Tests for the missing/blank cell policy stuff + */ + public void testGetCellPolicy() throws Exception { + HSSFWorkbook book = new HSSFWorkbook(); + HSSFSheet sheet = book.createSheet("test"); + HSSFRow row = sheet.createRow(0); + + // 0 -> string + // 1 -> num + // 2 missing + // 3 missing + // 4 -> blank + // 5 -> num + row.createCell((short)0).setCellValue(new HSSFRichTextString("test")); + row.createCell((short)1).setCellValue(3.2); + row.createCell((short)4, HSSFCell.CELL_TYPE_BLANK); + row.createCell((short)5).setCellValue(4); + + // First up, no policy + assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType()); + assertEquals(null, row.getCell(2)); + assertEquals(null, row.getCell(3)); + assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5).getCellType()); + + // RETURN_NULL_AND_BLANK - same as default + assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.RETURN_NULL_AND_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.RETURN_NULL_AND_BLANK).getCellType()); + assertEquals(null, row.getCell(2, HSSFRow.RETURN_NULL_AND_BLANK)); + assertEquals(null, row.getCell(3, HSSFRow.RETURN_NULL_AND_BLANK)); + assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4, HSSFRow.RETURN_NULL_AND_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.RETURN_NULL_AND_BLANK).getCellType()); + + // RETURN_BLANK_AS_NULL - nearly the same + assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.RETURN_BLANK_AS_NULL).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.RETURN_BLANK_AS_NULL).getCellType()); + assertEquals(null, row.getCell(2, HSSFRow.RETURN_BLANK_AS_NULL)); + assertEquals(null, row.getCell(3, HSSFRow.RETURN_BLANK_AS_NULL)); + assertEquals(null, row.getCell(4, HSSFRow.RETURN_BLANK_AS_NULL)); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.RETURN_BLANK_AS_NULL).getCellType()); + + // CREATE_NULL_AS_BLANK - creates as needed + assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(2, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(3, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_BLANK, row.getCell(4, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5, HSSFRow.CREATE_NULL_AS_BLANK).getCellType()); + + // Check created ones get the right column + assertEquals((short)0, row.getCell(0, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + assertEquals((short)1, row.getCell(1, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + assertEquals((short)2, row.getCell(2, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + assertEquals((short)3, row.getCell(3, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + assertEquals((short)4, row.getCell(4, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + assertEquals((short)5, row.getCell(5, HSSFRow.CREATE_NULL_AS_BLANK).getCellNum()); + } }