aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/documentation/content/xdocs/status.xml1
-rw-r--r--src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java22
-rw-r--r--src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java15
-rw-r--r--src/java/org/apache/poi/ss/usermodel/DataFormatter.java55
-rw-r--r--src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java43
5 files changed, 119 insertions, 17 deletions
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index 79da11ad82..b0ae08f9b9 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -34,6 +34,7 @@
<changes>
<release version="3.7-SNAPSHOT" date="2010-??-??">
+ <action dev="POI-DEVELOPERS" type="add">48617 - Optionally allow the overriding of the Locale used by DataFormatter to control how the default number and date formats should look</action>
<action dev="POI-DEVELOPERS" type="add">New event based xssf text extractor (XSSFEventBasedExcelExtractor)</action>
<action dev="POI-DEVELOPERS" type="add">ExtractorFactory can now be told to prefer Event Based extractors (current Excel only) on a per-thread or overall basis</action>
<action dev="POI-DEVELOPERS" type="fix">48544 - avoid failures in XLSX2CSV when shared string table is missing</action>
diff --git a/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java b/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
index 5e21bdf58e..60c11d3521 100644
--- a/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
+++ b/src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
@@ -16,9 +16,11 @@
==================================================================== */
package org.apache.poi.hssf.eventusermodel;
+import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.apache.poi.hssf.record.CellValueRecordInterface;
@@ -37,12 +39,28 @@ import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
*/
public class FormatTrackingHSSFListener implements HSSFListener {
private final HSSFListener _childListener;
- private HSSFDataFormatter _formatter = new HSSFDataFormatter();
+ private final HSSFDataFormatter _formatter;
+ private final NumberFormat _defaultFormat;
private final Map<Integer, FormatRecord> _customFormatRecords = new Hashtable<Integer, FormatRecord>();
private final List<ExtendedFormatRecord> _xfRecords = new ArrayList<ExtendedFormatRecord>();
+ /**
+ * Creates a format tracking wrapper around the given listener, using
+ * the {@link Locale#getDefault() default locale} for the formats.
+ */
public FormatTrackingHSSFListener(HSSFListener childListener) {
+ this(childListener, Locale.getDefault());
+ }
+
+ /**
+ * Creates a format tracking wrapper around the given listener, using
+ * the given locale for the formats.
+ */
+ public FormatTrackingHSSFListener(
+ HSSFListener childListener, Locale locale) {
_childListener = childListener;
+ _formatter = new HSSFDataFormatter(locale);
+ _defaultFormat = NumberFormat.getInstance(locale);
}
protected int getNumberOfCustomFormats() {
@@ -104,7 +122,7 @@ public class FormatTrackingHSSFListener implements HSSFListener {
String formatString = getFormatString(cell);
if (formatString == null) {
- return Double.toString(value);
+ return _defaultFormat.format(value);
}
// Format, using the nice new
// HSSFDataFormatter to do the work for us
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
index 6396492d8e..0024639ff5 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
@@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel;
import java.text.DecimalFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
+import java.util.Locale;
import org.apache.poi.ss.usermodel.DataFormatter;
@@ -66,4 +67,18 @@ import org.apache.poi.ss.usermodel.DataFormatter;
*/
public final class HSSFDataFormatter extends DataFormatter {
+ /**
+ * Creates a formatter using the given locale.
+ */
+ public HSSFDataFormatter(Locale locale) {
+ super(locale);
+ }
+
+ /**
+ * Creates a formatter using the {@link Locale#getDefault() default locale}.
+ */
+ public HSSFDataFormatter() {
+ this(Locale.getDefault());
+ }
+
}
diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
index bb7ef000e4..053e37cb50 100644
--- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
+++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
@@ -77,11 +77,21 @@ public class DataFormatter {
/** A regex to find patterns like [$$-1009] and [$?-452]. */
private static final Pattern specialPatternGroup = Pattern.compile("(\\[\\$[^-\\]]*-[0-9A-Z]+\\])");
+ /**
+ * The decimal symbols of the locale used for formatting values.
+ */
+ private final DecimalFormatSymbols decimalSymbols;
+
+ /**
+ * The date symbols of the locale used for formatting values.
+ */
+ private final DateFormatSymbols dateSymbols;
+
/** <em>General</em> format for whole numbers. */
- private static final Format generalWholeNumFormat = new DecimalFormat("#");
+ private final Format generalWholeNumFormat;
/** <em>General</em> format for decimal numbers. */
- private static final Format generalDecimalNumFormat = new DecimalFormat("#.##########");
+ private final Format generalDecimalNumFormat;
/** A default format to use when a number pattern cannot be parsed. */
private Format defaultNumFormat;
@@ -90,13 +100,25 @@ public class DataFormatter {
* A map to cache formats.
* Map<String,Format> formats
*/
- private final Map formats;
+ private final Map<String,Format> formats;
/**
- * Constructor
+ * Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
public DataFormatter() {
- formats = new HashMap();
+ this(Locale.getDefault());
+ }
+
+ /**
+ * Creates a formatter using the given locale.
+ */
+ public DataFormatter(Locale locale) {
+ dateSymbols = new DateFormatSymbols(locale);
+ decimalSymbols = new DecimalFormatSymbols(locale);
+ generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
+ generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);
+
+ formats = new HashMap<String,Format>();
// init built-in formats
@@ -143,7 +165,7 @@ public class DataFormatter {
}
private Format getFormat(double cellValue, int formatIndex, String formatStr) {
- Format format = (Format)formats.get(formatStr);
+ Format format = formats.get(formatStr);
if (format != null) {
return format;
}
@@ -242,7 +264,7 @@ public class DataFormatter {
StringBuffer sb = new StringBuffer();
char[] chars = formatStr.toCharArray();
boolean mIsMonth = true;
- List ms = new ArrayList();
+ List<Integer> ms = new ArrayList<Integer>();
for(int j=0; j<chars.length; j++) {
char c = chars[j];
if (c == 'h' || c == 'H') {
@@ -267,7 +289,7 @@ public class DataFormatter {
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();
+ int index = ms.get(i).intValue();
if (sb.charAt(index) == 'M') {
sb.replace(index, index+1, "m");
}
@@ -295,7 +317,7 @@ public class DataFormatter {
formatStr = sb.toString();
try {
- return new SimpleDateFormat(formatStr);
+ return new SimpleDateFormat(formatStr, dateSymbols);
} catch(IllegalArgumentException iae) {
// the pattern could not be parsed correctly,
@@ -335,7 +357,7 @@ public class DataFormatter {
}
try {
- return new DecimalFormat(sb.toString());
+ return new DecimalFormat(sb.toString(), decimalSymbols);
} catch(IllegalArgumentException iae) {
// the pattern could not be parsed correctly,
@@ -520,9 +542,9 @@ public class DataFormatter {
* @see java.text.Format#format
*/
public void setDefaultNumberFormat(Format format) {
- Iterator itr = formats.entrySet().iterator();
+ Iterator<Map.Entry<String,Format>> itr = formats.entrySet().iterator();
while(itr.hasNext()) {
- Map.Entry entry = (Map.Entry)itr.next();
+ Map.Entry<String,Format> entry = itr.next();
if (entry.getValue() == generalDecimalNumFormat
|| entry.getValue() == generalWholeNumFormat) {
entry.setValue(format);
@@ -562,7 +584,8 @@ public class DataFormatter {
*
* @author James May
*/
- private static final class SSNFormat extends Format {
+ @SuppressWarnings("serial")
+ private static final class SSNFormat extends Format {
public static final Format instance = new SSNFormat();
private static final DecimalFormat df = createIntegerOnlyFormat("000000000");
private SSNFormat() {
@@ -593,7 +616,8 @@ public class DataFormatter {
* built-in formatting for Zip + 4.
* @author James May
*/
- private static final class ZipPlusFourFormat extends Format {
+ @SuppressWarnings("serial")
+ private static final class ZipPlusFourFormat extends Format {
public static final Format instance = new ZipPlusFourFormat();
private static final DecimalFormat df = createIntegerOnlyFormat("000000000");
private ZipPlusFourFormat() {
@@ -623,7 +647,8 @@ public class DataFormatter {
* built-in phone number formatting.
* @author James May
*/
- private static final class PhoneFormat extends Format {
+ @SuppressWarnings("serial")
+ private static final class PhoneFormat extends Format {
public static final Format instance = new PhoneFormat();
private static final DecimalFormat df = createIntegerOnlyFormat("##########");
private PhoneFormat() {
diff --git a/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
new file mode 100644
index 0000000000..73c15e8c44
--- /dev/null
+++ b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
@@ -0,0 +1,43 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.usermodel;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests of {@link DataFormatter}
+ *
+ */
+public class TestDataFormatter extends TestCase {
+ /**
+ * Test that we use the specified locale when deciding
+ * how to format normal numbers
+ */
+ public void testLocale() {
+ DataFormatter dfUS = new DataFormatter(Locale.US);
+ DataFormatter dfFR = new DataFormatter(Locale.FRENCH);
+
+ assertEquals("1234", dfUS.formatRawCellContents(1234, -1, "@"));
+ assertEquals("1234", dfFR.formatRawCellContents(1234, -1, "@"));
+
+ assertEquals("12.34", dfUS.formatRawCellContents(12.34, -1, "@"));
+ assertEquals("12,34", dfFR.formatRawCellContents(12.34, -1, "@"));
+ }
+}