sw/qa/extras/ooxmlexport/data/tdf150542.docx  |binary
 sw/qa/extras/ooxmlexport/ooxmlexport16.cxx    |   21 +++++++++
 writerfilter/source/dmapper/SettingsTable.cxx |   58 +++++++++++++++++++++++++-
 writerfilter/source/ooxml/model.xml           |    3 +
 4 files changed, 81 insertions(+), 1 deletion(-)

New commits:
commit 992d86b1b67a6bd28bbf5e63b2d2406881f476b7
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Tue Mar 28 13:15:09 2023 +0300
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Mar 31 12:57:59 2023 +0000

    tdf#150542: DOCX import: support for document varibles
    
    Writer does insert document variables only if they are in
    document body as DOCVARIABLE fields. But ones given in
    settings.xml (w:docVars/w:docVar) were ignored.
    
    Moreover variables in settings should have priority and
    overwrite ones in fields. Word by default does show only
    field results, but refreshing field values will override
    values with ones from settings.
    
    Change-Id: I7103c90eef59ab18f8a25e616dcf8a8b1c6dcb08
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149646
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf150542.docx 
b/sw/qa/extras/ooxmlexport/data/tdf150542.docx
new file mode 100644
index 000000000000..3f115fa69370
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf150542.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index 0394c03495a6..6d501548ad25 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -994,6 +994,27 @@ CPPUNIT_TEST_FIXTURE(Test, Test_ShadowDirection)
                 "rotWithShape", "0");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf150542)
+{
+    loadAndSave("tdf150542.docx");
+
+    xmlDocUniquePtr pSettingsDoc = parseExport("word/settings.xml");
+    // Ensure that all docvars from input are written back and with correct 
values.
+    // Order of document variables is not checked. So this can fail at some 
time if order is changed.
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[1]", "name", 
u"LocalChars\u00C1\u0072\u0076\u00ED\u007A\u0074\u0075\u0072\u006F\u0054\u00FC\u006B\u00F6\u0072\u0066\u00FA\u0072\u00F3\u0067\u00E9\u0070");
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[1]", "val", u"Correct value 
(\u00E1\u0072\u0076\u00ED\u007A\u0074\u0075\u0072\u006F\u0020\u0074\u00FC\u006B\u00F6\u0072\u0066\u00FA\u0072\u00F3\u0067\u00E9\u0070)");
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[2]", "name", "DocVar1");
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[2]", "val", "DocVar1 Value");
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[3]", "name", "DocVar3");
+    assertXPath(pSettingsDoc,
+                "/w:settings/w:docVars/w:docVar[3]", "val", "DocVar3 Value");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf139549)
 {
     loadAndSave("tdf139549.docx");
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx 
b/writerfilter/source/dmapper/SettingsTable.cxx
index 45dc67b9f43b..d24dae617c01 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -26,6 +26,8 @@
 
 #include <rtl/ustring.hxx>
 #include <sfx2/zoomitem.hxx>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/beans/XPropertyState.hpp>
@@ -95,6 +97,7 @@ struct SettingsTable_Impl
     bool                m_bNoLeading = false;
     OUString            m_sDecimalSymbol;
     OUString            m_sListSeparator;
+    std::vector<std::pair<OUString, OUString>> m_aDocVars;
 
     uno::Sequence<beans::PropertyValue> m_pThemeFontLangProps;
 
@@ -136,7 +139,6 @@ struct SettingsTable_Impl
     , m_pThemeFontLangProps(3)
     , m_pCurrentCompatSetting(3)
     {}
-
 };
 
 SettingsTable::SettingsTable(const DomainMapper& rDomainMapper)
@@ -187,6 +189,12 @@ void SettingsTable::lcl_attribute(Id nName, Value & val)
     case NS_ooxml::LN_CT_View_val:
         m_pImpl->m_nView = nIntValue;
         break;
+    case NS_ooxml::LN_CT_DocVar_name:
+        m_pImpl->m_aDocVars.back().first = sStringValue;
+        break;
+    case NS_ooxml::LN_CT_DocVar_val:
+        m_pImpl->m_aDocVars.back().second = sStringValue;
+        break;
     case NS_ooxml::LN_CT_CompatSetting_name:
         m_pImpl->m_pCurrentCompatSetting.getArray()[0]
             = comphelper::makePropertyValue("name", sStringValue);
@@ -342,6 +350,25 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
         }
     }
     break;
+    case NS_ooxml::LN_CT_Settings_docVars:
+    {
+        writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+        if (pProperties)
+        {
+            pProperties->resolve(*this);
+        }
+    }
+    break;
+    case NS_ooxml::LN_CT_DocVar:
+    {
+        writerfilter::Reference<Properties>::Pointer_t pProperties = 
rSprm.getProps();
+        if (pProperties)
+        {
+            m_pImpl->m_aDocVars.push_back(std::make_pair(OUString(), 
OUString()));
+            pProperties->resolve(*this);
+        }
+    }
+    break;
     case NS_ooxml::LN_CT_Compat_noColumnBalance:
         m_pImpl->m_bNoColumnBalance = nIntValue;
         break;
@@ -572,6 +599,35 @@ void 
SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& x
         }
     }
 
+    // Create or overwrite DocVars based on found in settings
+    if (m_pImpl->m_aDocVars.size())
+    {
+        uno::Reference< text::XTextFieldsSupplier > xFieldsSupplier(xDoc, 
uno::UNO_QUERY_THROW);
+        uno::Reference< container::XNameAccess > xFieldMasterAccess = 
xFieldsSupplier->getTextFieldMasters();
+        for (const auto& docVar : m_pImpl->m_aDocVars)
+        {
+            uno::Reference< beans::XPropertySet > xMaster;
+            OUString sFieldMasterService("com.sun.star.text.FieldMaster.User." 
+ docVar.first);
+
+            // Find or create Field Master
+            if (xFieldMasterAccess->hasByName(sFieldMasterService))
+            {
+                
xMaster.set(xFieldMasterAccess->getByName(sFieldMasterService), 
uno::UNO_QUERY_THROW);
+            }
+            else
+            {
+                
xMaster.set(xTextFactory->createInstance("com.sun.star.text.FieldMaster.User"), 
uno::UNO_QUERY_THROW);
+                xMaster->setPropertyValue(getPropertyName(PROP_NAME), 
uno::Any(docVar.first));
+                uno::Reference<text::XDependentTextField> xField(
+                    
xTextFactory->createInstance("com.sun.star.text.TextField.User"),
+                    uno::UNO_QUERY);
+                xField->attachTextFieldMaster(xMaster);
+            }
+
+            xMaster->setPropertyValue(getPropertyName(PROP_CONTENT), 
uno::Any(docVar.second));
+        }
+    }
+
     // Auto hyphenation: turns on hyphenation by default, 
<w:suppressAutoHyphens/> may still disable it at a paragraph level.
     // Situation is similar for RTF_WIDOWCTRL, which turns on widow / orphan 
control by default.
     if (!(m_pImpl->m_bAutoHyphenation || m_pImpl->m_bNoHyphenateCaps || 
m_pImpl->m_bWidowControl))
diff --git a/writerfilter/source/ooxml/model.xml 
b/writerfilter/source/ooxml/model.xml
index 65295a94936c..888ffeba173c 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -18856,6 +18856,9 @@
       <attribute name="uri" tokenid="ooxml:CT_CompatSetting_uri"/>
       <attribute name="val" tokenid="ooxml:CT_CompatSetting_val"/>
     </resource>
+    <resource name="CT_DocVars" resource="Properties">
+      <element name="docVar" tokenid="ooxml:CT_DocVar"/>
+    </resource>
     <resource name="CT_DocVar" resource="Properties">
       <attribute name="name" tokenid="ooxml:CT_DocVar_name"/>
       <attribute name="val" tokenid="ooxml:CT_DocVar_val"/>

Reply via email to