sw/qa/extras/uiwriter/data/tdf151993.docx |binary sw/qa/extras/uiwriter/uiwriter6.cxx | 30 +++++++++++++++++++++- writerfilter/source/dmapper/DomainMapper.cxx | 10 +++++++ writerfilter/source/dmapper/DomainMapper_Impl.cxx | 7 +++-- writerfilter/source/dmapper/DomainMapper_Impl.hxx | 3 ++ 5 files changed, 47 insertions(+), 3 deletions(-)
New commits: commit 42baf73137d1776618af5d7c7406bac86ebeb63c Author: László Németh <nem...@numbertext.org> AuthorDate: Mon Nov 14 10:01:36 2022 +0100 Commit: László Németh <nem...@numbertext.org> CommitDate: Mon Nov 14 13:33:26 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. Conflicts: sw/qa/extras/uiwriter/uiwriter6.cxx writerfilter/source/dmapper/DomainMapper_Impl.cxx (cherry-picked from commit c6688def010fcb6854c6d896efe7186ff6c63475) Change-Id: Ib13584f83bf36cbd68105da252f7d4955296ec80 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142670 Tested-by: Jenkins Reviewed-by: László Németh <nem...@numbertext.org> 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/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx index 5b98871bed91..e66fae378115 100644 --- a/sw/qa/extras/uiwriter/uiwriter6.cxx +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx @@ -2173,7 +2173,8 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testCaptionShape) CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf148799) { - // load a document with table formulas with comman delimiter + // load a document with table formulas with comma delimiter, + // but with a document language with default point delimiter SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf148799.docx"); SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); // check formula update @@ -2194,6 +2195,33 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf148799) CPPUNIT_ASSERT_EQUAL(OUString("23684.5"), xCellA4->getString()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf151993) +{ + // load a document with table formulas with comma delimiter + // (with a document language with default comma delimiter) + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf151993.docx"); + 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(SwUiWriterTest6, testTdf151462) { createSwDoc(DATA_DIRECTORY, "tdf151462.odt"); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index bfe9769e6293..219c62cef04d 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 ca0803c53931..03ac1467426e 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -323,6 +323,7 @@ DomainMapper_Impl::DomainMapper_Impl( m_xTextFactory( xModel, uno::UNO_QUERY ), m_xComponentContext( 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 ), @@ -5498,8 +5499,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 f6b88fec09b3..1707e171b379 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -475,6 +475,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; @@ -686,6 +688,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 ; }