diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 64fb1d0be..be1def70b 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -36,7 +36,11 @@ + Improvements to HSSFDateUtils.isADateFormat, and have HSSFDateUtil.isCellDateFormatted use this + 42999 - [PATCH] - Fix for HSSFPatriarch positioning problems + Support for write-protecting a HSSF workbook Support for querying, setting and un-setting protection on sheets in a HSSF workbook + Initial HSMF (outlook) support Tidy up the javadocs diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 34694bc30..5fe08dbd4 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -33,7 +33,11 @@ + Improvements to HSSFDateUtils.isADateFormat, and have HSSFDateUtil.isCellDateFormatted use this + 42999 - [PATCH] - Fix for HSSFPatriarch positioning problems + Support for write-protecting a HSSF workbook Support for querying, setting and un-setting protection on sheets in a HSSF workbook + Initial HSMF (outlook) support Tidy up the javadocs diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 752f598af..ac3943da4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -256,6 +256,14 @@ public class HSSFCell } return retval; } + + /** + * Returns the Workbook that this Cell is bound to + * @return + */ + protected Workbook getBoundWorkbook() { + return book; + } /** * set the cell's number within the row (0 based) diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java index e978642c5..e2725937f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -18,7 +18,9 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.record.ExtendedFormatRecord; +import org.apache.poi.hssf.record.FormatRecord; import org.apache.poi.hssf.util.*; /** @@ -266,6 +268,17 @@ public class HSSFCellStyle { return format.getFormatIndex(); } + + /** + * Get the contents of the format string, by looking up + * the DataFormat against the supplied workbook + * @see org.apache.poi.hssf.usermodel.HSSFDataFormat + */ + public String getDataFormatString(Workbook workbook) { + HSSFDataFormat format = new HSSFDataFormat(workbook); + + return format.getFormat(getDataFormat()); + } /** * set the font for this style diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java index 2da04e7f4..af16204fd 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java @@ -159,7 +159,7 @@ public class HSSFDateUtil * non US date formats. * * @param formatIndex The index of the format, eg from ExtendedFormatRecord.getFormatIndex - * @param formatString The format string + * @param formatString The format string, eg from FormatRecord.getFormatString * @see #isInternalDateFormat(int) */ public static boolean isADateFormat(int formatIndex, String formatString) { @@ -173,12 +173,26 @@ public class HSSFDateUtil return false; } + String fs = formatString; + // Translate \- into just -, before matching - String fs = formatString.replaceAll("\\\\-","-"); + fs = fs.replaceAll("\\\\-","-"); + // And \, into , + fs = fs.replaceAll("\\\\,",","); + // And '\ ' into ' ' + fs = fs.replaceAll("\\\\ "," "); + + // If it end in ;@, that's some crazy dd/mm vs mm/dd + // switching stuff, which we can ignore + fs = fs.replaceAll(";@", ""); + + // If it starts with [$-...], then it is a date, but + // who knows what that starting bit is all about + fs = fs.replaceAll("\\[\\$\\-.*?\\]", ""); // Otherwise, check it's only made up of: - // y m d - / - if(fs.matches("^[ymd\\-/]+$")) { + // y m d - / , + if(fs.matches("^[ymd\\-/, ]+$")) { return true; } @@ -222,12 +236,34 @@ public class HSSFDateUtil * Check if a cell contains a date * Since dates are stored internally in Excel as double values * we infer it is a date if it is formatted as such. + * @see #isADateFormat(int,string) * @see #isInternalDateFormat(int) */ public static boolean isCellDateFormatted(HSSFCell cell) { if (cell == null) return false; boolean bDate = false; + double d = cell.getNumericCellValue(); + if ( HSSFDateUtil.isValidExcelDate(d) ) { + HSSFCellStyle style = cell.getCellStyle(); + int i = style.getDataFormat(); + String f = style.getDataFormatString(cell.getBoundWorkbook()); + bDate = isADateFormat(i, f); + } + return bDate; + } + /** + * Check if a cell contains a date, checking only for internal + * excel date formats. + * As Excel stores a great many of its dates in "non-internal" + * date formats, you will not normally want to use this method. + * @see #isADateFormat(int,string) + * @see #isInternalDateFormat(int) + */ + public static boolean isCellInternalDateFormatted(HSSFCell cell) { + if (cell == null) return false; + boolean bDate = false; + double d = cell.getNumericCellValue(); if ( HSSFDateUtil.isValidExcelDate(d) ) { HSSFCellStyle style = cell.getCellStyle(); diff --git a/src/testcases/org/apache/poi/hssf/data/DateFormats.xls b/src/testcases/org/apache/poi/hssf/data/DateFormats.xls new file mode 100644 index 000000000..6b2c3480b Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/DateFormats.xls differ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java index 174e01972..c1516f253 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java @@ -21,11 +21,15 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; +import java.io.FileInputStream; import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; +import org.apache.poi.hssf.model.Workbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + /** * Class TestHSSFDateUtil * @@ -215,6 +219,14 @@ public class TestHSSFDateUtil "dd/mm/yy", "dd/mm/yyyy", "dd/mmm/yy", "dd-mm-yy", "dd-mm-yyyy", "dd\\-mm\\-yy", // Sometimes escaped + + // These crazy ones are valid + "yyyy-mm-dd;@", "yyyy/mm/dd;@", + "dd-mm-yy;@", "dd-mm-yyyy;@", + // These even crazier ones are also valid + // (who knows what they mean though...) + "[$-F800]dddd\\,\\ mmm\\ dd\\,\\ yyyy", + "[$-F900]ddd/mm/yyy", }; for(int i=0; i