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 f5e64db444b5cd5cdb53b2744bd52d441a0169b3 Author: Justin Luth <[email protected]> AuthorDate: Thu Jan 22 13:22:17 2026 -0500 Commit: Justin Luth <[email protected]> CommitDate: Mon Jan 26 17:56:25 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 (cherry picked from commit 270fe90efbb275a670d063303e395ed88ea4731d) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198157 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 009b92a1d663..49e0ba96bedc 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx @@ -147,6 +147,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 0673a2601423..286ce3a077da 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -2887,9 +2887,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); @@ -5899,8 +5900,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); }
