aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/poi
diff options
context:
space:
mode:
authorNick Burch <nick@apache.org>2015-10-24 23:34:47 +0000
committerNick Burch <nick@apache.org>2015-10-24 23:34:47 +0000
commitb3f68c4eb4f81cfda99bc449b922c12abf348ade (patch)
treeb78e23301ec7ed5c825854abe91f8387fba4f964 /src/java/org/apache/poi
parentcbde002fa1356f53b382b97797229ed209ee522f (diff)
downloadpoi-b3f68c4eb4f81cfda99bc449b922c12abf348ade.tar.gz
poi-b3f68c4eb4f81cfda99bc449b922c12abf348ade.zip
#58532 For Excel cell formats with 3+ parts to them (eg +ve,-ve,0), which
DataFormatter didn't properly support, call out to the alternate CellFormat instead for the formatting. This also allows us to enable some disabled parts of DataFormatter unit tests We still need to rationalise DataFormatter and CellFormatter though, so we only have one set of cell formatting logic... git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1710399 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/poi')
-rw-r--r--src/java/org/apache/poi/ss/usermodel/DataFormatter.java65
1 files changed, 45 insertions, 20 deletions
diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
index 2f414a1d9e..add3be8cef 100644
--- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
+++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
@@ -40,8 +40,12 @@ import java.util.Observer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.poi.ss.format.CellFormat;
+import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
/**
@@ -197,6 +201,9 @@ public class DataFormatter implements Observer {
/** the Observable to notify, when the locale has been changed */
private final LocaleChangeObservable localeChangedObervable = new LocaleChangeObservable();
+ /** For logging any problems we find */
+ private static POILogger logger = POILogFactory.getLogger(DataFormatter.class);
+
/**
* Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
@@ -270,28 +277,30 @@ public class DataFormatter implements Observer {
// String formatStr = (i < formatBits.length) ? formatBits[i] : formatBits[0];
String formatStr = formatStrIn;
- // Excel supports positive/negative/zero, but java
- // doesn't, so we need to do it specially
- final int firstAt = formatStr.indexOf(';');
- final int lastAt = formatStr.lastIndexOf(';');
- // p and p;n are ok by default. p;n;z and p;n;z;s need to be fixed.
- if (firstAt != -1 && firstAt != lastAt) {
- final int secondAt = formatStr.indexOf(';', firstAt + 1);
- if (secondAt == lastAt) { // p;n;z
- if (cellValue == 0.0) {
- formatStr = formatStr.substring(lastAt + 1);
- } else {
- formatStr = formatStr.substring(0, lastAt);
- }
- } else {
- if (cellValue == 0.0) { // p;n;z;s
- formatStr = formatStr.substring(secondAt + 1, lastAt);
- } else {
- formatStr = formatStr.substring(0, secondAt);
+
+ // Excel supports 3+ part conditional data formats, eg positive/negative/zero,
+ // or (>1000),(>0),(0),(negative). As Java doesn't handle these kinds
+ // of different formats for different ranges, just +ve/-ve, we need to
+ // handle these ourselves in a special way.
+ // For now, if we detect 3+ parts, we call out to CellFormat to handle it
+ // TODO Going forward, we should really merge the logic between the two classes
+ if (formatStr.indexOf(";") != -1 &&
+ formatStr.indexOf(';') != formatStr.lastIndexOf(';')) {
+ try {
+ // Ask CellFormat to get a formatter for it
+ CellFormat cfmt = CellFormat.getInstance(formatStr);
+ // CellFormat requires callers to identify date vs not, so do so
+ Object cellValueO = Double.valueOf(cellValue);
+ if (DateUtil.isADateFormat(formatIndex, formatStr)) {
+ cellValueO = DateUtil.getJavaDate(cellValue);
}
+ // Wrap and return (non-cachable - CellFormat does that)
+ return new CellFormatResultWrapper( cfmt.apply(cellValueO) );
+ } catch (Exception e) {
+ logger.log(POILogger.WARN, "Formatting failed as " + formatStr + ", falling back", e);
}
}
-
+
// Excel's # with value 0 will output empty where Java will output 0. This hack removes the # from the format.
if (emulateCsv && cellValue == 0.0 && formatStr.contains("#") && !formatStr.contains("0")) {
formatStr = formatStr.replaceAll("#", "");
@@ -310,7 +319,6 @@ public class DataFormatter implements Observer {
// Build a formatter, and cache it
format = createFormat(cellValue, formatIndex, formatStr);
- formats.put(formatStr, format);
return format;
}
@@ -1116,4 +1124,21 @@ public class DataFormatter implements Observer {
return df.parseObject(source, pos);
}
}
+ /**
+ * Workaround until we merge {@link DataFormatter} with {@link CellFormat}.
+ * Constant, non-cachable wrapper around a {@link CellFormatResult}
+ */
+ @SuppressWarnings("serial")
+ private static final class CellFormatResultWrapper extends Format {
+ private final CellFormatResult result;
+ private CellFormatResultWrapper(CellFormatResult result) {
+ this.result = result;
+ }
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+ return toAppendTo.append(result.text);
+ }
+ public Object parseObject(String source, ParsePosition pos) {
+ return null; // Not supported
+ }
+ }
}