ScriptForge CallByName manages arrays

The bug "CallByName() does not work when the returned value
is an array"
   https://bugs.documentfoundation.org/show_bug.cgi?id=138155
is now fixed thanks to tdf#187145

This is a major improvement for the protocol
designed to make ScriptForge run smoothly
in Python as well as in Basic.

Indeed, CallByName() is a cornerstone of that protocol.
The implementation of this protocol is now
greatly simplified: the previous use of
hardcoded calls to workaround the limitation
to scalars of CallByName() has been suppressed.

The actual commit has no effect on existing scripts.
The documentation is not impacted.

Change-Id: Id01bb2d2d8be587d9c6aed227d172d10ddd85d4e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199740
Tested-by: Jenkins
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
This commit is contained in:
Jean-Pierre Ledure
2026-02-20 08:54:43 +01:00
parent caa0397cf9
commit 485d6db955
3 changed files with 63 additions and 163 deletions
@@ -553,12 +553,10 @@ class SFServices(object):
flgDictArg = 32 # Invoked service method may contain a dict argument
flgDateArg = 64 # Invoked service method may contain a date argument
flgDateRet = 128 # Invoked service method can return a date
flgArrayArg = 512 # 1st argument can be a 2D array
flgArrayRet = 1024 # Invoked service method can return a 2D array (standard modules) or any array (class modules)
flgUno = 256 # Invoked service method/property can return a UNO object
flgObject = 2048 # N-th argument may be a Basic object
# N (default = 0) can be passed as companion in a tuple
flgHardCode = 4096 # Force hardcoded call to method, avoid CallByName()
flgObject = 512 # N-th argument may be a Basic object
# N (default = 0) can be passed as companion in a tuple
flgHardCode = 1024 # Force hardcoded call to method, avoid CallByName()
# Basic class type
moduleClass, moduleStandard = 2, 1
#
@@ -661,13 +659,13 @@ class SFServices(object):
def basicmethods(self):
if self.serviceimplementation == 'basic':
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Methods')
return self.ExecMethod(self.vbMethod, 'Methods')
else:
return []
def basicproperties(self):
if self.serviceimplementation == 'basic':
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Properties')
return self.ExecMethod(self.vbMethod, 'Properties')
else:
return []
@@ -713,7 +711,7 @@ class SFScriptForge:
Difference with the Basic version: dates are returned in their iso format,
not as any of the datetime objects.
"""
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'ImportFromCSVFile',
return self.ExecMethod(self.vbMethod, 'ImportFromCSVFile',
filename, delimiter, dateformat)
# #########################################################################
@@ -1226,7 +1224,7 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod, 'FileExists', filename)
def Files(self, foldername, filter = '', includesubfolders = False):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Files', foldername, filter, includesubfolders)
return self.ExecMethod(self.vbMethod, 'Files', foldername, filter, includesubfolders)
def FolderExists(self, foldername):
return self.ExecMethod(self.vbMethod, 'FolderExists', foldername)
@@ -1286,7 +1284,7 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod, 'PickFolder', defaultfolder, title, freetext)
def SubFolders(self, foldername, filter = '', includesubfolders = False):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'SubFolders', foldername,
return self.ExecMethod(self.vbMethod, 'SubFolders', foldername,
filter, includesubfolders)
@classmethod
@@ -1578,7 +1576,7 @@ class SFScriptForge:
return cls.SIMPLEEXEC(scope + '#' + script, *args)
def GetRangeFromCalc(self, filename, range):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetRangeFromCalc', filename, range)
return self.ExecMethod(self.vbMethod, 'GetRangeFromCalc', filename, range)
def GetPDFExportOptions(self):
return self.ExecMethod(self.vbMethod, 'GetPDFExportOptions')
@@ -1604,13 +1602,13 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod + self.flgDictArg, 'SetPDFExportOptions', pdfoptions)
def UnoMethods(self, unoobject):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'UnoMethods', unoobject)
return self.ExecMethod(self.vbMethod, 'UnoMethods', unoobject)
def UnoObjectType(self, unoobject):
return self.ExecMethod(self.vbMethod, 'UnoObjectType', unoobject)
def UnoProperties(self, unoobject):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'UnoProperties', unoobject)
return self.ExecMethod(self.vbMethod, 'UnoProperties', unoobject)
def WebService(self, uri):
return self.ExecMethod(self.vbMethod, 'WebService', uri)
@@ -1635,7 +1633,7 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod, 'Exists', variablename)
def ReadValue(self, variablename):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'ReadValue', variablename)
return self.ExecMethod(self.vbMethod, 'ReadValue', variablename)
def Remove(self, variablename):
return self.ExecMethod(self.vbMethod, 'Remove', variablename)
@@ -1697,11 +1695,11 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod, 'IsUrl', inputstr)
def SplitNotQuoted(self, inputstr, delimiter = ' ', occurrences = 0, quotechar = '"'):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'SplitNotQuoted', inputstr, delimiter,
return self.ExecMethod(self.vbMethod, 'SplitNotQuoted', inputstr, delimiter,
occurrences, quotechar)
def Wrap(self, inputstr, width = 70, tabsize = 8):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Wrap', inputstr, width, tabsize)
return self.ExecMethod(self.vbMethod, 'Wrap', inputstr, width, tabsize)
# #########################################################################
# SF_TextStream CLASS
@@ -1813,7 +1811,7 @@ class SFScriptForge:
return self.ExecMethod(self.vbMethod, 'CreateDocument', documenttype, templatefile, hidden)
def Documents(self):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Documents')
return self.ExecMethod(self.vbMethod, 'Documents')
def EnterValue(self, prompt = '', valuetype = 'STRING', default = '', title = '', choices = (), format = ''):
if isinstance(default, (datetime.datetime, datetime.time)):
@@ -1925,7 +1923,7 @@ class SFDatabases:
return self.ExecMethod(self.vbMethod, 'DSum', expression, tablename, criteria)
def GetRows(self, sqlcommand, directsql = False, header = False, maxrows = 0):
return self.ExecMethod(self.vbMethod + self.flgArrayRet + self.flgDateRet, 'GetRows', sqlcommand,
return self.ExecMethod(self.vbMethod + self.flgDateRet, 'GetRows', sqlcommand,
directsql, header, maxrows)
def OpenFormDocument(self, formdocument):
@@ -1995,7 +1993,7 @@ class SFDatabases:
return self.ExecMethod(self.vbMethod, 'ExportValueToFile', fieldname, filename, overwrite)
def GetRows(self, header = False, maxrows = 0):
return self.ExecMethod(self.vbMethod + self.flgArrayRet + self.flgDateRet, 'GetRows', header, maxrows)
return self.ExecMethod(self.vbMethod + self.flgDateRet, 'GetRows', header, maxrows)
def GetValue(self, fieldname):
return self.ExecMethod(self.vbMethod, 'GetValue', fieldname)
@@ -2068,7 +2066,7 @@ class SFDatabases:
return self.ExecMethod(self.vbMethod, 'RemoveMenu', menuheader)
def Toolbars(self, toolbarname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Toolbars', toolbarname)
return self.ExecMethod(self.vbMethod, 'Toolbars', toolbarname)
# #####################################################################################################################
@@ -2130,7 +2128,7 @@ class SFDialogs:
return self.ExecMethod(self.vbMethod, 'CloneControl', sourcename, controlname, left, top)
def Controls(self, controlname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet + self.flgHardCode, 'Controls', controlname)
return self.ExecMethod(self.vbMethod, 'Controls', controlname)
def CreateButton(self, controlname, place, toggle = False, push = ''):
return self.ExecMethod(self.vbMethod, 'CreateButton', controlname, place, toggle, push)
@@ -2343,7 +2341,7 @@ class SFDialogs:
return self.ExecMethod(self.vbMethod, 'SetFocus')
def SetTableData(self, dataarray, widths = (1,), alignments = '', rowheaderwidth = 10):
return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetTableData', dataarray, widths, alignments,
return self.ExecMethod(self.vbMethod, 'SetTableData', dataarray, widths, alignments,
rowheaderwidth)
def WriteLine(self, line = ''):
@@ -2396,7 +2394,7 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
def ContextMenus(self, contextmenuname = '', submenuchar = '>'):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'ContextMenus', contextmenuname, submenuchar)
return self.ExecMethod(self.vbMethod, 'ContextMenus', contextmenuname, submenuchar)
def CreateMenu(self, menuheader, before = '', submenuchar = '>'):
return self.ExecMethod(self.vbMethod, 'CreateMenu', menuheader, before, submenuchar)
@@ -2442,12 +2440,12 @@ class SFDocuments:
# Exclude Base and Math
doctype = self.DocumentType
if doctype in ('Calc', 'Writer', 'FormDocument', 'Draw', 'Impress'):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Styles', family, namepattern, used,
return self.ExecMethod(self.vbMethod, 'Styles', family, namepattern, used,
userdefined, parentstyle, category)
raise RuntimeError('The \'Styles\' method is not applicable to {0} documents'.format(doctype))
def Toolbars(self, toolbarname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Toolbars', toolbarname)
return self.ExecMethod(self.vbMethod, 'Toolbars', toolbarname)
def XStyle(self, family, stylename):
# Exclude Base and Math
@@ -2490,10 +2488,10 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'CloseFormDocument', formdocument)
def FormDocuments(self):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'FormDocuments')
return self.ExecMethod(self.vbMethod, 'FormDocuments')
def Forms(self, formdocument, form = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', formdocument, form)
return self.ExecMethod(self.vbMethod, 'Forms', formdocument, form)
def GetDatabase(self, user = '', password = ''):
return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
@@ -2607,7 +2605,7 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'BorderRange', targetrange, borders, filterformula, filterscope)
def Charts(self, sheetname, chartname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Charts', sheetname, chartname)
return self.ExecMethod(self.vbMethod, 'Charts', sheetname, chartname)
def ClearAll(self, range, filterformula = '', filterscope = ''):
return self.ExecMethod(self.vbMethod, 'ClearAll', range, filterformula, filterscope)
@@ -2691,16 +2689,16 @@ class SFDocuments:
filterformula, filterscope)
def Forms(self, sheetname, form = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', sheetname, form)
return self.ExecMethod(self.vbMethod, 'Forms', sheetname, form)
def GetColumnName(self, columnnumber):
return self.ExecMethod(self.vbMethod, 'GetColumnName', columnnumber)
def GetFormula(self, range):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetFormula', range)
return self.ExecMethod(self.vbMethod, 'GetFormula', range)
def GetValue(self, range):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetValue', range)
return self.ExecMethod(self.vbMethod, 'GetValue', range)
def ImportFromCSVFile(self, filename, destinationcell, filteroptions = ScriptForge.cstSymEmpty):
return self.ExecMethod(self.vbMethod, 'ImportFromCSVFile', filename, destinationcell, filteroptions)
@@ -2748,19 +2746,19 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'RenameSheet', sheetname, newname)
def SetArray(self, targetcell, value):
return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetArray', targetcell, value)
return self.ExecMethod(self.vbMethod, 'SetArray', targetcell, value)
def SetCellStyle(self, targetrange, style, filterformula = '', filterscope = ''):
return self.ExecMethod(self.vbMethod, 'SetCellStyle', targetrange, style, filterformula, filterscope)
def SetFormula(self, targetrange, formula):
return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetFormula', targetrange, formula)
return self.ExecMethod(self.vbMethod, 'SetFormula', targetrange, formula)
def SetValue(self, targetrange, value):
return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetValue', targetrange, value)
return self.ExecMethod(self.vbMethod, 'SetValue', targetrange, value)
def Shapes(self, sheetname, shapename = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Shapes', sheetname, shapename)
return self.ExecMethod(self.vbMethod, 'Shapes', sheetname, shapename)
def ShiftDown(self, range, wholerow = False, rows = 0):
return self.ExecMethod(self.vbMethod, 'ShiftDown', range, wholerow, rows)
@@ -2872,7 +2870,7 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'CloseFormDocument')
def Controls(self, controlname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
return self.ExecMethod(self.vbMethod, 'Controls', controlname)
def GetDatabase(self, user = '', password = ''):
return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
@@ -2896,7 +2894,7 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'Requery')
def Subforms(self, subform = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Subforms', subform)
return self.ExecMethod(self.vbMethod, 'Subforms', subform)
# #########################################################################
# SF_FormControl CLASS
@@ -2927,7 +2925,7 @@ class SFDocuments:
Visible = 2, XControlModel = 0, XControlView = 0)
def Controls(self, controlname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
return self.ExecMethod(self.vbMethod, 'Controls', controlname)
def SetFocus(self):
return self.ExecMethod(self.vbMethod, 'SetFocus')
@@ -2963,7 +2961,7 @@ class SFDocuments:
return self.ExecMethod(self.vbMethod, 'CloseDocument')
def Forms(self, form = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', form)
return self.ExecMethod(self.vbMethod, 'Forms', form)
def GetDatabase(self, user = '', password = ''):
return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
@@ -3000,7 +2998,7 @@ class SFDocuments:
return windowname,
def Forms(self, form = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', form)
return self.ExecMethod(self.vbMethod, 'Forms', form)
def ImportStylesFromFile(self, filename = '', families = '', overwrite = False):
return self.ExecMethod(self.vbMethod, 'ImportStylesFromFile', filename, families, overwrite)
@@ -3142,7 +3140,7 @@ class SFWidgets:
ResourceURL = 0, Visible = 3, XUIElement = 0)
def ToolbarButtons(self, buttonname = ''):
return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'ToolbarButtons', buttonname)
return self.ExecMethod(self.vbMethod, 'ToolbarButtons', buttonname)
# #########################################################################
# SF_ToolbarButton CLASS