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