[Libreoffice-commits] core.git: wizards/source

Jean-Pierre Ledure (via logerrit) logerrit at kemper.freedesktop.org
Sun Apr 4 15:04:53 UTC 2021


 wizards/source/scriptforge/SF_PythonHelper.xba   |   55 ++-
 wizards/source/scriptforge/python/scriptforge.py |  396 ++++++++++++++++++++++-
 wizards/source/sfdocuments/SF_Base.xba           |    2 
 wizards/source/sfdocuments/SF_Calc.xba           |   56 ++-
 wizards/source/sfdocuments/SF_Form.xba           |    6 
 wizards/source/sfdocuments/SF_FormControl.xba    |    8 
 wizards/source/sfdocuments/SF_Register.xba       |    4 
 7 files changed, 479 insertions(+), 48 deletions(-)

New commits:
commit 88d3172f170fcb2e49d832b80444fd16b818deed
Author:     Jean-Pierre Ledure <jp at ledure.be>
AuthorDate: Sun Apr 4 15:56:44 2021 +0200
Commit:     Jean-Pierre Ledure <jp at ledure.be>
CommitDate: Sun Apr 4 17:04:15 2021 +0200

    ScriptForge (scriptforge.py) UI, Document & Calc classes
    
    Changes in the Basic-Python engine:
    - arguments of methods may be 2D arrays
    - 1st argument of method may be a Basic object
    - properties starting with 'X' may contain UNO objects
    - GetProperty may contain 1 argument
    
    Calc class is a subclass of the Document class in Python
    (in Basic it is simulated)
    A CalcReference class is also created to contain
    Range and Sheet objects
    
    Many comments have been reviewed for consistency in SF_Calc,
    SF_Form and SF_FormControl.xba
    Conversion to DataArrays is improved to process input
    arrays of arrays. Date conversions are supported.
    
    Change-Id: Id6254d668ec981b00555e7e277c4d31982c00092
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113568
    Tested-by: Jean-Pierre Ledure <jp at ledure.be>
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <jp at ledure.be>

diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba
index 5acd2dfc9228..728cb7b52fcc 100644
--- a/wizards/source/scriptforge/SF_PythonHelper.xba
+++ b/wizards/source/scriptforge/SF_PythonHelper.xba
@@ -544,6 +544,7 @@ Dim vArgs() As Variant				'	Alias for Args()
 Dim sScript As String				'	Argument of ExecuteBasicScript()
 Dim vParams As Variant				'	Array of arguments to pass to a ParamArray
 Dim sObjectType As String			'	Alias of object.ObjectType
+Dim sServiceName As String			'	Alias of BasicObject.ServiceName
 Dim bBasicClass As Boolean			'	True when BasicObject is a class
 Dim sLibrary As String				'	Library where the object belongs to
 Dim bUno As Boolean					'	Return value is a UNO object
@@ -560,9 +561,10 @@ Const vbGet = 2, vbLet = 4, vbMethod = 1, vbSet = 8
 '	Protocol flags
 Const cstDateArg = 64		'	May contain a date argument
 Const cstDateRet = 128		'	Return value can be a date
-Const cstArgArray = 512		'	1st argument can be a 2D array
+Const cstArgArray = 512		'	Any argument can be a 2D array
 Const cstRetArray = 1024	'	Return value can be an array
 Const cstUno = 256			'	Return value can be a UNO object
+Const cstObject = 2048		'	1st argument is a Basic object when numeric
 '	Object nature in returned array
 Const objMODULE = 1, objCLASS = 2, objUNO = 3
 
@@ -576,13 +578,21 @@ Check:
 	'	Reinterpret arguments one by one into vArgs, examine iso-dates and conventional NoArgs/Empty/Null values
 	iNbArgs = -1
 	vArgs = Array()
+
 	If UBound(Args) >= 0 Then
 		For i = 0 To UBound(Args)
 			vArg = Args(i)
+			'	Are there arguments ?
 			If i = 0 And VarType(vArg) = V_STRING Then
 				If vArg = cstNoArgs Then Exit For
 			End If
-			If VarType(vArg) = V_STRING Then
+			'	Is 1st argument a reference to a Basic object ?
+			If i = 0 And (( CallType And cstObject ) = cstObject) And SF_Utils._VarTypeExt(vArg) = V_NUMERIC Then
+				If vArg < 0 Or Not IsArray(_SF_.PythonStorage) Then GoTo Catch
+				If vArg > UBound(_SF_.PythonStorage) Then GoTo Catch
+				vArg = _SF_.PythonStorage(vArg)
+			'	Is argument a symbolic constant for Null, Empty, ... , or a date?
+			ElseIf VarType(vArg) = V_STRING Then
 				If Len(vArg) = 0 Then
 				ElseIf vArg = cstSymEmpty Then
 					vArg = Empty
@@ -649,24 +659,25 @@ Try:
 			If BasicObject > UBound(_SF_.PythonStorage) Then GoTo Catch
 			vBasicObject = _SF_.PythonStorage(BasicObject)
 			sObjectType = vBasicObject.ObjectType
+			sServiceName = vBasicObject.ServiceName
 			'	Basic modules have type = "SF_*"
 			bBasicClass = ( Left(sObjectType, 3) <> "SF_" )
-			sLibrary = Split(vBasicObject.ServiceName, ".")(0)
+			sLibrary = Split(sServiceName, ".")(0)
 			
 			'	Methods in standard modules returning a date are hardcoded as exceptions
 			If Not bBasicClass And ((CallType And vbMethod) = vbMethod) And ((CallType And cstDateRet) = cstDateRet) Then
-				Select Case sLibrary
-					Case "ScriptForge"
-						If sObjectType = "SF_FileSystem" And Script = "GetFileModified" Then vReturn = SF_FileSystem.GetFileModified(vArgs(0))
+				Select Case sServiceName
+					Case "ScriptForge.FileSystem"
+						If Script = "GetFileModified" Then vReturn = SF_FileSystem.GetFileModified(vArgs(0))
 				End Select
 
 			'	Methods in usual modules using a 2D array or returning arrays are hardcoded as exceptions
 			ElseIf Not bBasicClass And _
 						(((CallType And vbMethod) + (CallType And cstArgArray)) = vbMethod + cstArgArray Or _
 				   		((CallType And vbMethod) + (CallType And cstRetArray)) = vbMethod + cstRetArray) Then
-				Select Case sLibrary
-					Case "ScriptForge"
-						If sObjectType = "SF_Array" And Script = "ImportFromCSVFile" Then vReturn = SF_Array.ImportFromCSVFile(vArgs(0), vArgs(1), vArgs(2))
+				Select Case sServiceName
+					Case "ScriptForge.Array"
+						If Script = "ImportFromCSVFile" Then vReturn = SF_Array.ImportFromCSVFile(vArgs(0), vArgs(1), vArgs(2))
 				End Select
 
 			'	Methods in usual modules are called by ExecuteBasicScript() except if they use a ParamArray
@@ -688,17 +699,26 @@ Try:
 				_SF_.StackLevel = 0
 			
 			'	Properties in any service are got and set with obj.GetProperty/SetProperty(...)
-			ElseIf (CallType And vbGet) = vbGet Then
-				'	vReturn = sess.ExecuteBasicScript(, sLibrary & "." & sObjectType & ".GetProperty", Script)
-				vReturn = vBasicObject.GetProperty(Script)
+			ElseIf (CallType And vbGet) = vbGet Then	'	In some cases (Calc ...) GetProperty may have an argument
+				If UBound(vArgs) < 0 Then vReturn = vBasicObject.GetProperty(Script) Else vReturn = vBasicObject.GetProperty(Script, vArgs(0))
 			ElseIf (CallType And vbLet) = vbLet Then
-				'	vReturn = sess.ExecuteBasicScript(, sLibrary & "." & sObjectType & ".SetProperty", Script, vArgs(0))
 				vReturn = vBasicObject.SetProperty(Script, vArgs(0))
 			
 			'	Methods in class modules using a 2D array or returning arrays are hardcoded as exceptions
 			ElseIf ((CallType And vbMethod) + (CallType And cstArgArray)) = vbMethod + cstArgArray Or _
 				   ((CallType And vbMethod) + (CallType And cstRetArray)) = vbMethod + cstRetArray Then
-				Select Case sLibrary
+				Select Case sServiceName
+					Case "SFDocuments.Document"
+						If Script = "Forms" Then vReturn = vBasicObject.Forms(vArgs(0))
+					Case "SFDocuments.Calc"
+						Select Case Script
+							Case "Forms"		:	vReturn = vBasicObject.Forms(vArgs(0), vArgs(1))
+							Case "GetFormula"	:	vReturn = vBasicObject.GetFormula(vArgs(0))
+							Case "GetValue"		:	vReturn = vBasicObject.GetValue(vArgs(0))
+							Case "SetArray"		:	vReturn = vBasicObject.SetArray(vArgs(0), vArgs(1))
+							Case "SetFormula"	:	vReturn = vBasicObject.SetFormula(vArgs(0), vArgs(1))
+							Case "SetValue"		:	vReturn = vBasicObject.SetValue(vArgs(0), vArgs(1))
+						End Select
 				End Select
 			
 			'	Methods in class modules are invoked with CallByName
@@ -749,7 +769,7 @@ Try:
 		vReturnArray(1) = VarType(vReturn)
 		vReturnArray(2) = iDims
 	ElseIf VarType(vReturn) = V_OBJECT And Not IsNull(vReturn) Then
-		'	Uno or not Uno ?BuildPath
+		'	Uno or not Uno ?
 		bUno = False
 		If (CallType And cstUno) = cstUno Then		'	UNO considered only when pre-announced in CallType
 			If Len(sess.UnoObjectType(vReturn)) > 0 Then bUno = True
@@ -766,7 +786,10 @@ Try:
 		If Not bUno Then
 			vReturnArray(3) = vReturn.ObjectType
 			vReturnArray(4) = vReturn.ServiceName
-			If SF_Array.Contains(vReturn.Properties(), "Name", SortOrder := "ASC") Then vReturnArray(5) = vReturn.Name Else vReturnArray(5) = ""
+			vReturnArray(5) = ""
+			If vReturn.ObjectType <> "SF_CalcReference" Then	'	Calc references are implemented as a Type ... End Type data structure
+				If SF_Array.Contains(vReturn.Properties(), "Name", SortOrder := "ASC") Then vReturnArray(5) = vReturn.Name
+			End If
 		End If
 	Else	'	Scalar or Nothing
 		ReDim vReturnArray(0 To 1)
diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py
index c90264ad09bb..b0c6c53077d5 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -299,12 +299,13 @@ class ScriptForge(object, metaclass = _Singleton):
             else:
                 # Create the new class instance of the right subclass of SFServices()
                 servname = returntuple[cstService]
+                if servname not in cls.serviceslist:
+                    # When service not found
+                    raise RuntimeError("The service '" + servname + "' is not available in Python. Execution stops.")
                 subcls = cls.serviceslist[servname]
                 if subcls is not None:
                     return subcls(returntuple[cstValue], returntuple[cstType], returntuple[cstClass],
                                   returntuple[cstName])
-                # When service not found
-                raise RuntimeError("The service '" + servname + "' is not available in Python. Execution stops.")
         elif returntuple[cstVarType] >= ScriptForge.V_ARRAY:
             pass
         elif returntuple[cstVarType] == ScriptForge.V_DATE:
@@ -386,6 +387,7 @@ class SFServices(object):
     flgArrayArg = 512  # 1st argument can be a 2D array
     flgArrayRet = 1024  # Invoked service method can return a 2D array
     flgUno = 256  # Invoked service method/property can return a UNO object
+    flgObject = 2048  # 1st argument may be a Basic object
     # Basic class type
     moduleClass, moduleStandard = 2, 1
     #
@@ -501,12 +503,18 @@ class SFServices(object):
         if len(methodname) > 0:
             return self.EXEC(self.objectreference, flags, methodname, *args)
 
-    def GetProperty(self, propertyname):
+    def GetProperty(self, propertyname, arg = None):
         """
             Get the given property from the Basic world
             """
         if self.serviceimplementation == 'basic':
-            return self.EXEC(self.objectreference, self.vbGet, propertyname)
+            # Conventionally properties starting with X (and only them) may return a UNO object
+            calltype = self.vbGet + (self.flgUno if propertyname[0] == 'X' else 0)
+            if arg is None:
+                return self.EXEC(self.objectreference, calltype, propertyname)
+            else:   # There are a few cases (Calc ...) where GetProperty accepts an argument
+                return self.EXEC(self.objectreference, calltype, propertyname, arg)
+        return None
     getProperty, getproperty = GetProperty, GetProperty
 
     def Properties(self):
@@ -526,6 +534,8 @@ class SFServices(object):
 #                       SFScriptForge CLASS    (alias of ScriptForge Basic library)                                 ###
 # #####################################################################################################################
 class SFScriptForge:
+    pass
+
     # #########################################################################
     # SF_Array CLASS
     # #########################################################################
@@ -1020,7 +1030,7 @@ class SFScriptForge:
         # Mandatory class properties for service registration
         serviceimplementation = 'basic'
         servicename = 'ScriptForge.Platform'
-        servicesynonyms = ()
+        servicesynonyms = ('platform', 'scriptforge.platform')
         serviceproperties = dict(Architecture = False, ComputerName = False, CPUCount = False, CurrentUser = False,
                                  Locale = False, Machine = False, OfficeVersion = False, OSName = False,
                                  OSPlatform = False, OSRelease = False, OSVersion = False, Processor = False)
@@ -1312,8 +1322,382 @@ class SFScriptForge:
             return self.Execute(self.vbMethod, 'Terminate')
         terminate = Terminate
 
+    # #########################################################################
+    # SF_UI CLASS
+    # #########################################################################
+    class SF_UI(SFServices, metaclass = _Singleton):
+        """
+            Singleton class for the identification and the manipulation of the
+            different windows composing the whole LibreOffice application:
+                - Windows selection
+                - Windows moving and resizing
+                - Statusbar settings
+                - Creation of new windows
+                - Access to the underlying "documents"
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'ScriptForge.UI'
+        servicesynonyms = ('ui', 'scriptforge.ui')
+        serviceproperties = dict(ActiveWindow = False)
+        propertysynonyms = SFServices._getAttributeSynonyms(serviceproperties)
+
+        # Class constants
+        MACROEXECALWAYS, MAROEXECNEVER, MACROEXECNORMAL = 2, 1, 0
+        BASEDOCUMENT, CALCDOCUMENT, DRAWDOCUMENT, IMPRESSDOCUMENT, MATHDOCUMENT, WRITERDOCUMENT = \
+            'Base', 'Calc', 'Draw', 'Impress', 'Math', 'Writer'
+
+        @property
+        def ActiveWindow(self):
+            return self.Execute(self.vbMethod, 'ActiveWindow')
+        activeWindow, activewindow = ActiveWindow, ActiveWindow
+
+        def Activate(self, windowname = ''):
+            return self.Execute(self.vbMethod, 'Activate', windowname)
+        activate = Activate
+
+        def CreateBaseDocument(self, filename, embeddeddatabase = 'HSQLDB', registrationname = ''):
+            return self.Execute(self.vbMethod, 'CreateBaseDocument', filename, embeddeddatabase, registrationname)
+        createBaseDocument, createbasedocument = CreateBaseDocument, CreateBaseDocument
+
+        def CreateDocument(self, documenttype = '', templatefile = '', hidden = False):
+            return self.Execute(self.vbMethod, 'CreateDocument', documenttype, templatefile, hidden)
+        createDocument, createdocument = CreateDocument, CreateDocument
+
+        def Documents(self):
+            return self.Execute(self.vbMethod, 'Documents')
+        documents = Documents
+
+        def GetDocument(self, windowname = ''):
+            return self.Execute(self.vbMethod, 'GetDocument', windowname)
+        getDocument, getdocument = GetDocument, GetDocument
+
+        def Maximize(self, windowname = ''):
+            return self.Execute(self.vbMethod, 'Maximize', windowname)
+        maximize = Maximize
+
+        def Minimize(self, windowname = ''):
+            return self.Execute(self.vbMethod, 'Minimize', windowname)
+        minimize = Minimize
+
+        def OpenBaseDocument(self, filename = '', registrationname = '', macroexecution = MACROEXECNORMAL):
+            return self.Execute(self.vbMethod, 'OpenBaseDocument', filename, registrationname, macroexecution)
+        openBaseDocument, openbasedocument = OpenBaseDocument, OpenBaseDocument
+
+        def OpenDocument(self, filename, password = '', readonly = False, hidden = False,
+                         macroexecution = MACROEXECNORMAL, filtername = '', filteroptions = ''):
+            return self.Execute(self.vbMethod, 'OpenDocument', filename, password, readonly, hidden,
+                                macroexecution, filtername, filteroptions)
+        openDocument, opendocument = OpenDocument, OpenDocument
+
+        def Resize(self, left = -1, top = -1, width = -1, height = -1):
+            return self.Execute(self.vbMethod, 'Resize', left, top, width, height)
+        resize = Resize
+
+        def SetStatusbar(self, text = '', percentage = -1):
+            return self.Execute(self.vbMethod, 'SetStatusbar', text, percentage)
+        setStatusbar, setstatusbar = SetStatusbar, SetStatusbar
+
+        # ShowProgressBar - not supported in Python
+
+        def WindowExists(self, windowname):
+            return self.Execute(self.vbMethod, 'WindowExists', windowname)
+        windowExists, windowexists = WindowExists, WindowExists
+
+
+# #####################################################################################################################
+#                       SFDocuments CLASS    (alias of SFDocuments Basic library)                                   ###
+# #####################################################################################################################
+class SFDocuments:
+    """
+        The SFDocuments class gathers a number of classes, methods and properties making easy
+        managing and manipulating LibreOffice documents
+        """
+    pass
+
+    # #########################################################################
+    # SF_Document CLASS
+    # #########################################################################
+    class SF_Document(SFServices):
+        """
+            The methods and properties are generic for all types of documents: they are combined in the
+            current SF_Document class
+                - saving, closing documents
+                - accessing their standard or custom properties
+            Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Base, ...
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDocuments.Document'
+        servicesynonyms = ('document', 'sfdocuments.document')
+        serviceproperties = dict(Description = True, DocumentType = False, IsBase = False, IsCalc = False,
+                                 IsDraw = False, IsImpress = False, IsMath = False, IsWriter = False,
+                                 Keywords = True, Readonly = False, Subject = True, Title = True,
+                                 XComponent = False)
+        propertysynonyms = SFServices._getAttributeSynonyms(serviceproperties)
+        # Force for each property to get its value from Basic - due to intense interactivity with user
+        forceGetProperty = True
+
+        @property
+        def XComponent(self):
+            return self.Execute(self.vbGet + self.flgUno, 'XComponent')
+        xComponent, xcomponent = XComponent, XComponent
+
+        def Activate(self):
+            return self.Execute(self.vbMethod, 'Activate')
+        activate = Activate
+
+        def CloseDocument(self, saveask = True):
+            return self.Execute(self.vbMethod, 'CloseDocument', saveask)
+        closeDocument, closedocument = CloseDocument, CloseDocument
+
+        def Forms(self, form = ''):
+            return self.Execute(self.vbMethod + self.flgArrayRet, 'Forms', form)
+        forms = Forms
+
+        def RunCommand(self, command):
+            return self.Execute(self.vbMethod, 'RunCommand', command)
+        runCommand, runcommand = RunCommand, RunCommand
+
+        def Save(self):
+            return self.Execute(self.vbMethod, 'Save')
+        save = Save
+
+        def SaveAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
+            return self.Execute(self.vbMethod, 'SaveAs', filename, overwrite, password, filtername, filteroptions)
+        saveAs, saveas = SaveAs, SaveAs
+
+        def SaveCopyAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
+            return self.Execute(self.vbMethod, 'SaveCopyAs', filename, overwrite, password, filtername, filteroptions)
+        saveCopyAs, savecopyas = SaveCopyAs, SaveCopyAs
+
+    # #########################################################################
+    # SF_Base CLASS
+    # #########################################################################
+    class SF_Base(SF_Document, SFServices):
+        """
+            The SF_Base module is provided mainly to block parent properties that are NOT applicable to Base documents
+            In addition, it provides methods to identify form documents and access their internal forms
+            (read more elsewhere (the "SFDocuments.Form" service) about this subject)
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDocuments.Base'
+        servicesynonyms = ()
+        serviceproperties = dict(DocumentType = False, IsBase = False, IsCalc = False,
+                                 IsDraw = False, IsImpress = False, IsMath = False, IsWriter = False,
+                                 XComponent = False)
+        propertysynonyms = SFServices._getAttributeSynonyms(serviceproperties)
+
+    # #########################################################################
+    # SF_Calc CLASS
+    # #########################################################################
+    class SF_Calc(SF_Document, SFServices):
+        """
+            The SF_Calc module is focused on :
+                - management (copy, insert, move, ...) of sheets within a Calc document
+                - exchange of data between Basic data structures and Calc ranges of values
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDocuments.Calc'
+        servicesynonyms = ('calc', 'sfdocuments.calc')
+        serviceproperties = dict(CurrentSelection = True, Sheets = False,
+                                 Description = True, DocumentType = False, IsBase = False, IsCalc = False,
+                                 IsDraw = False, IsImpress = False, IsMath = False, IsWriter = False,
+                                 Keywords = True, Readonly = False, Subject = True, Title = True,
+                                 XComponent = False)
+        propertysynonyms = SFServices._getAttributeSynonyms(serviceproperties)
+        # Force for each property to get its value from Basic - due to intense interactivity with user
+        forceGetProperty = True
+
+        # Next functions are implemented in Basic as read-only properties with 1 argument
+        def Height(self, rangename):
+            return self.GetProperty('Height', rangename)
+        height = Height
+
+        def LastCell(self, sheetname):
+            return self.GetProperty('LastCell', sheetname)
+        lastCell, lastcell = LastCell, LastCell
+
+        def LastColumn(self, sheetname):
+            return self.GetProperty('LastColumn', sheetname)
+        lastColumn, lastcolumn = LastColumn, LastColumn
+
+        def LastRow(self, sheetname):
+            return self.GetProperty('LastRow', sheetname)
+        lastRow, lastrow = LastRow, LastRow
+
+        def Range(self, rangename):
+            return self.GetProperty('Range', rangename)
+        range = Range
+
+        def Sheet(self, sheetname):
+            return self.GetProperty('Sheet', sheetname)
+        sheet = Sheet
+
+        def Width(self, rangename):
+            return self.GetProperty('Width', rangename)
+        width = Width
+
+        def XCellRange(self, rangename):
+            return self.Execute(self.vbGet + self.flgUno, 'XCellRange', rangename)
+        xCellRange, xcellrange = XCellRange, XCellRange
+
+        def XSpreadsheet(self, sheetname):
+            return self.Execute(self.vbGet + self.flgUno, 'XSpreadsheet', sheetname)
+        xSpreadsheet, xspreadsheet = XSpreadsheet, XSpreadsheet
+
+        # Usual methods
+        def Activate(self, sheetname = ''):
+            return self.Execute(self.vbMethod, 'Activate', sheetname)
+        activate = Activate
+
+        def ClearAll(self, range):
+            return self.Execute(self.vbMethod, 'ClearAll', range)
+        clearAll, clearall = ClearAll, ClearAll
+
+        def ClearFormats(self, range):
+            return self.Execute(self.vbMethod, 'ClearFormats', range)
+        clearFormats, clearformats = ClearFormats, ClearFormats
+
+        def ClearValues(self, range):
+            return self.Execute(self.vbMethod, 'ClearValues', range)
+        clearValues, clearvalues = ClearValues, ClearValues
+
+        def CopySheet(self, sheetname, newname, beforesheet = 32768):
+            sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
+            return self.Execute(self.vbMethod + self.flgObject, 'CopySheet', sheet, newname, beforesheet)
+        copySheet, copysheet = CopySheet, CopySheet
+
+        def CopySheetFromFile(self, filename, sheetname, newname, beforesheet = 32768):
+            sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
+            return self.Execute(self.vbMethod + self.flgObject, 'CopySheetFromFile',
+                                filename, sheet, newname, beforesheet)
+        copySheetFromFile, copysheetfromfile = CopySheetFromFile, CopySheetFromFile
+
+        def CopyToCell(self, sourcerange, destinationcell):
+            range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
+                     else sourcerange)
+            return self.Execute(self.vbMethod + self.flgObject, 'CopyToCell', range, destinationcell)
+        copyToCell, copytocell = CopyToCell, CopyToCell
+
+        def CopyToRange(self, sourcerange, destinationrange):
+            range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
+                     else sourcerange)
+            return self.Execute(self.vbMethod + self.flgObject, 'CopyToRange', range, destinationrange)
+        copyToRange, copytorange = CopyToRange, CopyToRange
+
+        def DAvg(self, range):
+            return self.Execute(self.vbMethod, 'DAvg', range)
+        dAvg, davg = DAvg, DAvg
+
+        def DCount(self, range):
+            return self.Execute(self.vbMethod, 'DCount', range)
+        dCount, dcount = DCount, DCount
+
+        def DMax(self, range):
+            return self.Execute(self.vbMethod, 'DMax', range)
+        dMax, dmax = DMax, DMax
+
+        def DMin(self, range):
+            return self.Execute(self.vbMethod, 'DMin', range)
+        dMin, dmin = DMin, DMin
+
+        def DSum(self, range):
+            return self.Execute(self.vbMethod, 'DSum', range)
+        dSum, dsum = DSum, DSum
+
+        def Forms(self, sheetname, form = ''):
+            return self.Execute(self.vbMethod + self.flgArrayRet, 'Forms', sheetname, form)
+        forms = Forms
+
+        def GetColumnName(self, columnnumber):
+            return self.Execute(self.vbMethod, 'GetColumnName', columnnumber)
+        getColumnName, getcolumnname = GetColumnName, GetColumnName
+
+        def GetFormula(self, range):
+            return self.Execute(self.vbMethod + self.flgArrayRet, 'GetFormula', range)
+        getFormula, getformula = GetFormula, GetFormula
+
+        def GetValue(self, range):
+            return self.Execute(self.vbMethod + self.flgArrayRet, 'GetValue', range)
+        getValue, getvalue = GetValue, GetValue
+
+        def ImportFromCSVFile(self, filename, destinationcell, filteroptions = ScriptForge.cstSymEmpty):
+            return self.Execute(self.vbMethod, 'ImportFromCSVFile', filename, destinationcell, filteroptions)
+        importFromCSVFile, importfromcsvfile = ImportFromCSVFile, ImportFromCSVFile
+
+        def ImportFromDatabase(self, filename = '', registrationname = '', destinationcell = '', sqlcommand = '',
+                               directsql = False):
+            return self.Execute(self.vbMethod, 'ImportFromDatabase', filename, registrationname,
+                                destinationcell, sqlcommand, directsql)
+        importFromDatabase, importfromdatabase = ImportFromDatabase, ImportFromDatabase
+
+        def InsertSheet(self, sheetname, beforesheet = 32768):
+            return self.Execute(self.vbMethod, 'InsertSheet', sheetname, beforesheet)
+        insertSheet, insertsheet = InsertSheet, InsertSheet
+
+        def MoveRange(self, source, destination):
+            return self.Execute(self.vbMethod, 'MoveRange', source, destination)
+        moveRange, moverange = MoveRange, MoveRange
+
+        def MoveSheet(self, sheetname, beforesheet = 32768):
+            return self.Execute(self.vbMethod, 'MoveSheet', sheetname, beforesheet)
+        moveSheet, movesheet = MoveSheet, MoveSheet
+
+        def Offset(self, range, rows = 0, columns = 0, height = ScriptForge.cstSymEmpty,
+                   width = ScriptForge.cstSymEmpty):
+            return self.Execute(self.vbMethod, 'Offset', range, rows, columns, height, width)
+        offset = Offset
+
+        def RemoveSheet(self, sheetname):
+            return self.Execute(self.vbMethod, 'RemoveSheet', sheetname)
+        removeSheet, removesheet = RemoveSheet, RemoveSheet
+
+        def RenameSheet(self, sheetname, newname):
+            return self.Execute(self.vbMethod, 'RenameSheet', sheetname, newname)
+        renameSheet, renamesheet = RenameSheet, RenameSheet
+
+        def SetArray(self, targetcell, value):
+            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetArray', targetcell, value)
+        setArray, setarray = SetArray, SetArray
+
+        def SetCellStyle(self, targetrange, style):
+            return self.Execute(self.vbMethod, 'SetCellStyle', targetrange, style)
+        setCellStyle, setcellstyle = SetCellStyle, SetCellStyle
+
+        def SetFormula(self, targetrange, formula):
+            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetFormula', targetrange, formula)
+        setFormula, setformula = SetFormula, SetFormula
+
+        def SetValue(self, targetrange, value):
+            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetValue', targetrange, value)
+        setValue, setvalue = SetValue, SetValue
+
+        def SortRange(self, range, sortkeys, sortorder = 'ASC', destinationcell = ScriptForge.cstSymEmpty,
+                      containsheader = False, casesensitive = False, sortcolumns = False):
+            return self.Execute(self.vbMethod, 'SortRange', range, sortkeys, sortorder, destinationcell,
+                                containsheader, casesensitive, sortcolumns)
+        sortRange, sortrange = SortRange, SortRange
+
+    # #########################################################################
+    # SF_CalcReference CLASS
+    # #########################################################################
+    class SF_CalcReference(SFServices):
+        """
+            The SF_CalcReference class has as unique role to hold sheet and range references.
+            They are implemented in Basic as Type ... End Type data structures
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDocuments.CalcReference'
+        servicesynonyms = ()
+        serviceproperties = dict()
+        propertysynonyms = SFServices._getAttributeSynonyms(serviceproperties)
+
 
-# ##############################################False#######################################################################
+# ##############################################False##################################################################
 #                           CreateScriptService()                                                                   ###
 # #####################################################################################################################
 def CreateScriptService(service, *args):
diff --git a/wizards/source/sfdocuments/SF_Base.xba b/wizards/source/sfdocuments/SF_Base.xba
index f60886e574c9..e9f9075f4fd7 100644
--- a/wizards/source/sfdocuments/SF_Base.xba
+++ b/wizards/source/sfdocuments/SF_Base.xba
@@ -399,6 +399,8 @@ Public Function Methods() As Variant
 					, "FormDocuments" _
 					, "Forms" _
 					, "GetDatabase" _
+					, "IsLoaded" _
+					, "OpenFormDocument" _
 					, "RunCommand" _
 					, "Save" _
 					, "SaveAs" _
diff --git a/wizards/source/sfdocuments/SF_Calc.xba b/wizards/source/sfdocuments/SF_Calc.xba
index c1e4c1c75549..e4bf084c8b83 100644
--- a/wizards/source/sfdocuments/SF_Calc.xba
+++ b/wizards/source/sfdocuments/SF_Calc.xba
@@ -95,6 +95,7 @@ Private _Component				As Object		'	com.sun.star.lang.XComponent
 
 Type _Address
 	ObjectType					As String		'	Must be "SF_CalcReference"
+	ServiceName					As String		'	Must be "SFDocuments.CalcReference"
 	RawAddress					As String
 	Component					As Object		'	com.sun.star.lang.XComponent
 	SheetName					As String
@@ -115,6 +116,8 @@ Private Const MAXCOLS			= 2^10					'	Max number of columns in a sheet
 Private Const MAXROWS			= 2^20					'	Max number of rows in a sheet
 
 Private Const CALCREFERENCE		= "SF_CalcReference"	'	Object type of _Address
+Private Const SERVICEREFERENCE	= "SFDocuments.CalcReference"
+														'	Service name of _Address (used in Python)
 
 Private Const ISCALCFORM		= 2						'	Form is stored in a Calc document
 
@@ -526,7 +529,7 @@ Public Function CopySheetFromFile(Optional ByVal FileName As Variant _
 '''	Args:
 '''		FileName: Identifies the file to open. It must follow the SF_FileSystem.FileNaming notation
 '''			The file must not be protected with a password
-'''		SheetName: The name of the sheet to copy or its reference
+'''		SheetName: The name of the sheet to copy
 '''		NewName: Must not exist
 '''		BeforeSheet: The name (string) or index (numeric, starting from 1) of the sheet before which to insert
 '''	Returns:
@@ -597,7 +600,7 @@ Public Function CopyToCell(Optional ByVal SourceRange As Variant _
 '''		SourceRange: the source range as a string if it belongs to the same document
 '''			or as a reference if it belongs to another open Calc document
 '''		DestinationCell: the destination of the copied range of cells, as a string
-'''			If given as range, the destination will be reduced to its top-left cell
+'''			If given as a range of cells, the destination will be reduced to its top-left cell
 '''	Returns:
 '''		A string representing the modified range of cells
 '''		The modified area depends only on the size of the source area
@@ -789,7 +792,7 @@ Public Function DCount(Optional ByVal Range As Variant) As Long
 '''	Args:
 '''		Range : the range as a string where to get the values from
 '''	Returns:
-'''		The number of numeric values a Long
+'''		The number of numeric values as a Long
 '''	Examples:
 '''		Val = oDoc.DCount("~.A1:A1000")
 
@@ -859,6 +862,7 @@ Public Function Forms(Optional ByVal SheetName As Variant _
 '''		- the list of the Forms contained in the given sheet
 '''		- a SFDocuments.Form object based on its name or its index
 '''	Args:
+'''		SheetName: the name of the sheet containing the requested form or forms
 '''		Form: a form stored in the document given by its name or its index
 '''			When absent, the list of available forms is returned
 '''			To get the first (unique ?) form stored in the form document, set Form = 0
@@ -1035,8 +1039,10 @@ Try:
 	'	Superclass or subclass property ?
 	If ScriptForge.SF_Array.Contains([_Super].Properties(), PropertyName) Then
 		GetProperty = [_Super].GetProperty(PropertyName)
-	Else
+	ElseIf Len(ObjectName) = 0 Then
 		GetProperty = _PropertyGet(PropertyName)
+	Else
+		GetProperty = _PropertyGet(PropertyName, ObjectName)
 	End If
 
 Finally:
@@ -1177,7 +1183,7 @@ Public Sub ImportFromDatabase(Optional ByVal FileName As Variant _
 '''		RegistrationName: the name of a registered database
 '''			It is ignored if FileName <> ""
 '''		DestinationCell: the destination of the copied range of cells, as a string
-'''			If given as range, the destination will be reduced to its top-left cell
+'''			If given as a range of cells, the destination will be reduced to its top-left cell
 '''		SQLCommand: either a table or query name (without square brackets)
 '''			or a full SQL commands where table and fieldnames are preferably surrounded with square brackets
 '''	Returns:
@@ -1375,6 +1381,7 @@ Public Function MoveRange(Optional ByVal Source As Variant _
 '''	Args:
 '''		Source: the source range of cells as a string
 '''		Destination: the destination of the moved range of cells, as a string
+'''			If given as a range of cells, the destination will be reduced to its top-left cell
 '''	Returns:
 '''		A string representing the modified range of cells
 '''		The modified area depends only on the size of the source area
@@ -1556,7 +1563,7 @@ Public Function Properties() As Variant
 					, "Height" _
 					, "IsBase" _
 					, "IsCalc" _
-					, "IsDraw " _
+					, "IsDraw" _
 					, "IsImpress" _
 					, "IsMath" _
 					, "IsWriter" _
@@ -1958,7 +1965,7 @@ Public Function SortRange(Optional ByVal Range As Variant _
 '''		DestinationCell: the destination of the sorted range of cells, as a string
 '''			If given as range, the destination will be reduced to its top-left cell
 '''			By default, Range is overwritten with its sorted content
-'''		ContainsHeader: when True, the first row/column is not sorted
+'''		ContainsHeader: when True, the first row/column is not sorted. Default = False
 '''		CaseSensitive: only for string comparisons, default = False
 '''		SortColumns: when True, the columns are sorted from left to right
 '''			Default = False: rows are sorted from top to bottom.
@@ -1979,7 +1986,7 @@ Dim vSortFields As Variant			'	Array of com.sun.star.table.TableSortField
 Dim sOrder As String				'	Item in SortOrder
 Dim i As Long
 Const cstThisSub = "SFDocuments.Calc.SortRange"
-Const cstSubArgs = "Range, SortKeys, [TargetRange=""""], [SortOrder=""ASC""], [ContainsHeader=False], [CaseSensitive=False], [SortColumns=False]"
+Const cstSubArgs = "Range, SortKeys, [TargetRange=""""], [SortOrder=""ASC""], [DestinationCell=""""], [ContainsHeader=False], [CaseSensitive=False], [SortColumns=False]"
 
 	If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 	sSort = ""
@@ -2294,6 +2301,7 @@ Private Function _ConvertToDataArray(ByRef pvArray As Variant _
 								) As Variant
 '''	Create a 2-dimensions nested array (compatible with the ranges .DataArray property)
 '''	from a scalar, a 1D array or a 2D array
+'''	Input may be a 1D array of arrays, typically when call issued by a Python script
 '''	Array items are converted to (possibly empty) strings or doubles
 '''	Args:
 '''		pvArray: the input scalar or array. If array, must be 1 or 2D otherwise it is ignored.
@@ -2313,13 +2321,14 @@ Dim vDataArray() As Variant			'	Return value
 Dim vVector() As Variant			'	A temporary 1D array
 Dim vItem As Variant				'	A single input item
 Dim iDims As Integer				'	Number of dimensions of the input argument
-Dim lMin1 As Long					'	Lower bound of input array
-Dim lMax1 As Long					'	Upper bound
-Dim lMin2 As Long					'	Lower bound
-Dim lMax2 As Long					'	Upper bound
+Dim lMin1 As Long					'	Lower bound (1) of input array
+Dim lMax1 As Long					'	Upper bound (1)
+Dim lMin2 As Long					'	Lower bound (2)
+Dim lMax2 As Long					'	Upper bound (2)
 Dim lRows As Long					'	Upper bound of vDataArray
 Dim lCols As Long					'	Upper bound of vVector
 Dim bHorizontal As Boolean			'	Horizontal vector
+Dim bDataArray As Boolean			'	Input array is already an array of arrays
 Dim i As Long
 Dim j As Long
 
@@ -2339,11 +2348,18 @@ Try:
 	Select Case iDims
 		Case -1													'	Scalar value
 		Case 1
-			bHorizontal = ( plRows = 0 And plColumns > 0)
-			If Not bHorizontal Then
-				lMin1 = LBound(pvArray)	:	lMax1 = UBound(pvArray)
+			bHorizontal = ( plRows = 0 And plColumns > 0 )
+			bDataArray = IsArray(pvArray(0))
+			If Not bDataArray Then
+				If Not bHorizontal Then
+					lMin1 = LBound(pvArray)	:	lMax1 = UBound(pvArray)
+				Else
+					lMin2 = LBound(pvArray)	:	lMax2 = UBound(pvArray)
+				End If
 			Else
-				lMin2 = LBound(pvArray)	:	lMax2 = UBound(pvArray)
+				iDims = 2
+				lMin1 = LBound(pvArray)	:	lMax1 = UBound(pvArray)
+				lMin2 = LBound(pvArray(0))	:	lMax2 = UBound(pvArray(0))
 			End If
 		Case 2
 			lMin1 = LBound(pvArray, 1)	:	lMax1 = UBound(pvArray, 1)
@@ -2385,7 +2401,11 @@ Try:
 							vItem = _ConvertToCellValue(pvArray(i + lMin1))
 						End If
 					Case 2
-						vItem = _ConvertToCellValue(pvArray(i + lMin1, j + lMin2))
+						If bDataArray Then
+							vItem = _ConvertToCellValue(pvArray(i + lMin1)(j + lMin2))
+						Else
+							vItem = _ConvertToCellValue(pvArray(i + lMin1, j + lMin2))
+						End If
 				End Select
 				vVector(j) = vItem
 			End If
@@ -2581,6 +2601,7 @@ Try:
 	Set oOffset = New _Address
 	With oOffset
 		.ObjectType = CALCREFERENCE
+		.ServiceName = SERVICEREFERENCE
 		.RawAddress = oNewRange.AbsoluteName
 		.Component = _Component
 		.XSpreadsheet = oNewRange.Spreadsheet
@@ -2631,6 +2652,7 @@ Dim oSelect As Object				'	Current selection
 		.SheetName = ""			:	.RangeName = ""
 
 		.ObjectType = CALCREFERENCE
+		.ServiceName = SERVICEREFERENCE
 		.RawAddress = psAddress
 		Set .XSpreadSheet = Nothing	:	Set .XCellRange = Nothing
 		
diff --git a/wizards/source/sfdocuments/SF_Form.xba b/wizards/source/sfdocuments/SF_Form.xba
index 5e1f011c8a1d..2fc8f6d60038 100644
--- a/wizards/source/sfdocuments/SF_Form.xba
+++ b/wizards/source/sfdocuments/SF_Form.xba
@@ -15,7 +15,7 @@ Option Explicit
 '''	SF_Form
 '''	=======
 '''		Management of forms defined in LibreOffice documents. Supported types are Base, Calc and Writer documents.
-'''		For Base documents, it includes the management of subforms
+'''		It includes the management of subforms
 '''		Each instance of the current class represents a single form or a single subform
 '''
 '''		A form may optionally be (understand "is often") linked to a data source manageable with the SFDatabases.Database service
@@ -916,7 +916,7 @@ REM ----------------------------------------------------------------------------
 Public Function MovePrevious(Optional ByVal Offset As Variant) As Boolean
 '''	The cursor is (re)positioned on the previous row
 '''	Args:
-'''		Offset: The number of records to go forward (default = 1)
+'''		Offset: The number of records to go backward (default = 1)
 '''	Returns:
 '''		True if cursor move is successful
 '''	Example:
@@ -1070,7 +1070,7 @@ Public Function Subforms(Optional ByVal Subform As Variant) As Variant
 '''		An instance of the SF_Form class if Subform exists
 '''	Example:
 '''			Dim myForm As Object, myList As Variant, mySubform As Object
-'''				myList = oForm.Subforms()
+'''				myList = myForm.Subforms()
 '''				Set mySubform = myForm.Subforms("mySubform")
 
 Dim oSubform As Object				'	The new Form class instance
diff --git a/wizards/source/sfdocuments/SF_FormControl.xba b/wizards/source/sfdocuments/SF_FormControl.xba
index 7fbd49bba965..a40b902e3425 100644
--- a/wizards/source/sfdocuments/SF_FormControl.xba
+++ b/wizards/source/sfdocuments/SF_FormControl.xba
@@ -547,7 +547,7 @@ End Property	'	SFDocuments.SF_FormControl.OnUpdated (let)
 
 REM -----------------------------------------------------------------------------
 Property Get Parent() As Object
-'''	Return the Parent dialog object of the actual control
+'''	Return the Parent form or [table]control object of the actual control
 	Parent = _PropertyGet("Parent", Nothing)
 End Property	'	SFDocuments.SF_FormControl.Parent
 
@@ -860,9 +860,9 @@ Public Function SetFocus() As Boolean
 '''		True if focusing is successful
 '''	Example:
 '''		Dim oDoc As Object, oForm As Object, oControl As Object
-'''			Set oDoc = Set oDoc = CreateScriptService("SFDocuments.Document", ThisComponent)
+'''			Set oDoc = CreateScriptService("SFDocuments.Document", ThisComponent)
 '''			Set oForm = oDoc.Forms(0)
-'''			Set oControl = oDlg.Controls("thisControl")
+'''			Set oControl = oForm.Controls("thisControl")
 '''			oControl.SetFocus()
 
 Dim bSetFocus As Boolean		'	Return value
@@ -1846,4 +1846,4 @@ Private Function _Repr() As String
 End Function	'	SFDocuments.SF_FormControl._Repr
 
 REM ============================================ END OF SFDOCUMENTS.SF_FORMCONTROL
-</script:module>
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdocuments/SF_Register.xba b/wizards/source/sfdocuments/SF_Register.xba
index d2b0dafd341f..a8872e4115ed 100644
--- a/wizards/source/sfdocuments/SF_Register.xba
+++ b/wizards/source/sfdocuments/SF_Register.xba
@@ -66,8 +66,8 @@ Public Sub RegisterScriptServices() As Variant
 
 	With GlobalScope.ScriptForge.SF_Services
 		.RegisterService("Document",			"SFDocuments.SF_Register._NewDocument")		'	Reference to the function initializing the service
-		.RegisterService("Calc",				"SFDocuments.SF_Register._NewDocument")		'	Same references, distinction is made inside the function
-		.RegisterService("Base",				"SFDocuments.SF_Register._NewDocument")		'	Same references, distinction is made inside the function
+		.RegisterService("Calc",				"SFDocuments.SF_Register._NewDocument")		'	Same reference, distinction is made inside the function
+		.RegisterService("Base",				"SFDocuments.SF_Register._NewDocument")		'	Same reference, distinction is made inside the function
 		.RegisterEventManager("DocumentEvent",	"SFDocuments.SF_Register._EventManager")	'	Reference to the events manager
 		.RegisterEventManager("FormEvent",		"SFDocuments.SF_Register._FormEventManager")'	Reference to the form and controls events manager
 	End With


More information about the Libreoffice-commits mailing list