oox/source/export/vmlexport.cxx | 18 +++++++++++------- sc/qa/unit/subsequent_export_test2.cxx | 5 ++++- sc/source/filter/excel/xeescher.cxx | 9 ++++++++- 3 files changed, 23 insertions(+), 9 deletions(-)
New commits: commit 245912dc42bfc13cbf0db3f04f2411f3dede9615 Author: Justin Luth <jl...@mail.com> AuthorDate: Sat Jan 21 17:00:26 2023 -0500 Commit: Justin Luth <jl...@mail.com> CommitDate: Tue Jan 24 02:09:55 2023 +0000 tdf#117266 tdf#120374 sc oox: export correct vml button name #2 So the actual name is more important than I knew. For example, VBA maps click macros based on the button name. So use the MS-provided name and use the SPID to connect to the shape id. Of the existing unit tests that were affected by this: -macro-button-form-control.xlsm: button now launches hello macro -tdf117266_macroButton.xlsm - same file as ^^^ -button-form-control.xls nearly same file as ^^^ -tdf134769.xlsx - checkbox still exists on round-trip -tdf106181.ods - checkbox still exists, but link to cell still lost. -checkbox-form-control.xlsx - nearly same as ^^^ All looks good. Change-Id: If83cf17d60b73c46d55a21b1a46ed320513044cb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145961 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 339187fbe4d2..6da57bdd8be8 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -187,20 +187,24 @@ void VMLExport::AddShape( sal_uInt32 nShapeType, ShapeFlag nShapeFlags, sal_uInt m_nShapeFlags = nShapeFlags; m_sShapeId = ShapeIdString( nShapeId ); - // If shape is a watermark object - should keep the original shape's name - // because Microsoft detects if it is a watermark by the actual name - if (!IsWaterMarkShape(m_pSdrObject->GetName())) + if (m_sShapeId.startsWith("_x0000_")) { - // Not a watermark object - m_pShapeAttrList->add( XML_id, m_sShapeId ); + // xml_id must be set elsewhere. The id is critical for matching VBA macros etc, + // and the spid is critical to link to the shape number elsewhere. + m_pShapeAttrList->addNS( XML_o, XML_spid, m_sShapeId ); } - else + else if (IsWaterMarkShape(m_pSdrObject->GetName())) { - // A watermark object - store the optional shape ID + // Shape is a watermark object - keep the original shape's name + // because Microsoft detects if it is a watermark by the actual name m_pShapeAttrList->add( XML_id, m_pSdrObject->GetName() ); // also ('o:spid') m_pShapeAttrList->addNS( XML_o, XML_spid, m_sShapeId ); } + else + { + m_pShapeAttrList->add(XML_id, m_sShapeId); + } } bool VMLExport::IsWaterMarkShape(std::u16string_view rStr) diff --git a/sc/qa/unit/subsequent_export_test2.cxx b/sc/qa/unit/subsequent_export_test2.cxx index 16188c90bbfa..3093e63500dd 100644 --- a/sc/qa/unit/subsequent_export_test2.cxx +++ b/sc/qa/unit/subsequent_export_test2.cxx @@ -542,7 +542,10 @@ void ScExportTest2::testTdf117266() xmlDocUniquePtr pVmlDrawing = parseExport("xl/drawings/vmlDrawing1.vml"); OUString sName = getXPath(pVmlDrawing, "/xml/v:shape", "id"); - CPPUNIT_ASSERT(sName.startsWith("_x0000_s")); + CPPUNIT_ASSERT_EQUAL(OUString("Button 1001"), sName); + + OUString sSpid = getXPath(pVmlDrawing, "/xml/v:shape", "spid"); + CPPUNIT_ASSERT(sSpid.startsWith("_x0000_s")); assertXPathContent(pVmlDrawing, "/xml/v:shape/v:textbox/div/font", "Button 1 \"y\" z"); // Why the xx:, I have no idea..., but it certainly doesn't work with just x:. diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 00b1b53a76a1..c0c15fda599a 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -1093,12 +1093,14 @@ class VmlFormControlExporter : public oox::vml::VMLExport sal_uInt16 m_nObjType; tools::Rectangle m_aAreaFrom; tools::Rectangle m_aAreaTo; + OUString m_sControlName; OUString m_aLabel; OUString m_aMacroName; public: VmlFormControlExporter(const sax_fastparser::FSHelperPtr& p, sal_uInt16 nObjType, const tools::Rectangle& rAreaFrom, const tools::Rectangle& rAreaTo, + const OUString& sControlName, OUString aLabel, OUString aMacroName); protected: @@ -1112,11 +1114,13 @@ VmlFormControlExporter::VmlFormControlExporter(const sax_fastparser::FSHelperPtr sal_uInt16 nObjType, const tools::Rectangle& rAreaFrom, const tools::Rectangle& rAreaTo, + const OUString& sControlName, OUString aLabel, OUString aMacroName) : VMLExport(p) , m_nObjType(nObjType) , m_aAreaFrom(rAreaFrom) , m_aAreaTo(rAreaTo) + , m_sControlName(sControlName) , m_aLabel(std::move(aLabel)) , m_aMacroName(std::move(aMacroName)) { @@ -1126,6 +1130,9 @@ sal_Int32 VmlFormControlExporter::StartShape() { // Host control. AddShapeAttribute(XML_type, "#_x0000_t201"); + if (!m_sControlName.isEmpty()) + AddShapeAttribute(XML_id, m_sControlName.toUtf8()); + return VMLExport::StartShape(); } @@ -1186,7 +1193,7 @@ void XclExpTbxControlObj::SaveVml(XclExpXmlStream& rStrm) // Unlike XclExpTbxControlObj::SaveXml(), this is not calculated in EMUs. lcl_GetFromTo(mrRoot, pObj->GetLogicRect(), GetTab(), aAreaFrom, aAreaTo); VmlFormControlExporter aFormControlExporter(rStrm.GetCurrentStream(), GetObjType(), aAreaFrom, - aAreaTo, msLabel, GetMacroName()); + aAreaTo, msCtrlName, msLabel, GetMacroName()); aFormControlExporter.SetSkipwzName(true); // use XML_id for legacyid, not XML_ID aFormControlExporter.OverrideShapeIDGen(true, "_x0000_s"); aFormControlExporter.AddSdrObject(*pObj, /*bIsFollowingTextFlow=*/false, /*eHOri=*/-1,