From b991ec60421ecda9c87e141a02ce3259a95f4896 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 27 Aug 2026 09:57:19 +0200 Subject: [PATCH] tdf#173293 Use InvocationHelper in ooo.vba.excel.Application MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ScVbaApplication now contains a comphelper::InvocationHelper member which it forwards methods and properties to when ScVbaSWFunction doesn’t recognise them. This makes it possible to access methods such as getSelection when via the XInvocation such as when accessing the object via pyuno. Change-Id: I1481d4f2e613037ae9283bd86844bd4d805cd2bf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210131 Tested-by: Jenkins Reviewed-by: Neil Roberts --- sc/PythonTest_sc_python.mk | 1 + sc/qa/python/VbaApplication.py | 67 +++++++++++++++++++++++++++++ sc/source/ui/vba/vbaapplication.cxx | 27 +++++++++--- sc/source/ui/vba/vbaapplication.hxx | 3 ++ 4 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 sc/qa/python/VbaApplication.py diff --git a/sc/PythonTest_sc_python.mk b/sc/PythonTest_sc_python.mk index 55d992565d98..97b468bb994e 100644 --- a/sc/PythonTest_sc_python.mk +++ b/sc/PythonTest_sc_python.mk @@ -11,6 +11,7 @@ $(eval $(call gb_PythonTest_PythonTest,sc_python)) $(eval $(call gb_PythonTest_add_modules,sc_python,$(SRCDIR)/sc/qa/python,\ CalcRTL \ + VbaApplication \ )) # vim: set noet sw=4 ts=4: \ No newline at end of file diff --git a/sc/qa/python/VbaApplication.py b/sc/qa/python/VbaApplication.py new file mode 100644 index 000000000000..f951abbae979 --- /dev/null +++ b/sc/qa/python/VbaApplication.py @@ -0,0 +1,67 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +import unittest +from org.libreoffice.unotest import UnoInProcess +from com.sun.star.awt import Toolkit + + +# Tests that we can access ooo.vba.excel.Application from Python. See tdf#173293. +class VbaApplication(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls._uno = UnoInProcess() + cls._uno.setUp() + + cls.xContext = cls._uno.getContext() + cls.xDoc = cls._uno.openEmptyCalcDoc() + cls.xSheet = cls.xDoc.getSheets()[0] + + # This is needed for the VBA Application to find the doc + cls.xDoc.createInstance("ooo.vba.VBAGlobals") + + xServiceManager = cls.xContext.getServiceManager() + cls.xApplication = xServiceManager.createInstanceWithContext( + "ooo.vba.excel.Application", cls.xContext) + + @classmethod + def tearDownClass(cls): + cls.xApplication = None + cls.xSheet = None + cls.xDoc.dispose() + cls.xDoc = None + cls.xContext = None + cls._uno.tearDown() + + def testSelection(self): + # Tests that we can access the Selection property + + # Select a square of 10×10 cells in the topleft + xController = self.xDoc.getCurrentController() + xRange = self.xSheet.getCellRangeByName("A1:J10") + xController.select(xRange) + + # Use the VBA API to fill in the selection + self.xApplication.Selection.Value = "x" + + # Check that the values were filled in + self.assertEqual(xRange.getCellByPosition(0, 0).getString(), "x") + self.assertEqual(xRange.getCellByPosition(9, 0).getString(), "x") + self.assertEqual(xRange.getCellByPosition(0, 9).getString(), "x") + self.assertEqual(xRange.getCellByPosition(9, 9).getString(), "x") + + def testFunction(self): + # Tests that we can call a function + self.assertEqual(int(self.xApplication.CentimetersToPoints(1)), 28) + + def testWorksheetFunction(self): + # Tests that we can call a dynamic function via XInvocation + self.assertEqual(self.xApplication.Concat("one", " ", "potato"), "one potato") + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx index 2b4d4866a50e..914f6aaab16e 100644 --- a/sc/source/ui/vba/vbaapplication.cxx +++ b/sc/source/ui/vba/vbaapplication.cxx @@ -165,7 +165,8 @@ ScVbaApplication::RemoveSink( sal_uInt32 nNumber ) ScVbaApplication::ScVbaApplication( const uno::Reference& xContext ) : ScVbaApplication_BASE( xContext ), mrAppSettings( ScVbaStaticAppSettings() ), - m_nDialogType(0) + m_nDialogType(0), + m_aInvocationHelper( xContext ) { } @@ -201,7 +202,15 @@ ScVbaApplication::invoke( const OUString& FunctionName, const uno::Sequence< uno try { uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); - aAny = xWSF->invoke( FunctionName, Params, OutParamIndex, OutParam ); + if (xWSF->hasMethod(FunctionName)) + { + aAny = xWSF->invoke( FunctionName, Params, OutParamIndex, OutParam ); + } + else + { + aAny = m_aInvocationHelper.invoke( this, FunctionName, Params, + OutParamIndex, OutParam ); + } } catch (const uno::Exception&) { @@ -214,28 +223,34 @@ void SAL_CALL ScVbaApplication::setValue( const OUString& PropertyName, const uno::Any& Value ) { uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); - xWSF->setValue( PropertyName, Value ); + if (xWSF->hasProperty(PropertyName)) + xWSF->setValue( PropertyName, Value ); + else + m_aInvocationHelper.setValue( this, PropertyName, Value ); } uno::Any SAL_CALL ScVbaApplication::getValue( const OUString& PropertyName ) { uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); - return xWSF->getValue( PropertyName ); + if (xWSF->hasProperty(PropertyName)) + return xWSF->getValue( PropertyName ); + else + return m_aInvocationHelper.getValue( this, PropertyName ); } sal_Bool SAL_CALL ScVbaApplication::hasMethod( const OUString& Name ) { uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); - return xWSF->hasMethod( Name ); + return xWSF->hasMethod( Name ) || m_aInvocationHelper.hasMethod( this, Name ); } sal_Bool SAL_CALL ScVbaApplication::hasProperty( const OUString& Name ) { uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); - return xWSF->hasProperty( Name ); + return xWSF->hasProperty( Name ) || m_aInvocationHelper.hasProperty( this, Name ); } uno::Reference< excel::XWorkbook > diff --git a/sc/source/ui/vba/vbaapplication.hxx b/sc/source/ui/vba/vbaapplication.hxx index 4a049100b608..e2bbc49cf60c 100644 --- a/sc/source/ui/vba/vbaapplication.hxx +++ b/sc/source/ui/vba/vbaapplication.hxx @@ -24,6 +24,7 @@ #include #include +#include #include namespace com::sun::star::uno { class XComponentContext; } @@ -49,6 +50,8 @@ private: std::vector> mvSinks; + comphelper::InvocationHelper m_aInvocationHelper; + protected: virtual css::uno::Reference< css::frame::XModel > getCurrentDocument() override;