sw/qa/extras/uiwriter/data/tdf151993.docx         |binary
 sw/qa/extras/uiwriter/uiwriter8.cxx               |   31 +++++++++++++++++++++-
 writerfilter/source/dmapper/DomainMapper.cxx      |   10 +++++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |    7 +++-
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    3 ++
 5 files changed, 48 insertions(+), 3 deletions(-)

New commits:
commit c6688def010fcb6854c6d896efe7186ff6c63475
Author:     László Németh <[email protected]>
AuthorDate: Sat Nov 12 11:37:23 2022 +0100
Commit:     László Németh <[email protected]>
CommitDate: Mon Nov 14 09:30:14 2022 +0100

    tdf#151993 DOCX import: convert decimal comma only if needed
    
    E.g. convert en_US document with decimal comma, but not
    de_DE document with decimal comma.
    
    Regression from commit 94bf4908a6661101c270ef647e33dde09f16ac08
    "tdf#148799 DOCX import: fix invalid formulas with comma".
    
    DOCX allows to set decimal symbol independently from the locale
    of the document, so if the DOCX document uses comma, but
    its locale ("language") has got a default decimal point in Writer,
    Writer formulas must contain decimal points instead of commas,
    otherwise automatic update of the formulas, e.g. moving text
    cursor in the table, results ** Expression is faulty ** instead
    of the recalculated value. The only way to get standard
    Writer formulas is to replace the commas with points in numbers
    in writerfilter, if document language has a default
    decimal point in Writer.
    
    Note: not only document language, but area setting of
    LibreOffice installation modifies formula handling. I.e.
    plain numbers recognized with comma only if area setting
    is modified to a language, which uses decimal comma
    (but formulas still need decimal points, if the language
    of the document is a locale with default decimal point).
    E.g. an en_US DOCX document with decimal comma, or a
    de_DE document with decimal comma loaded correctly now,
    but recognizing cell content with a single number with comma
    needs to set also the correct area setting.
    
    Change-Id: I16dba1e10bf4271a44c435b5b09345d8d698b91d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142611
    Tested-by: Jenkins
    Reviewed-by: László Németh <[email protected]>

diff --git a/sw/qa/extras/uiwriter/data/tdf151993.docx 
b/sw/qa/extras/uiwriter/data/tdf151993.docx
new file mode 100644
index 000000000000..462feb0a61e4
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf151993.docx differ
diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx 
b/sw/qa/extras/uiwriter/uiwriter8.cxx
index 83698fa36a18..e6b5d0dad60c 100644
--- a/sw/qa/extras/uiwriter/uiwriter8.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter8.cxx
@@ -1400,7 +1400,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf146573)
 
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf148799)
 {
-    // load a document with table formulas with comma delimiter
+    // load a document with table formulas with comma delimiter,
+    // but with a document language with default point delimiter
     createSwDoc("tdf148799.docx");
     SwDoc* pDoc = getSwDoc();
     SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
@@ -1430,6 +1431,34 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf148799)
     CPPUNIT_ASSERT_EQUAL(OUString("23684.5"), xCellA4->getString());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf151993)
+{
+    // load a document with table formulas with comma delimiter
+    // (with a document language with default comma delimiter)
+    createSwDoc("tdf151993.docx");
+    SwDoc* pDoc = getSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+
+    // check formula update
+
+    // put cursor in the first table row
+    pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1);
+
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xTables(xTextTablesSupplier->getTextTables(),
+                                                    uno::UNO_QUERY);
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
+
+    uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), 
uno::UNO_QUERY);
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
+
+    // This was 0
+    uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName("A2"), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("30"), xCellA1->getString());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, testTdf148849)
 {
     // load a document with a table and an empty paragraph before the table
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 95694c270a8e..b5e45b7c2734 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -75,6 +75,7 @@
 #include <editeng/escapementitem.hxx>
 #include <filter/msfilter/util.hxx>
 #include <sfx2/DocumentMetadataAccess.hxx>
+#include <unotools/localedatawrapper.hxx>
 #include <unotools/mediadescriptor.hxx>
 
 #include "TextEffectsHandler.hxx"
@@ -658,6 +659,15 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
         case NS_ooxml::LN_CT_Language_eastAsia: //90315
         case NS_ooxml::LN_CT_Language_bidi: //90316
         {
+            // store decimal symbol associated to the language of the document
+            if ( m_pImpl->IsDocDefaultsImport() && ( nName == 
NS_ooxml::LN_CT_Language_val ) )
+            {
+                LanguageTag aLanguageTag( sStringValue );
+                LocaleDataWrapper aLocaleWrapper( std::move(aLanguageTag) );
+                if ( aLocaleWrapper.getNumDecimalSep() == "," )
+                    m_pImpl->SetIsDecimalComma();
+
+            }
             if (nName == NS_ooxml::LN_CT_Language_eastAsia)
                 m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, 
"eastAsia", sStringValue);
             else if (nName == NS_ooxml::LN_CT_Language_val)
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index e3e2ca0aa9dd..3cae3962811e 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -324,6 +324,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_xTextFactory( xModel, uno::UNO_QUERY ),
         m_xComponentContext(std::move( xContext )),
         m_bForceGenericFields(!utl::ConfigManager::IsFuzzing() && 
officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::get()),
+        m_bIsDecimalComma( false ),
         m_bSetUserFieldContent( false ),
         m_bSetCitation( false ),
         m_bSetDateValue( false ),
@@ -5556,8 +5557,10 @@ OUString DomainMapper_Impl::convertFieldFormula(const 
OUString& input) {
     icu::RegexMatcher rmatch6("\\b(ABOVE|BELOW|LEFT|RIGHT)\\b", usInput, 
rMatcherFlags, status);
     usInput = rmatch6.replaceAll(icu::UnicodeString(" $1 "), status);
 
-    /* fix decimal separator */
-    if ( m_pSettingsTable->GetDecimalSymbol() == "," )
+    /* DOCX allows to set decimal symbol independently from the locale of the 
document, so if
+     * needed, convert decimal comma to get working formula in a document 
language (locale),
+     * which doesn't use decimal comma */
+    if ( m_pSettingsTable->GetDecimalSymbol() == "," && !m_bIsDecimalComma )
     {
         icu::RegexMatcher rmatch7("\\b([0-9]+),([0-9]+([eE][-]?[0-9]+)?)\\b", 
usInput, rMatcherFlags, status);
         usInput = rmatch7.replaceAll(icu::UnicodeString("$1.$2"), status);
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 4c87fafa157d..32a657ce16d0 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -476,6 +476,8 @@ private:
     std::stack<std::pair<TextAppendContext, bool>>                             
     m_aHeaderFooterTextAppendStack;
     std::deque<FieldContextPtr> m_aFieldStack;
     bool m_bForceGenericFields;
+    /// Type of decimal symbol associated to the document language in Writer 
locale definition
+    bool                                                                       
     m_bIsDecimalComma;
     bool                                                                       
     m_bSetUserFieldContent;
     bool                                                                       
     m_bSetCitation;
     bool                                                                       
     m_bSetDateValue;
@@ -687,6 +689,7 @@ public:
     void RemoveDummyParaForTableInSection();
     void AddDummyParaForTableInSection();
     void RemoveLastParagraph( );
+    void SetIsDecimalComma() { m_bIsDecimalComma = true; };
     void SetIsLastParagraphInSection( bool bIsLast );
     bool GetIsLastParagraphInSection() const { return m_bIsLastParaInSection;}
     void SetRubySprmId( sal_uInt32 nSprmId) { m_aRubyInfo.nSprmId = nSprmId ; }

Reply via email to