OpenXLSX icon indicating copy to clipboard operation
OpenXLSX copied to clipboard

Broken with floats if locale decimal_point is not '.'

Open piru opened this issue 2 years ago • 6 comments

OpenXLSX fails when used with locales that use decimal_point other than .. This happens because of checking for hardcoded decimal separator at https://github.com/troldal/OpenXLSX/blob/29034465e569675f1677157b65b8263ccb1452f0/OpenXLSX/sources/XLCellValue.cpp#L249

piru avatar Oct 02 '22 16:10 piru

It’s my understanding that this is by design. If it were by locale, then other locales may see an invalid file format.

CEXT-Dan avatar Oct 02 '22 22:10 CEXT-Dan

OpenXLSX uses locale aware routines elsewhere to format floats. Hence it itself generates invalid formats. Either you consistently obey locale or don't. You can't mix.

piru avatar Oct 02 '22 22:10 piru

I don't think this is the case in the raw data, I believe this is stored in the STYLE, otherwise, if you were to send me a file to test, my tests would fail.

CEXT-Dan avatar Oct 02 '22 22:10 CEXT-Dan

Here are steps to reproduce:

  1. Apply this patch:
index 44d6eee..102b571 100644
--- a/Examples/Demo1.cpp
+++ b/Examples/Demo1.cpp
@@ -7,6 +7,8 @@ using namespace OpenXLSX;

 int main()
 {
+    setlocale(LC_ALL, "");
+
     cout << "********************************************************************************\n";
     cout << "DEMO PROGRAM #01: Basic Usage\n";
     cout << "********************************************************************************\n";
  1. Rebuild
  2. LC_NUMERIC=fi_FI.UTF-8 output/Demo1 (Note: Any locale that has non . decimal_point will do, fi_FI.UTF-8 is just one of them)

Result:

********************************************************************************
DEMO PROGRAM #01: Basic Usage
********************************************************************************
terminate called after throwing an instance of 'OpenXLSX::XLValueTypeError'
  what():  XLCellValue object does not contain the requested type.
Aborted

piru avatar Oct 02 '22 23:10 piru

I see, IMHO, the issue is in PUGI__SNPRINTF is using your locale when setting the data. The raw data itself should always be “.”

CEXT-Dan avatar Oct 02 '22 23:10 CEXT-Dan

This is a bit messy to fix cleanly on all platforms. On POSIX 2008 conforming system this is somewhat ok, as you can newlocale the "C" locale, and then either uselocale the "C" one when needed or even better use it directly with snprintf_l and wcstod_l/strtod_l, and finally cleaning up with freelocale.

Here is some discussion: https://stackoverflow.com/questions/13919817/how-to-parse-numbers-like-3-14-with-scanf-when-locale-expects-3-14

piru avatar Oct 03 '22 00:10 piru