diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index fc755ea79..5a90a0463 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + Port support for setting a policy on missing / blank cells when fetching, to XSSF too Common text extraction factory, which returns the correct POITextExtractor for the supplied data Text Extraction support for the new OOXML files (.xlsx, .docx and .pptx) Initial support for processing OOXML Excel files (.xlsx), both directly through XSSF, and also through the new common UserModel @@ -44,9 +45,10 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx - 45025 - improved FormulaParser parse error messages - 45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable - 45066 - fixed sheet encoding size mismatch problems + Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level + 45025 - improved FormulaParser parse error messages + 45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable + 45066 - fixed sheet encoding size mismatch problems 45003 - Support embeded HDGF visio documents 45001 - Partial fix for HWPF Range.insertBefore() and Range.delete() with unicode characters 44977 - Support for AM/PM in excel date formats diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index ba2c99ec6..6709b3271 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + Port support for setting a policy on missing / blank cells when fetching, to XSSF too Common text extraction factory, which returns the correct POITextExtractor for the supplied data Text Extraction support for the new OOXML files (.xlsx, .docx and .pptx) Initial support for processing OOXML Excel files (.xlsx), both directly through XSSF, and also through the new common UserModel @@ -41,9 +42,10 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx - 45025 - improved FormulaParser parse error messages - 45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable - 45066 - fixed sheet encoding size mismatch problems + Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level + 45025 - improved FormulaParser parse error messages + 45046 - allowed EXTERNALBOOK(0x01AE) to be optional in the LinkTable + 45066 - fixed sheet encoding size mismatch problems 45003 - Support embeded HDGF visio documents 45001 - Partial fix for HWPF Range.insertBefore() and Range.delete() with unicode characters 44977 - Support for AM/PM in excel date formats diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java index 056c872e7..3e95aaee4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -295,8 +295,23 @@ public final class HSSFRow implements Comparable, Row { /** * Get the hssfcell representing a given column (logical cell) - * 0-based. If you ask for a cell that is not defined.... + * 0-based. If you ask for a cell that is not defined, then * you get a null. + * This is the basic call, with no policies applied + * + * @param cellnum 0 based column number + * @return HSSFCell representing that column or null if undefined. + */ + private HSSFCell retrieveCell(int cellnum) { + 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 + * you get a null, unless you have set a different + * {@link MissingCellPolicy} on the base workbook. * Short method signature provided to retain binary * compatibility. * @@ -307,17 +322,18 @@ public final class HSSFRow implements Comparable, Row { int ushortCellNum = cellnum & 0x0000FFFF; // avoid sign extension return getCell(ushortCellNum); } + /** * Get the hssfcell representing a given column (logical cell) - * 0-based. If you ask for a cell that is not defined.... - * you get a null. + * 0-based. If you ask for a cell that is not defined then + * you get a null, unless you have set a different + * {@link MissingCellPolicy} on the base workbook. * * @param cellnum 0 based column number * @return HSSFCell representing that column or null if undefined. */ public HSSFCell getCell(int cellnum) { - if(cellnum<0||cellnum>=cells.length) return null; - return cells[cellnum]; + return getCell(cellnum, book.getMissingCellPolicy()); } /** @@ -330,7 +346,7 @@ public final class HSSFRow implements Comparable, Row { * @return representing that column or null if undefined + policy allows. */ public HSSFCell getCell(int cellnum, MissingCellPolicy policy) { - HSSFCell cell = getCell(cellnum); + HSSFCell cell = retrieveCell(cellnum); if(policy == RETURN_NULL_AND_BLANK) { return cell; } @@ -354,7 +370,6 @@ public final class HSSFRow implements Comparable, Row { * get the number of the first cell contained in this row. * @return short representing the first logical cell in the row, or -1 if the row does not contain any cells. */ - public short getFirstCellNum() { if (getPhysicalNumberOfCells() == 0) diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 32fce2f09..c059b028a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -51,7 +51,6 @@ import org.apache.poi.hssf.record.RecordFactory; import org.apache.poi.hssf.record.SSTRecord; import org.apache.poi.hssf.record.UnicodeString; import org.apache.poi.hssf.record.UnknownRecord; -import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.formula.Area3DPtg; import org.apache.poi.hssf.record.formula.MemFuncPtg; import org.apache.poi.hssf.record.formula.UnionPtg; @@ -60,6 +59,7 @@ import org.apache.poi.hssf.util.SheetReferences; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -119,6 +119,13 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm * someplace else. */ private HSSFDataFormat formatter; + + /** + * The policy to apply in the event of missing or + * blank cells when fetching from a row. + * See {@link MissingCellPolicy} + */ + private MissingCellPolicy missingCellPolicy = HSSFRow.RETURN_NULL_AND_BLANK; /** Extended windows meta file */ @@ -362,8 +369,28 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm log.log(POILogger.DEBUG, "convertLabelRecords exit"); } + /** + * Retrieves the current policy on what to do when + * getting missing or blank cells from a row. + * The default is to return blank and null cells. + * {@link MissingCellPolicy} + */ + public MissingCellPolicy getMissingCellPolicy() { + return missingCellPolicy; + } - /** + /** + * Sets the policy on what to do when + * getting missing or blank cells from a row. + * This will then apply to all calls to + * {@link Row.getCell()}. See + * {@link MissingCellPolicy} + */ + public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) { + this.missingCellPolicy = missingCellPolicy; + } + + /** * sets the order of appearance for a given sheet. * * @param sheetname the name of the sheet to reorder diff --git a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Workbook.java b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Workbook.java index f69bb726c..f68fd35c6 100644 --- a/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Workbook.java +++ b/src/ooxml/interfaces-jdk14/org/apache/poi/ss/usermodel/Workbook.java @@ -17,6 +17,7 @@ package org.apache.poi.ss.usermodel; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util.SheetReferences; @@ -44,4 +45,20 @@ public interface Workbook { int getExternalSheetIndex(int internalSheetIndex); CreationHelper getCreationHelper(); + + /** + * Retrieves the current policy on what to do when + * getting missing or blank cells from a row. + * The default is to return blank and null cells. + * {@link MissingCellPolicy} + */ + MissingCellPolicy getMissingCellPolicy(); + /** + * Sets the policy on what to do when + * getting missing or blank cells from a row. + * This will then apply to all calls to + * {@link Row.getCell()}. See + * {@link MissingCellPolicy} + */ + void setMissingCellPolicy(MissingCellPolicy missingCellPolicy); } diff --git a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java index 53f439b71..dbc7fdc97 100644 --- a/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java +++ b/src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.List; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.ss.util.SheetReferences; public interface Workbook { @@ -406,6 +407,22 @@ public interface Workbook { */ void removePrintArea(int sheetIndex); + /** + * Retrieves the current policy on what to do when + * getting missing or blank cells from a row. + * The default is to return blank and null cells. + * {@link MissingCellPolicy} + */ + MissingCellPolicy getMissingCellPolicy(); + /** + * Sets the policy on what to do when + * getting missing or blank cells from a row. + * This will then apply to all calls to + * {@link Row.getCell()}. See + * {@link MissingCellPolicy} + */ + void setMissingCellPolicy(MissingCellPolicy missingCellPolicy); + /** creates a new named range and add it to the model * @return named range high level */ @@ -493,4 +510,4 @@ public interface Workbook { * classes. */ CreationHelper getCreationHelper(); -} \ No newline at end of file +} 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 3047368e2..a2d188a3d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -129,7 +129,7 @@ public class XSSFRow implements Row { return xcell; } - public Cell getCell(int cellnum) { + private Cell retrieveCell(int cellnum) { Iterator it = cellIterator(); for ( ; it.hasNext() ; ) { Cell cell = it.next(); @@ -140,8 +140,21 @@ public class XSSFRow implements Row { return null; } + /** + * Returns the cell at the given (0 based) index, + * with the {@link MissingCellPolicy} from the + * parent Workbook. + */ + public Cell getCell(int cellnum) { + return getCell(cellnum, sheet.getWorkbook().getMissingCellPolicy()); + } + + /** + * Returns the cell at the given (0 based) index, + * with the specified {@link MissingCellPolicy} + */ public Cell getCell(int cellnum, MissingCellPolicy policy) { - Cell cell = getCell(cellnum); + Cell cell = retrieveCell(cellnum); if(policy == RETURN_NULL_AND_BLANK) { return cell; } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index 37f130a74..9fe9ff80a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -35,10 +35,12 @@ import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Palette; import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.SharedStringSource; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.StylesSource; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.ss.util.SheetReferences; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -220,6 +222,8 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { private SharedStringSource sharedStringSource; private StylesSource stylesSource; + + private MissingCellPolicy missingCellPolicy = Row.RETURN_NULL_AND_BLANK; private static POILogger log = POILogFactory.getLogger(XSSFWorkbook.class); @@ -634,6 +638,26 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { this.workbook.getSheets().removeSheet(index); } + /** + * Retrieves the current policy on what to do when + * getting missing or blank cells from a row. + * The default is to return blank and null cells. + * {@link MissingCellPolicy} + */ + public MissingCellPolicy getMissingCellPolicy() { + return missingCellPolicy; + } + /** + * Sets the policy on what to do when + * getting missing or blank cells from a row. + * This will then apply to all calls to + * {@link Row.getCell()}. See + * {@link MissingCellPolicy} + */ + public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) { + this.missingCellPolicy = missingCellPolicy; + } + public void setBackupFlag(boolean backupValue) { // TODO Auto-generated method stub diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java index d307a0e25..3c8f3a873 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; /** * Test HSSFRow is okay. @@ -224,7 +225,7 @@ public final class TestHSSFRow extends TestCase { row.createCell((short)4, HSSFCell.CELL_TYPE_BLANK); row.createCell((short)5).setCellValue(4); - // First up, no policy + // First up, no policy given, uses default assertEquals(HSSFCell.CELL_TYPE_STRING, row.getCell(0).getCellType()); assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType()); assertEquals(null, row.getCell(2)); @@ -263,5 +264,17 @@ public final class TestHSSFRow extends TestCase { 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()); + + + // Now change the cell policy on the workbook, check + // that that is now used if no policy given + book.setMissingCellPolicy(HSSFRow.RETURN_BLANK_AS_NULL); + + 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(null, row.getCell(4)); + assertEquals(HSSFCell.CELL_TYPE_NUMERIC, row.getCell(5).getCellType()); } }