mirror of https://github.com/apache/poi.git
[Bug 60422] fix data formatter issue with specific format in German locale
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1800713 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c78f22564f
commit
26389768b9
|
@ -138,6 +138,16 @@ public class CellDateFormatter extends CellFormatter {
|
|||
* @param format The format.
|
||||
*/
|
||||
public CellDateFormatter(String format) {
|
||||
this(LocaleUtil.getUserLocale(), format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new date formatter with the given specification.
|
||||
*
|
||||
* @param locale The locale.
|
||||
* @param format The format.
|
||||
*/
|
||||
public CellDateFormatter(Locale locale, String format) {
|
||||
super(format);
|
||||
DatePartHandler partHandler = new DatePartHandler();
|
||||
StringBuffer descBuf = CellFormatPart.parseFormat(format,
|
||||
|
@ -146,7 +156,7 @@ public class CellDateFormatter extends CellFormatter {
|
|||
// tweak the format pattern to pass tests on JDK 1.7,
|
||||
// See https://issues.apache.org/bugzilla/show_bug.cgi?id=53369
|
||||
String ptrn = descBuf.toString().replaceAll("((y)(?!y))(?<!yy)", "yy");
|
||||
dateFmt = new SimpleDateFormat(ptrn, LocaleUtil.getUserLocale());
|
||||
dateFmt = new SimpleDateFormat(ptrn, locale);
|
||||
dateFmt.setTimeZone(LocaleUtil.getUserTimeZone());
|
||||
}
|
||||
|
||||
|
@ -182,7 +192,7 @@ public class CellDateFormatter extends CellFormatter {
|
|||
Formatter formatter = new Formatter(toAppendTo, Locale.ROOT);
|
||||
try {
|
||||
long msecs = dateObj.getTime() % 1000;
|
||||
formatter.format(LocaleUtil.getUserLocale(), sFmt, msecs / 1000.0);
|
||||
formatter.format(locale, sFmt, msecs / 1000.0);
|
||||
} finally {
|
||||
formatter.close();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.poi.ss.format;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.logging.Level;
|
||||
|
@ -35,6 +36,7 @@ import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
|||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.util.DateFormatConverter;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
/**
|
||||
* Format a value according to the standard Excel behavior. This "standard" is
|
||||
|
@ -90,6 +92,7 @@ import org.apache.poi.ss.util.DateFormatConverter;
|
|||
* native character numbers, as documented at https://help.libreoffice.org/Common/Number_Format_Codes
|
||||
*/
|
||||
public class CellFormat {
|
||||
private final Locale locale;
|
||||
private final String format;
|
||||
private final CellFormatPart posNumFmt;
|
||||
private final CellFormatPart zeroNumFmt;
|
||||
|
@ -101,9 +104,6 @@ public class CellFormat {
|
|||
CellFormatPart.FORMAT_PAT.pattern() + "(;|$)",
|
||||
Pattern.COMMENTS | Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final CellFormatPart DEFAULT_TEXT_FORMAT =
|
||||
new CellFormatPart("@");
|
||||
|
||||
/*
|
||||
* Cells that cannot be formatted, e.g. cells that have a date or time
|
||||
* format and have an invalid date or time value, are displayed as 255
|
||||
|
@ -121,18 +121,23 @@ public class CellFormat {
|
|||
/**
|
||||
* Format a value as it would be were no format specified. This is also
|
||||
* used when the format specified is <tt>General</tt>.
|
||||
* @deprecated use {@link #getInstance(Locale, "General")} instead
|
||||
*/
|
||||
public static final CellFormat GENERAL_FORMAT = new CellFormat("General") {
|
||||
@Override
|
||||
public CellFormatResult apply(Object value) {
|
||||
String text = (new CellGeneralFormatter()).format(value);
|
||||
return new CellFormatResult(true, text, null);
|
||||
}
|
||||
};
|
||||
public static final CellFormat GENERAL_FORMAT = createGeneralFormat(LocaleUtil.getUserLocale());
|
||||
|
||||
private static CellFormat createGeneralFormat(final Locale locale) {
|
||||
return new CellFormat(locale, "General") {
|
||||
@Override
|
||||
public CellFormatResult apply(Object value) {
|
||||
String text = (new CellGeneralFormatter(locale)).format(value);
|
||||
return new CellFormatResult(true, text, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Maps a format string to its parsed version for efficiencies sake. */
|
||||
private static final Map<String, CellFormat> formatCache =
|
||||
new WeakHashMap<String, CellFormat>();
|
||||
private static final Map<Locale, Map<String, CellFormat>> formatCache =
|
||||
new WeakHashMap<Locale, Map<String, CellFormat>>();
|
||||
|
||||
/**
|
||||
* Returns a {@link CellFormat} that applies the given format. Two calls
|
||||
|
@ -143,13 +148,31 @@ public class CellFormat {
|
|||
* @return A {@link CellFormat} that applies the given format.
|
||||
*/
|
||||
public static CellFormat getInstance(String format) {
|
||||
CellFormat fmt = formatCache.get(format);
|
||||
return getInstance(LocaleUtil.getUserLocale(), format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link CellFormat} that applies the given format. Two calls
|
||||
* with the same format may or may not return the same object.
|
||||
*
|
||||
* @param locale The locale.
|
||||
* @param format The format.
|
||||
*
|
||||
* @return A {@link CellFormat} that applies the given format.
|
||||
*/
|
||||
public static synchronized CellFormat getInstance(Locale locale, String format) {
|
||||
Map<String, CellFormat> formatMap = formatCache.get(locale);
|
||||
if (formatMap == null) {
|
||||
formatMap = new WeakHashMap<String, CellFormat>();
|
||||
formatCache.put(locale, formatMap);
|
||||
}
|
||||
CellFormat fmt = formatMap.get(format);
|
||||
if (fmt == null) {
|
||||
if (format.equals("General") || format.equals("@"))
|
||||
fmt = GENERAL_FORMAT;
|
||||
fmt = createGeneralFormat(locale);
|
||||
else
|
||||
fmt = new CellFormat(format);
|
||||
formatCache.put(format, fmt);
|
||||
fmt = new CellFormat(locale, format);
|
||||
formatMap.put(format, fmt);
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
@ -159,8 +182,10 @@ public class CellFormat {
|
|||
*
|
||||
* @param format The format.
|
||||
*/
|
||||
private CellFormat(String format) {
|
||||
private CellFormat(Locale locale, String format) {
|
||||
this.locale = locale;
|
||||
this.format = format;
|
||||
CellFormatPart defaultTextFormat = new CellFormatPart(locale, "@");
|
||||
Matcher m = ONE_PART.matcher(format);
|
||||
List<CellFormatPart> parts = new ArrayList<CellFormatPart>();
|
||||
|
||||
|
@ -172,7 +197,7 @@ public class CellFormat {
|
|||
if (valueDesc.endsWith(";"))
|
||||
valueDesc = valueDesc.substring(0, valueDesc.length() - 1);
|
||||
|
||||
parts.add(new CellFormatPart(valueDesc));
|
||||
parts.add(new CellFormatPart(locale, valueDesc));
|
||||
} catch (RuntimeException e) {
|
||||
CellFormatter.logger.log(Level.WARNING,
|
||||
"Invalid format: " + CellFormatter.quote(m.group()), e);
|
||||
|
@ -187,19 +212,19 @@ public class CellFormat {
|
|||
posNumFmt = parts.get(0);
|
||||
negNumFmt = null;
|
||||
zeroNumFmt = null;
|
||||
textFmt = DEFAULT_TEXT_FORMAT;
|
||||
textFmt = defaultTextFormat;
|
||||
break;
|
||||
case 2:
|
||||
posNumFmt = parts.get(0);
|
||||
negNumFmt = parts.get(1);
|
||||
zeroNumFmt = null;
|
||||
textFmt = DEFAULT_TEXT_FORMAT;
|
||||
textFmt = defaultTextFormat;
|
||||
break;
|
||||
case 3:
|
||||
posNumFmt = parts.get(0);
|
||||
negNumFmt = parts.get(1);
|
||||
zeroNumFmt = parts.get(2);
|
||||
textFmt = DEFAULT_TEXT_FORMAT;
|
||||
textFmt = defaultTextFormat;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
|
@ -384,7 +409,7 @@ public class CellFormat {
|
|||
|| (posNumFmt.hasCondition() && posNumFmt.applies(val))) {
|
||||
return posNumFmt;
|
||||
} else {
|
||||
return new CellFormatPart("General");
|
||||
return new CellFormatPart(locale, "General");
|
||||
}
|
||||
} else if (formatPartCount == 2) {
|
||||
if ((!posNumFmt.hasCondition() && val >= 0)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.poi.ss.format;
|
||||
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -173,6 +174,16 @@ public class CellFormatPart {
|
|||
* @param desc The string to parse.
|
||||
*/
|
||||
public CellFormatPart(String desc) {
|
||||
this(LocaleUtil.getUserLocale(), desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an object to represent a format part.
|
||||
*
|
||||
* @param locale The locale to use.
|
||||
* @param desc The string to parse.
|
||||
*/
|
||||
public CellFormatPart(Locale locale, String desc) {
|
||||
Matcher m = FORMAT_PAT.matcher(desc);
|
||||
if (!m.matches()) {
|
||||
throw new IllegalArgumentException("Unrecognized format: " + quote(
|
||||
|
@ -181,7 +192,7 @@ public class CellFormatPart {
|
|||
color = getColor(m);
|
||||
condition = getCondition(m);
|
||||
type = getCellFormatType(m);
|
||||
format = getFormatter(m);
|
||||
format = getFormatter(locale, m);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,7 +298,7 @@ public class CellFormatPart {
|
|||
*
|
||||
* @return The formatter.
|
||||
*/
|
||||
private CellFormatter getFormatter(Matcher matcher) {
|
||||
private CellFormatter getFormatter(Locale locale, Matcher matcher) {
|
||||
String fdesc = matcher.group(SPECIFICATION_GROUP);
|
||||
|
||||
// For now, we don't support localised currencies, so simplify if there
|
||||
|
@ -305,7 +316,7 @@ public class CellFormatPart {
|
|||
}
|
||||
|
||||
// Build a formatter for this simplified string
|
||||
return type.formatter(fdesc);
|
||||
return type.formatter(locale, fdesc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.poi.ss.format;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The different kinds of formats that the formatter understands.
|
||||
*
|
||||
|
@ -26,11 +28,14 @@ public enum CellFormatType {
|
|||
|
||||
/** The general (default) format; also used for <tt>"General"</tt>. */
|
||||
GENERAL {
|
||||
boolean isSpecial(char ch) {
|
||||
return false;
|
||||
}
|
||||
CellFormatter formatter(String pattern) {
|
||||
return new CellGeneralFormatter();
|
||||
}
|
||||
boolean isSpecial(char ch) {
|
||||
return false;
|
||||
CellFormatter formatter(Locale locale, String pattern) {
|
||||
return new CellGeneralFormatter(locale);
|
||||
}
|
||||
},
|
||||
/** A numeric format. */
|
||||
|
@ -41,6 +46,9 @@ public enum CellFormatType {
|
|||
CellFormatter formatter(String pattern) {
|
||||
return new CellNumberFormatter(pattern);
|
||||
}
|
||||
CellFormatter formatter(Locale locale, String pattern) {
|
||||
return new CellNumberFormatter(locale, pattern);
|
||||
}
|
||||
},
|
||||
/** A date format. */
|
||||
DATE {
|
||||
|
@ -50,6 +58,9 @@ public enum CellFormatType {
|
|||
CellFormatter formatter(String pattern) {
|
||||
return new CellDateFormatter(pattern);
|
||||
}
|
||||
CellFormatter formatter(Locale locale, String pattern) {
|
||||
return new CellDateFormatter(locale, pattern);
|
||||
}
|
||||
},
|
||||
/** An elapsed time format. */
|
||||
ELAPSED {
|
||||
|
@ -59,6 +70,9 @@ public enum CellFormatType {
|
|||
CellFormatter formatter(String pattern) {
|
||||
return new CellElapsedFormatter(pattern);
|
||||
}
|
||||
CellFormatter formatter(Locale locale, String pattern) {
|
||||
return new CellElapsedFormatter(pattern);
|
||||
}
|
||||
},
|
||||
/** A text format. */
|
||||
TEXT {
|
||||
|
@ -68,6 +82,9 @@ public enum CellFormatType {
|
|||
CellFormatter formatter(String pattern) {
|
||||
return new CellTextFormatter(pattern);
|
||||
}
|
||||
CellFormatter formatter(Locale locale, String pattern) {
|
||||
return new CellTextFormatter(pattern);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -88,4 +105,15 @@ public enum CellFormatType {
|
|||
* @return A new formatter of the appropriate type, for the given pattern.
|
||||
*/
|
||||
abstract CellFormatter formatter(String pattern);
|
||||
|
||||
/**
|
||||
* Returns a new formatter of the appropriate type, for the given pattern.
|
||||
* The pattern must be appropriate for the type.
|
||||
*
|
||||
* @param locale The locale to use.
|
||||
* @param pattern The pattern to use.
|
||||
*
|
||||
* @return A new formatter of the appropriate type, for the given pattern.
|
||||
*/
|
||||
abstract CellFormatter formatter(Locale locale, String pattern);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,11 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.ss.format;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
|
||||
/**
|
||||
* This is the abstract supertype for the various cell formatters.
|
||||
*
|
||||
|
@ -26,6 +29,7 @@ import java.util.logging.Logger;
|
|||
public abstract class CellFormatter {
|
||||
/** The original specified format. */
|
||||
protected final String format;
|
||||
protected final Locale locale;
|
||||
|
||||
/**
|
||||
* Creates a new formatter object, storing the format in {@link #format}.
|
||||
|
@ -33,6 +37,17 @@ public abstract class CellFormatter {
|
|||
* @param format The format.
|
||||
*/
|
||||
public CellFormatter(String format) {
|
||||
this(LocaleUtil.getUserLocale(), format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new formatter object, storing the format in {@link #format}.
|
||||
*
|
||||
* @param locale The locale.
|
||||
* @param format The format.
|
||||
*/
|
||||
public CellFormatter(Locale locale, String format) {
|
||||
this.locale = locale;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,11 @@ import org.apache.poi.util.LocaleUtil;
|
|||
public class CellGeneralFormatter extends CellFormatter {
|
||||
/** Creates a new general formatter. */
|
||||
public CellGeneralFormatter() {
|
||||
super("General");
|
||||
this(LocaleUtil.getUserLocale());
|
||||
}
|
||||
/** Creates a new general formatter. */
|
||||
public CellGeneralFormatter(Locale locale) {
|
||||
super(locale, "General");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,9 +63,9 @@ public class CellGeneralFormatter extends CellFormatter {
|
|||
stripZeros = false;
|
||||
}
|
||||
|
||||
Formatter formatter = new Formatter(toAppendTo, LocaleUtil.getUserLocale());
|
||||
Formatter formatter = new Formatter(toAppendTo, locale);
|
||||
try {
|
||||
formatter.format(LocaleUtil.getUserLocale(), fmt, value);
|
||||
formatter.format(locale, fmt, value);
|
||||
} finally {
|
||||
formatter.close();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Formatter;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
@ -48,7 +49,7 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
private final Special numerator;
|
||||
private final Special afterInteger;
|
||||
private final Special afterFractional;
|
||||
private final boolean integerCommas;
|
||||
private final boolean showGroupingSeparator;
|
||||
private final List<Special> specials = new ArrayList<Special>();
|
||||
private final List<Special> integerSpecials = new ArrayList<Special>();
|
||||
private final List<Special> fractionalSpecials = new ArrayList<Special>();
|
||||
|
@ -69,13 +70,11 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
// ("#" for integer values, and "#.#" for floating-point values) is
|
||||
// different from the 'General' format for numbers ("#" for integer
|
||||
// values and "#.#########" for floating-point values).
|
||||
private static final CellFormatter SIMPLE_NUMBER = new GeneralNumberFormatter();
|
||||
private static final CellFormatter SIMPLE_INT = new CellNumberFormatter("#");
|
||||
private static final CellFormatter SIMPLE_FLOAT = new CellNumberFormatter("#.#");
|
||||
private final CellFormatter SIMPLE_NUMBER = new GeneralNumberFormatter(locale);
|
||||
|
||||
private static class GeneralNumberFormatter extends CellFormatter {
|
||||
private GeneralNumberFormatter() {
|
||||
super("General");
|
||||
private GeneralNumberFormatter(Locale locale) {
|
||||
super(locale, "General");
|
||||
}
|
||||
|
||||
public void formatValue(StringBuffer toAppendTo, Object value) {
|
||||
|
@ -86,7 +85,8 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
CellFormatter cf;
|
||||
if (value instanceof Number) {
|
||||
Number num = (Number) value;
|
||||
cf = (num.doubleValue() % 1.0 == 0) ? SIMPLE_INT : SIMPLE_FLOAT;
|
||||
cf = (num.doubleValue() % 1.0 == 0) ? new CellNumberFormatter(locale, "#") :
|
||||
new CellNumberFormatter(locale, "#.#");
|
||||
} else {
|
||||
cf = CellTextFormatter.SIMPLE_TEXT;
|
||||
}
|
||||
|
@ -124,7 +124,17 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
* @param format The format to parse.
|
||||
*/
|
||||
public CellNumberFormatter(String format) {
|
||||
super(format);
|
||||
this(LocaleUtil.getUserLocale(), format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new cell number formatter.
|
||||
*
|
||||
* @param locale The locale to use.
|
||||
* @param format The format to parse.
|
||||
*/
|
||||
public CellNumberFormatter(Locale locale, String format) {
|
||||
super(locale, format);
|
||||
|
||||
CellNumberPartHandler ph = new CellNumberPartHandler();
|
||||
StringBuffer descBuf = CellFormatPart.parseFormat(format, CellFormatType.NUMBER, ph);
|
||||
|
@ -177,7 +187,7 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
}
|
||||
|
||||
double scaleByRef[] = { ph.getScale() };
|
||||
integerCommas = interpretIntegerCommas(descBuf, specials, decimalPoint, integerEnd(), fractionalEnd(), scaleByRef);
|
||||
showGroupingSeparator = interpretIntegerCommas(descBuf, specials, decimalPoint, integerEnd(), fractionalEnd(), scaleByRef);
|
||||
if (exponent == null) {
|
||||
scale = scaleByRef[0];
|
||||
} else {
|
||||
|
@ -259,14 +269,17 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
}
|
||||
fmtBuf.append('E');
|
||||
placeZeros(fmtBuf, exponentSpecials.subList(2, exponentSpecials.size()));
|
||||
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
|
||||
decimalFmt = new DecimalFormat(fmtBuf.toString(), dfs);
|
||||
decimalFmt = new DecimalFormat(fmtBuf.toString(), getDecimalFormatSymbols());
|
||||
printfFmt = null;
|
||||
}
|
||||
|
||||
desc = descBuf.toString();
|
||||
}
|
||||
|
||||
private DecimalFormatSymbols getDecimalFormatSymbols() {
|
||||
return DecimalFormatSymbols.getInstance(locale);
|
||||
}
|
||||
|
||||
private static void placeZeros(StringBuffer sb, List<Special> specials) {
|
||||
for (Special s : specials) {
|
||||
if (isDigitFmt(s)) {
|
||||
|
@ -436,7 +449,7 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
}
|
||||
|
||||
Set<CellNumberStringMod> mods = new TreeSet<CellNumberStringMod>();
|
||||
StringBuffer output = new StringBuffer(desc);
|
||||
StringBuffer output = new StringBuffer(localiseFormat(desc));
|
||||
|
||||
if (exponent != null) {
|
||||
writeScientific(value, output, mods);
|
||||
|
@ -444,21 +457,24 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
writeFraction(value, null, fractional, output, mods);
|
||||
} else {
|
||||
StringBuffer result = new StringBuffer();
|
||||
Formatter f = new Formatter(result, LocaleUtil.getUserLocale());
|
||||
Formatter f = new Formatter(result, locale);
|
||||
try {
|
||||
f.format(LocaleUtil.getUserLocale(), printfFmt, value);
|
||||
f.format(locale, printfFmt, value);
|
||||
} finally {
|
||||
f.close();
|
||||
}
|
||||
|
||||
if (numerator == null) {
|
||||
writeFractional(result, output);
|
||||
writeInteger(result, output, integerSpecials, mods, integerCommas);
|
||||
writeInteger(result, output, integerSpecials, mods, showGroupingSeparator);
|
||||
} else {
|
||||
writeFraction(value, result, fractional, output, mods);
|
||||
}
|
||||
}
|
||||
|
||||
DecimalFormatSymbols dfs = getDecimalFormatSymbols();
|
||||
String groupingSeparator = Character.toString(dfs.getGroupingSeparator());
|
||||
|
||||
// Now strip out any remaining '#'s and add any pending text ...
|
||||
Iterator<CellNumberStringMod> changes = mods.iterator();
|
||||
CellNumberStringMod nextChange = (changes.hasNext() ? changes.next() : null);
|
||||
|
@ -478,7 +494,7 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
switch (nextChange.getOp()) {
|
||||
case CellNumberStringMod.AFTER:
|
||||
// ignore adding a comma after a deleted char (which was a '#')
|
||||
if (nextChange.getToAdd().equals(",") && deletedChars.get(s.pos)) {
|
||||
if (nextChange.getToAdd().equals(groupingSeparator) && deletedChars.get(s.pos)) {
|
||||
break;
|
||||
}
|
||||
output.insert(modPos + 1, nextChange.getToAdd());
|
||||
|
@ -545,7 +561,7 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
StringBuffer result = new StringBuffer();
|
||||
FieldPosition fractionPos = new FieldPosition(DecimalFormat.FRACTION_FIELD);
|
||||
decimalFmt.format(value, result, fractionPos);
|
||||
writeInteger(result, output, integerSpecials, mods, integerCommas);
|
||||
writeInteger(result, output, integerSpecials, mods, showGroupingSeparator);
|
||||
writeFractional(result, output);
|
||||
|
||||
/*
|
||||
|
@ -683,6 +699,27 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
LOG.log(POILogger.ERROR, "error while fraction evaluation", ignored);
|
||||
}
|
||||
}
|
||||
|
||||
private String localiseFormat(String format) {
|
||||
DecimalFormatSymbols dfs = getDecimalFormatSymbols();
|
||||
if(format.contains(",") && dfs.getGroupingSeparator() != ',') {
|
||||
if(format.contains(".") && dfs.getDecimalSeparator() != '.') {
|
||||
format = replaceLast(format, "\\.", "[DECIMAL_SEPARATOR]");
|
||||
format = format.replace(',', dfs.getGroupingSeparator())
|
||||
.replace("[DECIMAL_SEPARATOR]", Character.toString(dfs.getDecimalSeparator()));
|
||||
} else {
|
||||
format = format.replace(',', dfs.getGroupingSeparator());
|
||||
}
|
||||
} else if(format.contains(".") && dfs.getDecimalSeparator() != '.') {
|
||||
format = format.replace('.', dfs.getDecimalSeparator());
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
private static String replaceLast(String text, String regex, String replacement) {
|
||||
return text.replaceFirst("(?s)(.*)" + regex, "$1" + replacement);
|
||||
}
|
||||
|
||||
private static boolean hasChar(char ch, List<Special>... numSpecials) {
|
||||
for (List<Special> specials : numSpecials) {
|
||||
|
@ -698,9 +735,9 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
private void writeSingleInteger(String fmt, int num, StringBuffer output, List<Special> numSpecials, Set<CellNumberStringMod> mods) {
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Formatter formatter = new Formatter(sb, LocaleUtil.getUserLocale());
|
||||
Formatter formatter = new Formatter(sb, locale);
|
||||
try {
|
||||
formatter.format(LocaleUtil.getUserLocale(), fmt, num);
|
||||
formatter.format(locale, fmt, num);
|
||||
} finally {
|
||||
formatter.close();
|
||||
}
|
||||
|
@ -709,9 +746,13 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
|
||||
private void writeInteger(StringBuffer result, StringBuffer output,
|
||||
List<Special> numSpecials, Set<CellNumberStringMod> mods,
|
||||
boolean showCommas) {
|
||||
boolean showGroupingSeparator) {
|
||||
|
||||
int pos = result.indexOf(".") - 1;
|
||||
DecimalFormatSymbols dfs = getDecimalFormatSymbols();
|
||||
String decimalSeparator = Character.toString(dfs.getDecimalSeparator());
|
||||
String groupingSeparator = Character.toString(dfs.getGroupingSeparator());
|
||||
|
||||
int pos = result.indexOf(decimalSeparator) - 1;
|
||||
if (pos < 0) {
|
||||
if (exponent != null && numSpecials == integerSpecials) {
|
||||
pos = result.indexOf("E") - 1;
|
||||
|
@ -723,13 +764,13 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
int strip;
|
||||
for (strip = 0; strip < pos; strip++) {
|
||||
char resultCh = result.charAt(strip);
|
||||
if (resultCh != '0' && resultCh != ',') {
|
||||
if (resultCh != '0' && resultCh != dfs.getGroupingSeparator()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ListIterator<Special> it = numSpecials.listIterator(numSpecials.size());
|
||||
boolean followWithComma = false;
|
||||
boolean followWithGroupingSeparator = false;
|
||||
Special lastOutputIntegerDigit = null;
|
||||
int digit = 0;
|
||||
while (it.hasPrevious()) {
|
||||
|
@ -741,16 +782,16 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
resultCh = '0';
|
||||
}
|
||||
Special s = it.previous();
|
||||
followWithComma = showCommas && digit > 0 && digit % 3 == 0;
|
||||
followWithGroupingSeparator = showGroupingSeparator && digit > 0 && digit % 3 == 0;
|
||||
boolean zeroStrip = false;
|
||||
if (resultCh != '0' || s.ch == '0' || s.ch == '?' || pos >= strip) {
|
||||
zeroStrip = s.ch == '?' && pos < strip;
|
||||
output.setCharAt(s.pos, (zeroStrip ? ' ' : resultCh));
|
||||
lastOutputIntegerDigit = s;
|
||||
}
|
||||
if (followWithComma) {
|
||||
mods.add(insertMod(s, zeroStrip ? " " : ",", CellNumberStringMod.AFTER));
|
||||
followWithComma = false;
|
||||
if (followWithGroupingSeparator) {
|
||||
mods.add(insertMod(s, zeroStrip ? " " : groupingSeparator, CellNumberStringMod.AFTER));
|
||||
followWithGroupingSeparator = false;
|
||||
}
|
||||
digit++;
|
||||
--pos;
|
||||
|
@ -761,10 +802,10 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
// pos was decremented at the end of the loop above when the iterator was at its end
|
||||
++pos;
|
||||
extraLeadingDigits = new StringBuffer(result.substring(0, pos));
|
||||
if (showCommas) {
|
||||
if (showGroupingSeparator) {
|
||||
while (pos > 0) {
|
||||
if (digit > 0 && digit % 3 == 0) {
|
||||
extraLeadingDigits.insert(pos, ',');
|
||||
extraLeadingDigits.insert(pos, groupingSeparator);
|
||||
}
|
||||
digit++;
|
||||
--pos;
|
||||
|
@ -778,7 +819,8 @@ public class CellNumberFormatter extends CellFormatter {
|
|||
int digit;
|
||||
int strip;
|
||||
if (fractionalSpecials.size() > 0) {
|
||||
digit = result.indexOf(".") + 1;
|
||||
String decimalSeparator = Character.toString(getDecimalFormatSymbols().getDecimalSeparator());
|
||||
digit = result.indexOf(decimalSeparator) + 1;
|
||||
if (exponent != null) {
|
||||
strip = result.indexOf("e") - 1;
|
||||
} else {
|
||||
|
|
|
@ -292,10 +292,6 @@ public class DataFormatter implements Observer {
|
|||
* @param cell The cell to retrieve a Format for
|
||||
* @return A Format for the format String
|
||||
*/
|
||||
private Format getFormat(Cell cell) {
|
||||
return getFormat(cell, null);
|
||||
}
|
||||
|
||||
private Format getFormat(Cell cell, ConditionalFormattingEvaluator cfEvaluator) {
|
||||
if (cell == null) return null;
|
||||
|
||||
|
@ -315,12 +311,12 @@ public class DataFormatter implements Observer {
|
|||
|
||||
private Format getFormat(double cellValue, int formatIndex, String formatStrIn) {
|
||||
localeChangedObservable.checkForLocaleChange();
|
||||
|
||||
// // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
|
||||
// // That however would require other code to be re factored.
|
||||
// String[] formatBits = formatStrIn.split(";");
|
||||
// int i = cellValue > 0.0 ? 0 : cellValue < 0.0 ? 1 : 2;
|
||||
// String formatStr = (i < formatBits.length) ? formatBits[i] : formatBits[0];
|
||||
|
||||
// Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
|
||||
// That however would require other code to be re factored.
|
||||
// String[] formatBits = formatStrIn.split(";");
|
||||
// int i = cellValue > 0.0 ? 0 : cellValue < 0.0 ? 1 : 2;
|
||||
// String formatStr = (i < formatBits.length) ? formatBits[i] : formatBits[0];
|
||||
|
||||
String formatStr = formatStrIn;
|
||||
|
||||
|
@ -336,7 +332,7 @@ public class DataFormatter implements Observer {
|
|||
) ) {
|
||||
try {
|
||||
// Ask CellFormat to get a formatter for it
|
||||
CellFormat cfmt = CellFormat.getInstance(formatStr);
|
||||
CellFormat cfmt = CellFormat.getInstance(locale, formatStr);
|
||||
// CellFormat requires callers to identify date vs not, so do so
|
||||
Object cellValueO = Double.valueOf(cellValue);
|
||||
if (DateUtil.isADateFormat(formatIndex, formatStr) &&
|
||||
|
@ -607,7 +603,7 @@ public class DataFormatter implements Observer {
|
|||
try {
|
||||
return new ExcelStyleDateFormatter(formatStr, dateSymbols);
|
||||
} catch(IllegalArgumentException iae) {
|
||||
|
||||
logger.log(POILogger.DEBUG, "Formatting failed for format " + formatStr + ", falling back", iae);
|
||||
// the pattern could not be parsed correctly,
|
||||
// so fall back to the default number format
|
||||
return getDefaultFormat(cellValue);
|
||||
|
@ -718,7 +714,7 @@ public class DataFormatter implements Observer {
|
|||
setExcelStyleRoundingMode(df);
|
||||
return df;
|
||||
} catch(IllegalArgumentException iae) {
|
||||
|
||||
logger.log(POILogger.DEBUG, "Formatting failed for format " + formatStr + ", falling back", iae);
|
||||
// the pattern could not be parsed correctly,
|
||||
// so fall back to the default number format
|
||||
return getDefaultFormat(cellValue);
|
||||
|
|
|
@ -811,7 +811,6 @@ public class TestDataFormatter {
|
|||
CellReference ref = new CellReference("D47");
|
||||
|
||||
Cell cell = wb.getSheetAt(0).getRow(ref.getRow()).getCell(ref.getCol());
|
||||
//noinspection deprecation
|
||||
assertEquals(CellType.FORMULA, cell.getCellTypeEnum());
|
||||
assertEquals("G9:K9 I7:I12", cell.getCellFormula());
|
||||
|
||||
|
@ -888,18 +887,12 @@ public class TestDataFormatter {
|
|||
≈ */
|
||||
@Test
|
||||
public void testBug60422() {
|
||||
//when this is set to Locale.Germany, the result is
|
||||
LocaleUtil.setUserLocale(Locale.ROOT);
|
||||
try {
|
||||
char euro = '\u20AC';
|
||||
DataFormatter df = new DataFormatter(Locale.GERMANY);
|
||||
String formatString = String.format(Locale.ROOT,
|
||||
"_-* #,##0.00\\ \"%s\"_-;\\-* #,##0.00\\ \"%s\"_-;_-* \"-\"??\\ \"%s\"_-;_-@_-",
|
||||
euro, euro, euro);
|
||||
//this should be 4,33
|
||||
assertEquals("4.33 " + euro, df.formatRawCellContents(4.33, 178, formatString));
|
||||
} finally {
|
||||
LocaleUtil.resetUserLocale();
|
||||
}
|
||||
char euro = '\u20AC';
|
||||
DataFormatter df = new DataFormatter(Locale.GERMANY);
|
||||
String formatString = String.format(Locale.ROOT,
|
||||
"_-* #,##0.00\\ \"%s\"_-;\\-* #,##0.00\\ \"%s\"_-;_-* \"-\"??\\ \"%s\"_-;_-@_-",
|
||||
euro, euro, euro);
|
||||
assertEquals("4,33 " + euro, df.formatRawCellContents(4.33, 178, formatString));
|
||||
assertEquals("1.234,33 " + euro, df.formatRawCellContents(1234.33, 178, formatString));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue