From ae5f469d3893de73850ccc369dbf426a4acd8f15 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 30 Jan 2020 17:56:53 +0100 Subject: DOCX export: write document variables This means that in case a user field is exported to DOCX and the user updates the field, the result will be still correct, not empty. Change-Id: I2b52292c70aa6f597f92af95e16c773839247efa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87748 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- sw/qa/extras/ooxmlexport/ooxmlexport14.cxx | 7 ++++ sw/source/filter/ww8/docxexport.cxx | 55 ++++++++++++++++++++++++++++++ sw/source/filter/ww8/docxexport.hxx | 3 ++ 3 files changed, 65 insertions(+) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx index b79850140144..b8069d9f84df 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx @@ -301,6 +301,7 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField) utl::MediaDescriptor aMediaDescriptor; aMediaDescriptor["FilterName"] <<= OUString("Office Open XML Text"); xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + validate(maTempFile.GetFileName(), test::OOXML); mbExported = true; xmlDocPtr pXmlDoc = parseExport("word/document.xml"); CPPUNIT_ASSERT(pXmlDoc); @@ -309,6 +310,12 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField) // exported as User Field foo = bar. assertXPathContent(pXmlDoc, "//w:p/w:r[2]/w:instrText", " DOCVARIABLE foo "); assertXPathContent(pXmlDoc, "//w:p/w:r[4]/w:t", "bar"); + + // Make sure that not only the variables, but also their values are written. + pXmlDoc = parseExport("word/settings.xml"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "//w:docVars/w:docVar", "name", "foo"); + assertXPath(pXmlDoc, "//w:docVars/w:docVar", "val", "bar"); } DECLARE_OOXMLEXPORT_TEST(testTdf124367, "tdf124367.docx") diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 526d100768c8..992a97d69103 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -887,6 +888,58 @@ void DocxExport::WriteProperties( ) m_pFilter->exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly ); } +void DocxExport::WriteDocVars(const sax_fastparser::FSHelperPtr& pFS) +{ + SwDocShell* pDocShell = m_pDoc->GetDocShell(); + if (!pDocShell) + { + return; + } + + uno::Reference xModel(pDocShell->GetModel(), uno::UNO_QUERY); + uno::Reference xTextFieldMasters = xModel->getTextFieldMasters(); + uno::Sequence aMasterNames = xTextFieldMasters->getElementNames(); + if (!aMasterNames.hasElements()) + { + return; + } + + // Only write docVars if there will be at least a single docVar. + bool bStarted = false; + const OUStringLiteral aPrefix("com.sun.star.text.fieldmaster.User."); + for (const auto& rMasterName : std::as_const(aMasterNames)) + { + if (!rMasterName.startsWith(aPrefix)) + { + // Not a user field. + continue; + } + + uno::Reference xField; + xTextFieldMasters->getByName(rMasterName) >>= xField; + if (!xField.is()) + { + continue; + } + + OUString aKey = rMasterName.copy(aPrefix.getLength()); + OUString aValue; + xField->getPropertyValue("Content") >>= aValue; + if (!bStarted) + { + bStarted = true; + pFS->startElementNS(XML_w, XML_docVars); + } + pFS->singleElementNS(XML_w, XML_docVar, FSNS(XML_w, XML_name), aKey.toUtf8(), + FSNS(XML_w, XML_val), aValue.toUtf8()); + } + + if (bStarted) + { + pFS->endElementNS(XML_w, XML_docVars); + } +} + void DocxExport::WriteSettings() { SwViewShell *pViewShell(m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()); @@ -1151,6 +1204,8 @@ void DocxExport::WriteSettings() } } + WriteDocVars(pFS); + // Protect form // Section-specific write protection if (! hasProtectionProperties) diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 00b908dc7efa..f659cd1244f4 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -245,6 +245,9 @@ private: /// Write word/settings.xml void WriteSettings(); + /// Writes the part of settings.xml + void WriteDocVars(const sax_fastparser::FSHelperPtr& pFS); + /// Write word/theme/theme1.xml void WriteTheme(); -- cgit