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;