diff options
author | Josh Micich <josh@apache.org> | 2008-07-28 20:08:15 +0000 |
---|---|---|
committer | Josh Micich <josh@apache.org> | 2008-07-28 20:08:15 +0000 |
commit | 903202916b619a886ca98d997220ff806d2b44d5 (patch) | |
tree | 37a909c50ef3560f01ee285dc12d43e6375079fc /src/java | |
parent | cfb357a62c6203bd7d1dfde123f703b82cd81e39 (diff) | |
download | poi-903202916b619a886ca98d997220ff806d2b44d5.tar.gz poi-903202916b619a886ca98d997220ff806d2b44d5.zip |
More tweaks for bug 45404. Fixes for JDK 1.4, improved member scoping and formatting.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@680470 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
-rw-r--r-- | src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java | 722 |
1 files changed, 350 insertions, 372 deletions
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java index e186cf73c3..67291a22f1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java @@ -68,78 +68,64 @@ import java.util.regex.Pattern; * can override the default format pattern with <code> * HSSFDataFormatter.setDefaultNumberFormat(Format)</code>. <b>Note:</b> the * default format will only be used when a Format cannot be created from the - * cell's data format string. - * + * cell's data format string. + * * @author James May (james dot may at fmr dot com) * */ -public class HSSFDataFormatter { +public final class HSSFDataFormatter { /** Pattern to find a number format: "0" or "#" */ - protected Pattern numPattern; - + private static final Pattern numPattern = Pattern.compile("[0#]+"); + /** Pattern to find days of week as text "ddd...." */ - protected Pattern daysAsText; - + private static final Pattern daysAsText = Pattern.compile("([d]{3,})", Pattern.CASE_INSENSITIVE); + /** Pattern to find "AM/PM" marker */ - protected Pattern amPmPattern; + private static final Pattern amPmPattern = Pattern.compile("((A|P)[M/P]*)", Pattern.CASE_INSENSITIVE); /** A regex to find patterns like [$$-1009] and [$�-452]. */ - protected Pattern specialPatternGroup; - + private static final Pattern specialPatternGroup = Pattern.compile("(\\[\\$[^-\\]]*-[0-9A-Z]+\\])"); + /** <em>General</em> format for whole numbers. */ - protected Format generalWholeNumFormat; - + private static final Format generalWholeNumFormat = new DecimalFormat("#"); + /** <em>General</em> format for decimal numbers. */ - protected Format generalDecimalNumFormat; - + private static final Format generalDecimalNumFormat = new DecimalFormat("#.##########"); + /** A default format to use when a number pattern cannot be parsed. */ - protected Format defaultNumFormat; - - /** + private Format defaultNumFormat; + + /** * A map to cache formats. * Map<String,Format> formats */ - protected Map formats; - + private final Map formats; /** * Constructor */ public HSSFDataFormatter() { - numPattern = Pattern.compile("[0#]+"); - daysAsText = Pattern.compile("([d]{3,})", Pattern.CASE_INSENSITIVE); - amPmPattern = Pattern.compile("((A|P)[M/P]*)", Pattern.CASE_INSENSITIVE); - specialPatternGroup = Pattern.compile("(\\[\\$[^-\\]]*-[0-9A-Z]+\\])"); - generalWholeNumFormat = new DecimalFormat("#"); - generalDecimalNumFormat = new DecimalFormat("#.##########"); formats = new HashMap(); - + // init built-in formats - init(); - } - /** - * Initialize the formatter. Called after construction. - */ - protected void init() { - - ZipPlusFourFormat zipFormat = new ZipPlusFourFormat(); + Format zipFormat = ZipPlusFourFormat.instance; addFormat("00000\\-0000", zipFormat); addFormat("00000-0000", zipFormat); - - PhoneFormat phoneFormat = new PhoneFormat(); + + Format phoneFormat = PhoneFormat.instance; // allow for format string variations addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat); addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat); addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat); - addFormat("###-####;(###) ###-####", phoneFormat); - - SSNFormat ssnFormat = new SSNFormat(); - addFormat("000\\-00\\-0000", ssnFormat); - addFormat("000-00-0000", ssnFormat); + addFormat("###-####;(###) ###-####", phoneFormat); + + Format ssnFormat = SSNFormat.instance; + addFormat("000\\-00\\-0000", ssnFormat); + addFormat("000-00-0000", ssnFormat); } - + /** * Return a Format for the given cell if one exists, otherwise try to * create one. This method will return <code>null</code> if the any of the @@ -149,15 +135,15 @@ public class HSSFDataFormatter { * <li>the style's data format string is null or empty</li> * <li>the format string cannot be recognized as either a number or date</li> * </ul> - * + * * @param cell The cell to retrieve a Format for * @return A Format for the format String */ - protected Format getFormat(HSSFCell cell) { + private Format getFormat(HSSFCell cell) { if ( cell.getCellStyle() == null) { return null; } - + int formatIndex = cell.getCellStyle().getDataFormat(); String formatStr = cell.getCellStyle().getDataFormatString(); if(formatStr == null || formatStr.trim().length() == 0) { @@ -165,382 +151,375 @@ public class HSSFDataFormatter { } return getFormat(cell.getNumericCellValue(), formatIndex, formatStr); } - + private Format getFormat(double cellValue, int formatIndex, String formatStr) { Format format = (Format)formats.get(formatStr); if (format != null) { return format; - } else if (formatStr.equals("General")) { + } + if (formatStr.equals("General")) { if (HSSFDataFormatter.isWholeNumber(cellValue)) { return generalWholeNumFormat; - } else { - return generalDecimalNumFormat; } - } else { - format = createFormat(cellValue, formatIndex, formatStr); - formats.put(formatStr, format); - return format; + return generalDecimalNumFormat; } + format = createFormat(cellValue, formatIndex, formatStr); + formats.put(formatStr, format); + return format; } - + /** * Create and return a Format based on the format string from a cell's * style. If the pattern cannot be parsed, return a default pattern. - * + * * @param cell The Excel cell * @return A Format representing the excel format. May return null. */ - protected Format createFormat(HSSFCell cell) { - String sFormat = cell.getCellStyle().getDataFormatString(); - + public Format createFormat(HSSFCell cell) { + int formatIndex = cell.getCellStyle().getDataFormat(); String formatStr = cell.getCellStyle().getDataFormatString(); - return createFormat(cell.getNumericCellValue(), formatIndex, formatStr); + return createFormat(cell.getNumericCellValue(), formatIndex, formatStr); } - + private Format createFormat(double cellValue, int formatIndex, String sFormat) { // remove color formatting if present String formatStr = sFormat.replaceAll("\\[[a-zA-Z]*\\]", ""); - - // Try to extract special characters like currency - // Need to re-create the matcher each time, as the string - // will potentially change on each pass - Matcher m; - try { - while((m = specialPatternGroup.matcher(formatStr)).find()) { - String match = m.group(); - String symbol = match.substring(match.indexOf('$') + 1, match.indexOf('-')); - if (symbol.indexOf('$') > -1) { - StringBuffer sb = new StringBuffer(); - sb.append(symbol.substring(0, symbol.indexOf('$'))); - sb.append('\\'); - sb.append(symbol.substring(symbol.indexOf('$'), symbol.length())); - symbol = sb.toString(); - } - formatStr = m.replaceAll(symbol); + + // try to extract special characters like currency + Matcher m = specialPatternGroup.matcher(formatStr); + while(m.find()) { + String match = m.group(); + String symbol = match.substring(match.indexOf('$') + 1, match.indexOf('-')); + if (symbol.indexOf('$') > -1) { + StringBuffer sb = new StringBuffer(); + sb.append(symbol.substring(0, symbol.indexOf('$'))); + sb.append('\\'); + sb.append(symbol.substring(symbol.indexOf('$'), symbol.length())); + symbol = sb.toString(); } - } catch (Exception e) { - return getDefaultFormat(cellValue); + formatStr = m.replaceAll(symbol); + m = specialPatternGroup.matcher(formatStr); } - + if(formatStr == null || formatStr.trim().length() == 0) { return getDefaultFormat(cellValue); } - Format returnVal = null; - StringBuffer sb = null; - - if(HSSFDateUtil.isADateFormat(formatIndex,formatStr) && - HSSFDateUtil.isValidExcelDate(cellValue)) { - formatStr = formatStr.replaceAll("\\\\-","-"); - formatStr = formatStr.replaceAll("\\\\,",","); - formatStr = formatStr.replaceAll("\\\\ "," "); - formatStr = formatStr.replaceAll(";@", ""); - boolean hasAmPm = false; - Matcher amPmMatcher = amPmPattern.matcher(formatStr); - while (amPmMatcher.find()) { - formatStr = amPmMatcher.replaceAll("a"); - hasAmPm = true; - } - - Matcher dateMatcher = daysAsText.matcher(formatStr); - if (dateMatcher.find()) { - String match = dateMatcher.group(0); - formatStr = dateMatcher.replaceAll(match.toUpperCase().replaceAll("D", "E")); - } - - // Convert excel date format to SimpleDateFormat. - // Excel uses lower case 'm' for both minutes and months. - // From Excel help: - /* - The "m" or "mm" code must appear immediately after the "h" or"hh" - code or immediately before the "ss" code; otherwise, Microsoft - Excel displays the month instead of minutes." - */ - - sb = new StringBuffer(); - char[] chars = formatStr.toCharArray(); - boolean mIsMonth = true; - List ms = new ArrayList(); - for(int j=0; j<chars.length; j++) { - char c = chars[j]; - if (c == 'h' || c == 'H') { - mIsMonth = false; - if (hasAmPm) { - sb.append('h'); - } else { - sb.append('H'); - } - } - else if (c == 'm') { - if(mIsMonth) { - sb.append('M'); - ms.add( - new Integer(sb.length() -1) - ); - } else { - sb.append('m'); - } - } - else if (c == 's' || c == 'S') { - sb.append('s'); - // if 'M' precedes 's' it should be minutes ('m') - for (int i = 0; i < ms.size(); i++) { - int index = ((Integer)ms.get(i)).intValue(); - if (sb.charAt(index) == 'M') { - sb.replace(index, index+1, "m"); - } - } - mIsMonth = true; - ms.clear(); - } - else if (Character.isLetter(c)) { - mIsMonth = true; - ms.clear(); - if (c == 'y' || c == 'Y') { - sb.append('y'); - } - else if (c == 'd' || c == 'D') { - sb.append('d'); - } - else { - sb.append(c); - } - } - else { - sb.append(c); - } - } - formatStr = sb.toString(); - - try { - returnVal = new SimpleDateFormat(formatStr); - } catch(IllegalArgumentException iae) { - - // the pattern could not be parsed correctly, - // so fall back to the default number format - return getDefaultFormat(cellValue); - } - - } else if (numPattern.matcher(formatStr).find()) { - sb = new StringBuffer(formatStr); - for (int i = 0; i < sb.length(); i++) { - char c = sb.charAt(i); - //handle (#,##0_); - if (c == '(') { - int idx = sb.indexOf(")", i); - if (idx > -1 && sb.charAt(idx -1) == '_') { - sb.deleteCharAt(idx); - sb.deleteCharAt(idx - 1); - sb.deleteCharAt(i); - i--; + + if(HSSFDateUtil.isADateFormat(formatIndex,formatStr) && + HSSFDateUtil.isValidExcelDate(cellValue)) { + return createDateFormat(formatStr, cellValue); + } + if (numPattern.matcher(formatStr).find()) { + return createNumberFormat(formatStr, cellValue); + } + // TODO - when does this occur? + return null; + } + + private Format createDateFormat(String pFormatStr, double cellValue) { + String formatStr = pFormatStr; + formatStr = formatStr.replaceAll("\\\\-","-"); + formatStr = formatStr.replaceAll("\\\\,",","); + formatStr = formatStr.replaceAll("\\\\ "," "); + formatStr = formatStr.replaceAll(";@", ""); + boolean hasAmPm = false; + Matcher amPmMatcher = amPmPattern.matcher(formatStr); + while (amPmMatcher.find()) { + formatStr = amPmMatcher.replaceAll("@"); + hasAmPm = true; + amPmMatcher = amPmPattern.matcher(formatStr); + } + formatStr = formatStr.replaceAll("@", "a"); + + + Matcher dateMatcher = daysAsText.matcher(formatStr); + if (dateMatcher.find()) { + String match = dateMatcher.group(0); + formatStr = dateMatcher.replaceAll(match.toUpperCase().replaceAll("D", "E")); + } + + // Convert excel date format to SimpleDateFormat. + // Excel uses lower case 'm' for both minutes and months. + // From Excel help: + /* + The "m" or "mm" code must appear immediately after the "h" or"hh" + code or immediately before the "ss" code; otherwise, Microsoft + Excel displays the month instead of minutes." + */ + + StringBuffer sb = new StringBuffer(); + char[] chars = formatStr.toCharArray(); + boolean mIsMonth = true; + List ms = new ArrayList(); + for(int j=0; j<chars.length; j++) { + char c = chars[j]; + if (c == 'h' || c == 'H') { + mIsMonth = false; + if (hasAmPm) { + sb.append('h'); + } else { + sb.append('H'); + } + } + else if (c == 'm') { + if(mIsMonth) { + sb.append('M'); + ms.add( + new Integer(sb.length() -1) + ); + } else { + sb.append('m'); + } + } + else if (c == 's' || c == 'S') { + sb.append('s'); + // if 'M' precedes 's' it should be minutes ('m') + for (int i = 0; i < ms.size(); i++) { + int index = ((Integer)ms.get(i)).intValue(); + if (sb.charAt(index) == 'M') { + sb.replace(index, index+1, "m"); } - } else if (c == ')' && i > 0 && sb.charAt(i - 1) == '_') { - sb.deleteCharAt(i); - sb.deleteCharAt(i - 1); - i--; - // remove quotes and back slashes - } else if (c == '\\' || c == '"') { - sb.deleteCharAt(i); - i--; - - // for scientific/engineering notation - } else if (c == '+' && i > 0 && sb.charAt(i - 1) == 'E') { + } + mIsMonth = true; + ms.clear(); + } + else if (Character.isLetter(c)) { + mIsMonth = true; + ms.clear(); + if (c == 'y' || c == 'Y') { + sb.append('y'); + } + else if (c == 'd' || c == 'D') { + sb.append('d'); + } + else { + sb.append(c); + } + } + else { + sb.append(c); + } + } + formatStr = sb.toString(); + + try { + return new SimpleDateFormat(formatStr); + } catch(IllegalArgumentException iae) { + + // the pattern could not be parsed correctly, + // so fall back to the default number format + return getDefaultFormat(cellValue); + } + + } + + private Format createNumberFormat(String formatStr, double cellValue) { + StringBuffer sb = new StringBuffer(formatStr); + for (int i = 0; i < sb.length(); i++) { + char c = sb.charAt(i); + //handle (#,##0_); + if (c == '(') { + int idx = sb.indexOf(")", i); + if (idx > -1 && sb.charAt(idx -1) == '_') { + sb.deleteCharAt(idx); + sb.deleteCharAt(idx - 1); sb.deleteCharAt(i); i--; - } - } - formatStr = sb.toString(); - try { - returnVal = new DecimalFormat(formatStr); - } catch(IllegalArgumentException iae) { + } + } else if (c == ')' && i > 0 && sb.charAt(i - 1) == '_') { + sb.deleteCharAt(i); + sb.deleteCharAt(i - 1); + i--; + // remove quotes and back slashes + } else if (c == '\\' || c == '"') { + sb.deleteCharAt(i); + i--; - // the pattern could not be parsed correctly, - // so fall back to the default number format - return getDefaultFormat(cellValue); + // for scientific/engineering notation + } else if (c == '+' && i > 0 && sb.charAt(i - 1) == 'E') { + sb.deleteCharAt(i); + i--; } } - return returnVal; + + try { + return new DecimalFormat(sb.toString()); + } catch(IllegalArgumentException iae) { + + // the pattern could not be parsed correctly, + // so fall back to the default number format + return getDefaultFormat(cellValue); + } } - + /** * Return true if the double value represents a whole number * @param d the double value to check - * @return true if d is a whole number + * @return <code>true</code> if d is a whole number */ private static boolean isWholeNumber(double d) { return d == Math.floor(d); } - + /** * Returns a default format for a cell. * @param cell The cell * @return a default format */ - protected Format getDefaultFormat(HSSFCell cell) { + public Format getDefaultFormat(HSSFCell cell) { return getDefaultFormat(cell.getNumericCellValue()); } private Format getDefaultFormat(double cellValue) { // for numeric cells try user supplied default if (defaultNumFormat != null) { return defaultNumFormat; - - // otherwise use general format - } else if (isWholeNumber(cellValue)){ + + // otherwise use general format + } + if (isWholeNumber(cellValue)){ return generalWholeNumFormat; - } else { - return generalDecimalNumFormat; } + return generalDecimalNumFormat; } - + /** * Returns the formatted value of an Excel date as a <tt>String</tt> based * on the cell's <code>DataFormat</code>. i.e. "Thursday, January 02, 2003" * , "01/02/2003" , "02-Jan" , etc. - * + * * @param cell The cell * @return a formatted date string - */ - protected String getFormattedDateString(HSSFCell cell) { - Format dateFormat = getFormat(cell); - Date d = cell.getDateCellValue(); - if (dateFormat != null) { - return dateFormat.format(d); - } else { - return d.toString(); - } - } - + */ + private String getFormattedDateString(HSSFCell cell) { + Format dateFormat = getFormat(cell); + Date d = cell.getDateCellValue(); + if (dateFormat != null) { + return dateFormat.format(d); + } + return d.toString(); + } + /** * Returns the formatted value of an Excel number as a <tt>String</tt> * based on the cell's <code>DataFormat</code>. Supported formats include * currency, percents, decimals, phone number, SSN, etc.: * "61.54%", "$100.00", "(800) 555-1234". - * + * * @param cell The cell * @return a formatted number string - */ - protected String getFormattedNumberString(HSSFCell cell) { - - Format numberFormat = getFormat(cell); - double d = cell.getNumericCellValue(); - if (numberFormat != null) { - return numberFormat.format(new Double(d)); - } else { - return String.valueOf(d); - } - } - - /** - * Formats the given raw cell value, based on the supplied - * format index and string, according to excel style rules. - * @see #formatCellValue(HSSFCell) - */ - public String formatRawCellContents(double value, int formatIndex, String formatString) { - // Is it a date? - if(HSSFDateUtil.isADateFormat(formatIndex,formatString) && - HSSFDateUtil.isValidExcelDate(value)) { - - Format dateFormat = getFormat(value, formatIndex, formatString); - Date d = HSSFDateUtil.getJavaDate(value); - if (dateFormat != null) { - return dateFormat.format(d); - } else { - return d.toString(); - } - } else { - // Number - Format numberFormat = getFormat(value, formatIndex, formatString); - if (numberFormat != null) { - return numberFormat.format(new Double(value)); - } else { - return String.valueOf(value); - } - } - } - + */ + private String getFormattedNumberString(HSSFCell cell) { + + Format numberFormat = getFormat(cell); + double d = cell.getNumericCellValue(); + if (numberFormat == null) { + return String.valueOf(d); + } + return numberFormat.format(new Double(d)); + } + + /** + * Formats the given raw cell value, based on the supplied + * format index and string, according to excel style rules. + * @see #formatCellValue(HSSFCell) + */ + public String formatRawCellContents(double value, int formatIndex, String formatString) { + // Is it a date? + if(HSSFDateUtil.isADateFormat(formatIndex,formatString) && + HSSFDateUtil.isValidExcelDate(value)) { + + Format dateFormat = getFormat(value, formatIndex, formatString); + Date d = HSSFDateUtil.getJavaDate(value); + if (dateFormat == null) { + return d.toString(); + } + return dateFormat.format(d); + } + // else Number + Format numberFormat = getFormat(value, formatIndex, formatString); + if (numberFormat == null) { + return String.valueOf(value); + } + return numberFormat.format(new Double(value)); + } + /** * <p> * Returns the formatted value of a cell as a <tt>String</tt> regardless * of the cell type. If the Excel format pattern cannot be parsed then the - * cell value will be formatted using a default format. + * cell value will be formatted using a default format. * </p> * <p>When passed a null or blank cell, this method will return an empty * String (""). Formulas in formula type cells will not be evaluated. * </p> - * + * * @param cell The cell * @return the formatted cell value as a String */ public String formatCellValue(HSSFCell cell) { return formatCellValue(cell, null); } - + /** * <p> * Returns the formatted value of a cell as a <tt>String</tt> regardless * of the cell type. If the Excel format pattern cannot be parsed then the - * cell value will be formatted using a default format. + * cell value will be formatted using a default format. * </p> * <p>When passed a null or blank cell, this method will return an empty * String (""). Formula cells will be evaluated using the given * {@link HSSFFormulaEvaluator} if the evaluator is non-null. If the * evaluator is null, then the formula String will be returned. The caller - * is responsible for setting the currentRow on the evaluator, otherwise an - * IllegalArgumentException may be thrown. + * is responsible for setting the currentRow on the evaluator *</p> - * - * @param cell The cell + * + * @param cell The cell (can be null) * @param evaluator The HSSFFormulaEvaluator (can be null) * @return a string value of the cell - * @throws IllegalArgumentException if cell type is <code> - * HSSFCell.CELL_TYPE_FORMULA</code> <b>and</b> evaluator is not null - * <b>and</b> the evlaluator's currentRow has not been set. */ - public String formatCellValue(HSSFCell cell, + public String formatCellValue(HSSFCell cell, HSSFFormulaEvaluator evaluator) throws IllegalArgumentException { - String value = ""; if (cell == null) { - return value; + return ""; } - + int cellType = cell.getCellType(); if (evaluator != null && cellType == HSSFCell.CELL_TYPE_FORMULA) { try { cellType = evaluator.evaluateFormulaCell(cell); - } catch (Throwable t) { - throw new IllegalArgumentException("Did you forget to set the current" + - " row on the HSSFFormulaEvaluator?", t); + } catch (RuntimeException e) { + throw new RuntimeException("Did you forget to set the current" + + " row on the HSSFFormulaEvaluator?", e); } - } + } switch (cellType) - { - case HSSFCell.CELL_TYPE_FORMULA : - // should only occur if evaluator is null - value = cell.getCellFormula(); - break; - - case HSSFCell.CELL_TYPE_NUMERIC : - - if (HSSFDateUtil.isCellDateFormatted(cell)) { - value = getFormattedDateString(cell); - } else { - value = getFormattedNumberString(cell); - } - break; - - case HSSFCell.CELL_TYPE_STRING : - value = cell.getRichStringCellValue().getString(); - break; - - case HSSFCell.CELL_TYPE_BOOLEAN : - value = String.valueOf(cell.getBooleanCellValue()); - } - return value; + { + case HSSFCell.CELL_TYPE_FORMULA : + // should only occur if evaluator is null + return cell.getCellFormula(); + + case HSSFCell.CELL_TYPE_NUMERIC : + + if (HSSFDateUtil.isCellDateFormatted(cell)) { + return getFormattedDateString(cell); + } + return getFormattedNumberString(cell); + + case HSSFCell.CELL_TYPE_STRING : + return cell.getRichStringCellValue().getString(); + + case HSSFCell.CELL_TYPE_BOOLEAN : + return String.valueOf(cell.getBooleanCellValue()); + case HSSFCell.CELL_TYPE_BLANK : + return ""; + } + throw new RuntimeException("Unexpected celltype (" + cellType + ")"); } - - + + /** * <p> * Sets a default number format to be used when the Excel format cannot be @@ -554,7 +533,7 @@ public class HSSFDataFormatter { * numeric cell. Therefore the code in the format method should expect a * <code>Number</code> value. * </p> - * + * * @param format A Format instance to be used as a default * @see java.text.Format#format */ @@ -568,8 +547,8 @@ public class HSSFDataFormatter { } } defaultNumFormat = format; - } - + } + /** * Adds a new format to the available formats. * <p> @@ -577,7 +556,7 @@ public class HSSFDataFormatter { * by <code>java.text.Format#format</code>) will be a double value from a * numeric cell. Therefore the code in the format method should expect a * <code>Number</code> value. - * </p> + * </p> * @param excelFormatStr The data format string * @param format A Format instance */ @@ -586,24 +565,30 @@ public class HSSFDataFormatter { } // Some custom formats - + + /** + * @return a <tt>DecimalFormat</tt> with parseIntegerOnly set <code>true</code> + */ + /* package */ static DecimalFormat createIntegerOnlyFormat(String fmt) { + DecimalFormat result = new DecimalFormat(fmt); + result.setParseIntegerOnly(true); + return result; + } /** * Format class for Excel's SSN format. This class mimics Excel's built-in * SSN formatting. - * + * * @author James May */ - static class SSNFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public SSNFormat() { - df = new DecimalFormat("000000000"); - df.setParseIntegerOnly(true); - } - + private static final class SSNFormat extends Format { + public static final Format instance = new SSNFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("000000000"); + private SSNFormat() { + // enforce singleton + } + /** Format a number as an SSN */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); sb.append(result.substring(0, 3)).append('-'); @@ -611,66 +596,60 @@ public class HSSFDataFormatter { sb.append(result.substring(5, 9)); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } } - + /** * Format class for Excel Zip + 4 format. This class mimics Excel's * built-in formatting for Zip + 4. * @author James May - */ - static class ZipPlusFourFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public ZipPlusFourFormat() { - df = new DecimalFormat("000000000"); - df.setParseIntegerOnly(true); - } - + */ + private static final class ZipPlusFourFormat extends Format { + public static final Format instance = new ZipPlusFourFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("000000000"); + private ZipPlusFourFormat() { + // enforce singleton + } + /** Format a number as Zip + 4 */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); sb.append(result.substring(0, 5)).append('-'); sb.append(result.substring(5, 9)); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } - } - + } + /** * Format class for Excel phone number format. This class mimics Excel's * built-in phone number formatting. * @author James May - */ - static class PhoneFormat extends Format { - private DecimalFormat df; - - /** Constructor */ - public PhoneFormat() { - df = new DecimalFormat("##########"); - df.setParseIntegerOnly(true); + */ + private static final class PhoneFormat extends Format { + public static final Format instance = new PhoneFormat(); + private static final DecimalFormat df = createIntegerOnlyFormat("##########"); + private PhoneFormat() { + // enforce singleton } - + /** Format a number as a phone number */ - public String format(Number num) { + public static String format(Number num) { String result = df.format(num); StringBuffer sb = new StringBuffer(); String seg1, seg2, seg3; @@ -678,28 +657,27 @@ public class HSSFDataFormatter { if (len <= 4) { return result; } - + seg3 = result.substring(len - 4, len); - seg2 = result.substring(Math.max(0, len - 7), len - 4); + seg2 = result.substring(Math.max(0, len - 7), len - 4); seg1 = result.substring(Math.max(0, len - 10), Math.max(0, len - 7)); - + if(seg1 != null && seg1.trim().length() > 0) { sb.append('(').append(seg1).append(") "); } if(seg2 != null && seg2.trim().length() > 0) { - sb.append(seg2).append('-'); + sb.append(seg2).append('-'); } sb.append(seg3); return sb.toString(); } - - public StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos) { + + public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { return toAppendTo.append(format((Number)obj)); } - + public Object parseObject(String source, ParsePosition pos) { return df.parseObject(source, pos); } - } + } } |