]> source.dussan.org Git - poi.git/commitdiff
[Bug 60422] fix data formatter issue with specific format in German locale
authorPJ Fanning <fanningpj@apache.org>
Mon, 3 Jul 2017 20:56:02 +0000 (20:56 +0000)
committerPJ Fanning <fanningpj@apache.org>
Mon, 3 Jul 2017 20:56:02 +0000 (20:56 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1800713 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/format/CellDateFormatter.java
src/java/org/apache/poi/ss/format/CellFormat.java
src/java/org/apache/poi/ss/format/CellFormatPart.java
src/java/org/apache/poi/ss/format/CellFormatType.java
src/java/org/apache/poi/ss/format/CellFormatter.java
src/java/org/apache/poi/ss/format/CellGeneralFormatter.java
src/java/org/apache/poi/ss/format/CellNumberFormatter.java
src/java/org/apache/poi/ss/usermodel/DataFormatter.java
src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java

index 11c567c4c93564b8a654965480513e9c2a162351..a59fd0c72b0609d0e7a17325093c876510d03a92 100644 (file)
@@ -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();
                     }
index bad8497126a1864c4375f586b697e51a26902b45..415506b0d3f9b986c98b3559cc9405385a94583e 100644 (file)
@@ -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)
index b4b508fb3083d31a44185e357031c98e2b7af4e9..40cfb4a76e285189beca6c499d7204d500178beb 100644 (file)
@@ -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);
     }
 
     /**
index e1f436bdc8284cd12b380fc585abfa91abc903d6..af947b1db4aec338cd82630e2c0239fb7aab3fc3 100644 (file)
@@ -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);
 }
index e529a90f16bd0058bc427d709b9af0506de12712..2803c37e59709d3b32a49eb7ce9dfa7fdaa96740 100644 (file)
 ==================================================================== */
 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;
     }
 
index 52df33b72cda1dcf8c7dd86db2c7053b7be0c22d..37f202c9dd111454dd9ca28828512ad41189c88c 100644 (file)
@@ -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();
             }
index 668149f85a0a10536eb586c9c073f9d129a2af88..9657572e402d2bde67129b1f27e53a1f04f63a63 100644 (file)
@@ -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) {
+
+        DecimalFormatSymbols dfs = getDecimalFormatSymbols();
+        String decimalSeparator = Character.toString(dfs.getDecimalSeparator());
+        String groupingSeparator = Character.toString(dfs.getGroupingSeparator());
 
-        int pos = result.indexOf(".") - 1;
+        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 {
index f07225432cf13aaa1dad2a4450a75dd02ab6fd0c..0da7b6e714c56007ae36a0972fe0c0c040044d3f 100644 (file)
@@ -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);
index 679404f141815c248e5501833208bb3fdbd1e601..211f8019133c4219888b3a2a0f9e874a72e93665 100644 (file)
@@ -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));
     }
 }