sw/qa/extras/ooxmlexport/data/tdf170438_dropdown.odt |binary sw/qa/extras/ooxmlexport/ooxmlexport25.cxx | 12 ++++++++++++ sw/source/filter/ww8/docxattributeoutput.cxx | 6 ++++-- 3 files changed, 16 insertions(+), 2 deletions(-)
New commits: commit 270fe90efbb275a670d063303e395ed88ea4731d Author: Justin Luth <[email protected]> AuthorDate: Thu Jan 22 13:22:17 2026 -0500 Commit: Justin Luth <[email protected]> CommitDate: Fri Jan 23 19:16:46 2026 +0100 tdf#170438 docx export: never export listItem with empty displayText MS Word was reporting a document as corrupt after LO round-tripped it with an empty displayText. However, an empty w:value is not a 'corrupt' result. Note that this situation was possible also while importing DOCX. We don't always import SDTs as content controls (e.g. in tables). In that case, only the 'values' are considered, so an empty entry is created in the dropdown field, which then got exported as an empty displayText. make CppunitTest_sw_ooxmlexport25 \ CPPUNIT_TEST_NAME=testTdf170438_dropdown ooxmlexport13's tdf119809.docx is a VML shape that is called a combobox, and it exported with WritePostponedFormControl. It sounds like it can only have 'values' when added by a VBA macro, so likely these will almost never output a displayText. Change-Id: Ib306eda90b4179e10402c276e7c47a3bfdd83cfb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197867 Reviewed-by: Justin Luth <[email protected]> Tested-by: Jenkins diff --git a/sw/qa/extras/ooxmlexport/data/tdf170438_dropdown.odt b/sw/qa/extras/ooxmlexport/data/tdf170438_dropdown.odt new file mode 100644 index 000000000000..02bbe360bf25 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf170438_dropdown.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx index 2ea0d1a6a50f..110211a7c2c9 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx @@ -150,6 +150,18 @@ DECLARE_OOXMLEXPORT_TEST(testTdf165478_bottomAligned, "tdf165478_bottomAligned.d CPPUNIT_ASSERT_EQUAL(sal_Int32(1887), nFlyTop); } +CPPUNIT_TEST_FIXTURE(Test, testTdf170438_dropdown) +{ + createSwDoc("tdf170438_dropdown.odt"); + + saveAndReload(TestFilter::DOCX); + + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + // MS Word reports document as corrupt if displayText is empty + assertXPath(pXmlDoc, "//w:listItem[1]", "displayText", u" "); + assertXPath(pXmlDoc, "//w:listItem[1]", "value", u""); // value may be empty +} + CPPUNIT_TEST_FIXTURE(Test, testTdf170389_manyTabstops) { createSwDoc("tdf170389_manyTabstops.odt"); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index ddcc2c629a2b..e1a2e450ee14 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -2882,9 +2882,10 @@ void DocxAttributeOutput::WriteSdtDropDownStart( for (auto const& rItem : rListItems) { auto const item(OUStringToOString(rItem, RTL_TEXTENCODING_UTF8)); + OString sDisplayText = item.isEmpty() ? " "_ostr : item; // displayText must not be empty m_pSerializer->singleElementNS(XML_w, XML_listItem, FSNS(XML_w, XML_value), item, - FSNS(XML_w, XML_displayText), item); + FSNS(XML_w, XML_displayText), sDisplayText); } m_pSerializer->endElementNS(XML_w, XML_dropDownList); @@ -5894,8 +5895,9 @@ void DocxAttributeOutput::WritePostponedFormControl(const SdrObject* pObject) for (const auto& rItem : aItems) { + OUString sDisplayText = rItem.isEmpty() ? " " : rItem; // displayText must not be empty m_pSerializer->singleElementNS(XML_w, XML_listItem, - FSNS(XML_w, XML_displayText), rItem, + FSNS(XML_w, XML_displayText), sDisplayText, FSNS(XML_w, XML_value), rItem); }
