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,

Reply via email to