mirror of https://github.com/apache/poi.git
Add patch from Jukka from bug #48617 + test - Optionally allow the overriding of the Locale used by DataFormatter to control how the default number and date formats should look
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@903303 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
63dc16b762
commit
421505b715
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,6 +584,7 @@ public class DataFormatter {
|
|||
*
|
||||
* @author James May
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static final class SSNFormat extends Format {
|
||||
public static final Format instance = new SSNFormat();
|
||||
private static final DecimalFormat df = createIntegerOnlyFormat("000000000");
|
||||
|
@ -593,6 +616,7 @@ public class DataFormatter {
|
|||
* built-in formatting for Zip + 4.
|
||||
* @author James May
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static final class ZipPlusFourFormat extends Format {
|
||||
public static final Format instance = new ZipPlusFourFormat();
|
||||
private static final DecimalFormat df = createIntegerOnlyFormat("000000000");
|
||||
|
@ -623,6 +647,7 @@ public class DataFormatter {
|
|||
* built-in phone number formatting.
|
||||
* @author James May
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static final class PhoneFormat extends Format {
|
||||
public static final Format instance = new PhoneFormat();
|
||||
private static final DecimalFormat df = createIntegerOnlyFormat("##########");
|
||||
|
|
|
@ -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, "@"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue