include/vbahelper/vbacollectionimpl.hxx |   17 +++++++++++++----
 sw/qa/core/data/docm/testModernVBA.docm |binary
 sw/source/ui/vba/vbacontentcontrol.cxx  |    6 +++---
 sw/source/ui/vba/vbacontentcontrols.cxx |   15 ++++++++-------
 4 files changed, 24 insertions(+), 14 deletions(-)

New commits:
commit 7ba8ff76d197f53e7a40cbd74b75a09fa4ec2eda
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Wed Nov 23 20:45:09 2022 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Dec 20 08:06:22 2022 +0000

    tdf#151548 ContentControls vba: allow search by name/float
    
    This so-called modern content control is rather terrible for
    VBA programmers. It has no modifiable ID!
    Instead, there is a random _signed-integer_ as a unique id.
    How descriptive...
    
    Since it is an integer, it can't be passed to Item(),
    because then it would be an index lookup.
    Instead, you can pass it as a float (indicated by a #)
    or as a _unsigned-integer_ string.
    
    Recently the ID was preserved for content control import/export,
    so we can now round out our VBA to find content controls by name.
    
    make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba
    
    Change-Id: I387a287505e17d3768bad5ed954136e532ca70e6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143196
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144549
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/include/vbahelper/vbacollectionimpl.hxx 
b/include/vbahelper/vbacollectionimpl.hxx
index c6a0b85aee75..201fbd01faa6 100644
--- a/include/vbahelper/vbacollectionimpl.hxx
+++ b/include/vbahelper/vbacollectionimpl.hxx
@@ -293,19 +293,28 @@ public:
 
     virtual css::uno::Any SAL_CALL Item(const css::uno::Any& Index1, const 
css::uno::Any& /*not processed in this base class*/) override
     {
-        if ( Index1.getValueTypeClass() != css::uno::TypeClass_STRING )
+        OUString aStringSheet;
+        if (Index1.getValueTypeClass() == css::uno::TypeClass_DOUBLE)
+        {
+            // This is needed for ContentControls, where the unique integer ID
+            // can be passed as float to simulate a "by name" lookup.
+            double fIndex = 0;
+            Index1 >>= fIndex;
+            aStringSheet = OUString::number(fIndex);
+        }
+        else if (Index1.getValueTypeClass() != css::uno::TypeClass_STRING)
         {
             sal_Int32 nIndex = 0;
-
             if ( !( Index1 >>= nIndex ) )
             {
                 throw  css::lang::IndexOutOfBoundsException( "Couldn't convert 
index to Int32" );
             }
+
             return  getItemByIntIndex( nIndex );
         }
-        OUString aStringSheet;
+        else
+            Index1 >>= aStringSheet;
 
-        Index1 >>= aStringSheet;
         return getItemByStringIndex( aStringSheet );
     }
 
diff --git a/sw/qa/core/data/docm/testModernVBA.docm 
b/sw/qa/core/data/docm/testModernVBA.docm
index be7d99a24b84..49e53b615622 100644
Binary files a/sw/qa/core/data/docm/testModernVBA.docm and 
b/sw/qa/core/data/docm/testModernVBA.docm differ
diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx 
b/sw/source/ui/vba/vbacontentcontrol.cxx
index da3f3ec6f4ee..0a156e35c96b 100644
--- a/sw/source/ui/vba/vbacontentcontrol.cxx
+++ b/sw/source/ui/vba/vbacontentcontrol.cxx
@@ -473,9 +473,9 @@ uno::Any SwVbaContentControl::getDropdownListEntries()
 
 OUString SwVbaContentControl::getID()
 {
-    //const std::shared_ptr<SwContentControl>& pCC = 
m_rCC.GetContentControl().GetContentControl();
-    //return OUString::number(static_cast<sal_uInt32>(pCC->GetId()));
-    return OUString();
+    const std::shared_ptr<SwContentControl>& pCC = 
m_rCC.GetContentControl().GetContentControl();
+    // This signed integer is treated in VBA as if it was an unsigned int.
+    return OUString::number(static_cast<sal_uInt32>(pCC->GetId()));
 }
 
 sal_Int32 SwVbaContentControl::getLevel()
diff --git a/sw/source/ui/vba/vbacontentcontrols.cxx 
b/sw/source/ui/vba/vbacontentcontrols.cxx
index 4ef73f5d196e..e39094df357a 100644
--- a/sw/source/ui/vba/vbacontentcontrols.cxx
+++ b/sw/source/ui/vba/vbacontentcontrols.cxx
@@ -65,15 +65,16 @@ lcl_getContentControl(std::u16string_view sName, 
std::u16string_view sTag,
                 && sTitle != 
pControl->GetContentControl().GetContentControl()->GetAlias())
                 continue;
 
-            //OUString sID = OUString::number(static_cast<sal_uInt32>(
-            //    pControl->GetContentControl().GetContentControl()->GetId()));
-            //if (!sName.empty() && sName != sID)
-            //    continue;
+            // When treated as a name, consider the integer ID to be unsigned
+            const OUString sID = OUString::number(static_cast<sal_uInt32>(
+                pControl->GetContentControl().GetContentControl()->GetId()));
+            if (!sName.empty() && sName != sID)
+                continue;
 
-            //if (pElementNames)
-            //    vElementNames.push_back(sID);
+            if (pElementNames)
+                vElementNames.push_back(sID);
 
-            if (rIndex == nCounter /*|| !sName.empty()*/)
+            if (rIndex == nCounter || !sName.empty())
                 break;
 
             pControl = nullptr;

Reply via email to