tdf#173293 Use InvocationHelper in ooo.vba.excel.Application

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 <nroberts@libreoffice.org>
This commit is contained in:
Neil Roberts
2026-09-25 10:39:30 +02:00
parent 6154aa313c
commit b991ec6042
4 changed files with 92 additions and 6 deletions
+1
View File
@@ -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:
+67
View File
@@ -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:
+21 -6
View File
@@ -165,7 +165,8 @@ ScVbaApplication::RemoveSink( sal_uInt32 nNumber )
ScVbaApplication::ScVbaApplication( const uno::Reference<uno::XComponentContext >& 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 >
+3
View File
@@ -24,6 +24,7 @@
#include <ooo/vba/excel/XApplication.hpp>
#include <vbahelper/vbaapplicationbase.hxx>
#include <comphelper/invocationhelper.hxx>
#include <cppuhelper/implbase.hxx>
namespace com::sun::star::uno { class XComponentContext; }
@@ -49,6 +50,8 @@ private:
std::vector<css::uno::Reference< ooo::vba::XSink >> mvSinks;
comphelper::InvocationHelper m_aInvocationHelper;
protected:
virtual css::uno::Reference< css::frame::XModel > getCurrentDocument() override;