Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/wizards/source/scriptforge/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 46 kB image not shown  

SSL SF_PythonHelper.xba   Sprache: unbekannt

 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_PythonHelper" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
REM ===   The ScriptForge library and its associated libraries are part of the LibreOffice project.    ===
REM ===     Full documentation is available on https://help.libreoffice.org/        ===
REM =======================================================================================================================

Option Compatible
Option Explicit

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''' SF_PythonHelper (aka Basic)
''' ===============
'''  Singleton class implementing the "ScriptForge.Basic" service
'''  Implemented as a usual Basic module
'''
'''  The "Basic" service must be called ONLY from a PYTHON script
'''  Service invocations: Next Python code lines are equivalent:
'''   bas = CreateScriptService('ScriptForge.Basic')
'''   bas = CreateScriptService('Basic')
'''
'''  This service proposes a collection of methods to be executed in a Python context
'''  to simulate the exact behaviour of the identical Basic builtin method.
'''  Typical example:
'''   bas.MsgBox('This has to be displayed in a message box')
'''
'''  The service includes also an agnostic "Python Dispatcher" function.
'''  It dispatches Python script requests to execute Basic services to the
'''  appropriate properties and methods via dynamic call techniques
'''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

REM ================================================================== EXCEPTIONS

REM ============================================================ MODULE CONSTANTS

REM ===================================================== CONSTRUCTOR/DESTRUCTOR

REM -----------------------------------------------------------------------------
Public Function Dispose() As Variant
 Set Dispose = Nothing
End Function ' ScriptForge.SF_PythonHelper Explicit destructor

REM ================================================================== PROPERTIES

REM -----------------------------------------------------------------------------
Property Get ObjectType As String
''' Only to enable object representation
 ObjectType = "SF_PythonHelper"
End Property ' ScriptForge.SF_PythonHelper.ObjectType

REM -----------------------------------------------------------------------------
Property Get ServiceName As String
''' Internal use
 ServiceName = "ScriptForge.Basic"
End Property ' ScriptForge.SF_PythonHelper.ServiceName

REM ============================================================== PUBLIC METHODS

REM -----------------------------------------------------------------------------
Public Function PyCDate(ByVal DateArg As Variant) As Variant
''' Convenient function to replicate CDate() in Python scripts
''' Args:
'''  DateArg: a date as a string or as a double
''' Returns:
'''  The converted date as a UNO DateTime structure
'''  If the input argument could not be recognized as a date, return the argument unchanged
''' Example: (Python code)
'''  a = bas.CDate('2021-02-18')

Dim vDate As Variant    ' Return value
Const cstThisSub = "Basic.CDate"
Const cstSubArgs = "datearg"

 On Local Error GoTo Catch
 vDate = Null

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 vDate = CDate(DateArg)

Finally:
 If VarType(vDate) = V_DATE Then PyCDate = CDateToUnoDateTime(vDate) Else PyCDate = DateArg
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 On Local Error GoTo 0
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyCDate

REM -----------------------------------------------------------------------------
Public Function PyConvertFromUrl(ByVal FileName As Variant) As String
''' Convenient function to replicate ConvertFromUrl() in Python scripts
''' Args:
'''  FileName: a string representing a file in URL format
''' Returns:
'''  The same file name in native operating system notation
''' Example: (Python code)
'''  a = bas.ConvertFromUrl('file:////boot.sys')

Dim sFileName As String   ' Return value
Const cstThisSub = "Basic.ConvertFromUrl"
Const cstSubArgs = "filename"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 sFileName = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 sFileName = ConvertFromUrl(FileName)

Finally:
 PyConvertFromUrl = sFileName
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyConvertFromUrl

REM -----------------------------------------------------------------------------
Public Function PyConvertToUrl(ByVal FileName As Variant) As String
''' Convenient function to replicate ConvertToUrl() in Python scripts
''' Args:
'''  FileName: a string representing a file in native operating system notation
''' Returns:
'''  The same file name in URL format
''' Example: (Python code)
'''  a = bas.ConvertToUrl('C:\boot.sys')

Dim sFileName As String   ' Return value
Const cstThisSub = "Basic.ConvertToUrl"
Const cstSubArgs = "filename"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 sFileName = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 sFileName = ConvertToUrl(FileName)

Finally:
 PyConvertToUrl = sFileName
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyConvertToUrl

REM -----------------------------------------------------------------------------
Public Function PyCreateUnoService(ByVal UnoService As Variant) As Variant
''' Convenient function to replicate CreateUnoService() in Python scripts
''' Args:
'''  UnoService: a string representing the service to create
''' Returns:
'''  A UNO object
''' Example: (Python code)
'''  a = bas.CreateUnoService('com.sun.star.i18n.CharacterClassification')

Dim vUno As Variant    ' Return value
Const cstThisSub = "Basic.CreateUnoService"
Const cstSubArgs = "unoservice"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 Set vUno = Nothing

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 Set vUno = CreateUnoService(UnoService)

Finally:
 Set PyCreateUnoService = vUno
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyCreateUnoService

REM -----------------------------------------------------------------------------
Public Function PyDateAdd(ByVal Add As Variant _
       , ByVal Count As Variant _
       , ByVal DateArg As Variant _
       ) As Variant
''' Convenient function to replicate DateAdd() in Python scripts
''' Args:
'''  Add: The unit to add
'''  Count: how many times to add (might be negative)
'''  DateArg: a date as a com.sun.star.util.DateTime UNO structure
''' Returns:
'''  The new date as a string in iso format
''' Example: (Python code)
'''  a = bas.DateAdd('d', 1, bas.Now())  ' Tomorrow

Dim vNewDate As Variant    ' Return value
Dim vDate As Date     ' Alias of DateArg
Const cstThisSub = "Basic.DateAdd"
Const cstSubArgs = "add, count, datearg"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 vNewDate = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 If VarType(DateArg) = V_OBJECT Then
  vDate = CDateFromUnoDateTime(DateArg)
 Else
  vDate = SF_Utils._CStrToDate(DateArg)
 End If
 vNewDate = DateAdd(Add, Count, vDate)

Finally:
 If VarType(vNewDate) = V_DATE Then PyDateAdd = CDateToUnoDateTime(vNewDate) Else PyDateAdd = vNewDate
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyDateAdd

REM -----------------------------------------------------------------------------
Public Function PyDateDiff(ByVal Add As Variant _
       , ByVal Date1 As Variant _
       , ByVal Date2 As Variant _
       , ByVal WeekStart As Variant _
       , ByVal YearStart As Variant _
       ) As Long
''' Convenient function to replicate DateDiff() in Python scripts
''' Args:
'''  Add: The unit of the date interval
'''  Date1, Date2: the two dates to be compared
'''  WeekStart: the starting day of a week
'''  YearStart: the starting week of a year
''' Returns:
'''  The number of intervals expressed in Adds
''' Example: (Python code)
'''  a = bas.DateDiff('d', bas.DateAdd('d', 1, bas.Now()), bas.Now())  ' -1 day

Dim lDiff As Long     ' Return value
Dim vDate1 As Date     ' Alias of Date1
Dim vDate2 As Date     ' Alias of Date2
Const cstThisSub = "Basic.DateDiff"
Const cstSubArgs = "add, date1, date2, [weekstart=1], [yearstart=1]"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 lDiff = 0

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 If VarType(Date1) = V_OBJECT Then
  vDate1 = CDateFromUnoDateTime(Date1)
 Else
  vDate1 = SF_Utils._CStrToDate(Date1)
 End If
 If VarType(Date2) = V_OBJECT Then
  vDate2 = CDateFromUnoDateTime(Date2)
 Else
  vDate2 = SF_Utils._CStrToDate(Date2)
 End If
 lDiff = DateDiff(Add, vDate1, vDate2, WeekStart, YearStart)


Finally:
 PyDateDiff = lDiff
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyDateDiff

REM -----------------------------------------------------------------------------
Public Function PyDatePart(ByVal Add As Variant _
       , ByVal DateArg As Variant _
       , ByVal WeekStart As Variant _
       , ByVal YearStart As Variant _
       ) As Long
''' Convenient function to replicate DatePart() in Python scripts
''' Args:
'''  Add: The unit of the date interval
'''  DateArg: The date from which to extract a part
'''  WeekStart: the starting day of a week
'''  YearStart: the starting week of a year
''' Returns:
'''  The specified part of the date
''' Example: (Python code)
'''  a = bas.DatePart('y', bas.Now())  ' day of year

Dim lPart As Long     ' Return value
Dim vDate As Date     ' Alias of DateArg
Const cstThisSub = "Basic.DatePart"
Const cstSubArgs = "add, datearg, [weekstart=1], [yearstart=1]"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 lPart = 0

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 If VarType(DateArg) = V_OBJECT Then
  vDate = CDateFromUnoDateTime(DateArg)
 Else
  vDate = SF_Utils._CStrToDate(DateArg)
 End If
 lPart = DatePart(Add, vDate, WeekStart, YearStart)


Finally:
 PyDatePart = lPart
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyDatePart

REM -----------------------------------------------------------------------------
Public Function PyDateValue(ByVal DateArg As Variant) As Variant
''' Convenient function to replicate DateValue() in Python scripts
''' Args:
'''  DateArg: a date as a string
''' Returns:
'''  The converted date as a UNO DateTime structure
''' Example: (Python code)
'''  a = bas.DateValue('2021-02-18')

Dim vDate As Variant    ' Return value
Const cstThisSub = "Basic.DateValue"
Const cstSubArgs = "datearg"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 vDate = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 vDate = DateValue(DateArg)

Finally:
 If VarType(vDate) = V_DATE Then PyDateValue = CDateToUnoDateTime(vDate) Else PyDateValue = vDate
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyDateValue

REM -----------------------------------------------------------------------------
Public Function PyFormat(ByVal Value As Variant _
       , ByVal Pattern As Variant _
       ) As String
''' Convenient function to replicate Format() in Python scripts
''' Args:
'''  Value: a date or a number
'''  Pattern: the format to apply
''' Returns:
'''  The formatted value
''' Example: (Python code)
'''     MsgBox bas.Format(6328.2, '##,##0.00')

Dim sFormat As String     ' Return value
Dim vValue As Variant    ' Alias of Value
Const cstThisSub = "Basic.Format"
Const cstSubArgs = "value, pattern"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 sFormat = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 If VarType(Value) = V_OBJECT Then vValue = CDateFromUnoDateTime(Value) ELse vValue = Value
 If IsEmpty(Pattern) Or Len(Pattern) = 0 Then sFormat = Str(vValue) Else sFormat = Format(vValue, Pattern)


Finally:
 PyFormat = sFormat
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyFormat

REM -----------------------------------------------------------------------------
Public Function PyGetGuiType() As Integer
''' Convenient function to replicate GetGuiType() in Python scripts
''' Args:
''' Returns:
'''  The GetGuiType value
''' Example: (Python code)
'''     MsgBox bas.GetGuiType()

Const cstThisSub = "Basic.GetGuiType"
Const cstSubArgs = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 PyGetGuiType = GetGuiType()


Finally:
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
End Function ' ScriptForge.SF_PythonHelper.PyGetGuiType

REM -----------------------------------------------------------------------------
Public Function PyGetSystemTicks() As Long
''' Convenient function to replicate GetSystemTicks() in Python scripts
''' Args:
''' Returns:
'''  The GetSystemTicks value
''' Example: (Python code)
'''     MsgBox bas.GetSystemTicks()

Const cstThisSub = "Basic.GetSystemTicks"
Const cstSubArgs = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 PyGetSystemTicks = GetSystemTicks()


Finally:
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
End Function ' ScriptForge.SF_PythonHelper.PyGetSystemTicks

REM -----------------------------------------------------------------------------
Public Function PyGlobalScope(ByVal Library As Variant) As Object
''' Convenient function to replicate GlobalScope() in Python scripts
''' Args:
'''  Library: "Basic" or "Dialog"
''' Returns:
'''  The GlobalScope value
''' Example: (Python code)
'''     bas.Xray(bas.GlobalScope.BasicLibraries())

Const cstThisSub = "Basic.GlobalScope.BasicLibraries" ' or DialogLibraries
Const cstSubArgs = ""

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 Select Case Library
  Case "Basic"
   PyGlobalScope = GlobalScope.BasicLibraries()
  Case "Dialog"
   PyGlobalScope = GlobalScope.DialogLibraries()
  Case Else
 End Select

Finally:
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
End Function ' ScriptForge.SF_PythonHelper.PyGlobalScope

REM -----------------------------------------------------------------------------
Public Function PyInputBox(ByVal Msg As Variant _
        , ByVal Title As Variant _
        , ByVal Default As Variant _
        , Optional ByVal XPosTwips As Variant _
        , Optional ByVal YPosTwips As Variant _
        ) As String
''' Convenient function to replicate InputBox() in Python scripts
''' Args:
'''  Msg: String expression displayed as the message in the dialog box
'''  Title: String expression displayed in the title bar of the dialog box
'''  Default: String expression displayed in the text box as default if no other input is given
'''  XPosTwips: Integer expression that specifies the horizontal position of the dialog
'''  YPosTwips: Integer expression that specifies the vertical position of the dialog
'''   If XPosTwips and YPosTwips are omitted, the dialog is centered on the screen
'''   The position is specified in twips.
''' Returns:
'''  The entered value or "" if the user pressed the Cancel button
''' Example: (Python code)
'''     a = bas.InputBox ('Please enter a phrase:', 'Dear User')

Dim sInput As String  ' Return value
Const cstThisSub = "Basic.InputBox"
Const cstSubArgs = "msg, [title=''], [default=''], [xpostwips], [ypostwips]"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 sInput = ""

Check:
 If IsMissing(YPosTwips) Then YPosTwips = 1
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 If IsMissing(XPosTwips) Then
  sInput = InputBox(Msg, Title, Default)
 Else
  sInput = InputBox(Msg, Title, Default, XPosTwips, YPosTwips)
 End If

Finally:
 PyInputBox = sInput
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyInputBox

REM -----------------------------------------------------------------------------
Public Function PyMsgBox(ByVal Text As Variant _
        , ByVal DialogType As Variant _
        , ByVal DialogTitle As Variant _
        ) As Integer
''' Convenient function to replicate MsgBox() in Python scripts
''' Args:
'''  Text: String expression displayed as a message in the dialog box
'''  DialogType: Any integer expression that defines the number and type of buttons or icons displayed
'''  DialogTitle: String expression displayed in the title bar of the dialog
''' Returns:
'''  The pressed button
''' Example: (Python code)
'''     a = bas.MsgBox ('Please press a button:', bas.MB_EXCLAMATION, 'Dear User')

Dim iMsg As Integer  ' Return value
Const cstThisSub = "Basic.MsgBox"
Const cstSubArgs = "text, [dialogtype=0], [dialogtitle]"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 iMsg = -1

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 iMsg = MsgBox(Text, DialogType, DialogTitle)

Finally:
 PyMsgBox = iMsg
 SF_Utils._ExitFunction(cstThisSub)
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper.PyMsgBox

REM -----------------------------------------------------------------------------
Public Sub PyWait(ByVal Millisec As Variant)
''' Convenient function to replicate Wait() in Python scripts
''' This method is normally not necessary. But constructions like:
'''  import time
'''  while True:
'''   time.sleep(1)
''' have the drawback to often freeze the LibreOffice user interface.
'''  basic = CreateScriptService('Basic')
'''  white True:
'''   basic.Wait(1000)
''' might be a good alternative, although less precise due to the Python/Basic exchanges.
''' Args:
'''  Millisec: the amount of time (in milliseconds) to wait before the program is continued

Const cstThisSub = "Basic.Wait"
Const cstSubArgs = "millisec"

 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch

Check:
 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)

Try:
 Wait Millisec

Finally:
 SF_Utils._ExitFunction(cstThisSub)
 Exit Sub
Catch:
 GoTo Finally
End Sub ' ScriptForge.SF_PythonHelper.PyWait

REM ============================================================= PRIVATE METHODS

REM -----------------------------------------------------------------------------
Public Function _PythonDispatcher(ByRef BasicObject As Variant _
         , ByVal CallType As Variant _
         , ByVal Script As Variant _
         , ParamArray Args() As Variant _
        ) As Variant
''' Called from Python only
''' The method calls the method Script associated with the BasicObject class or module
''' with the given arguments
''' The invocation of the method can be a Property Get, Property Let or a usual call
''' NB: arguments and return values must not be 2D arrays
''' The implementation intends to be as AGNOSTIC as possible in terms of objects nature and methods called
''' The method returns the value effectively returned by the called component,
''' completed with additional metadata. The whole is packaged in a 1D array.
''' Args:
'''  BasicObject: a module or a class instance - May also be the reserved string: "SF_Services"
'''  CallType: one of the constants applicable to a CallByName statement + optional protocol flags
'''  Script: the name of the method or property
'''  Args: the arguments to pass to the method. Input arguments can contain symbolic constants for Null, Missing, etc.
''' Returns:
'''  A 1D array:
'''   [0]  The returned value - scalar, object or 1D array
'''   [1]  The VarType() of the returned value
'''      Null, Empty and Nothing have different vartypes but return all None to Python
'''   Additionally, when array:
'''   [2]  Number of dimensions in Basic
'''   Additionally, when Basic object:
'''   [2]  Module (1), Class instance (2) or UNO (3)
'''   [3]  The object's ObjectType
'''   [4]  The object's service name
'''   [5]  The object's name
'''  When an error occurs Python receives None as a scalar. This determines the occurrence of a failure

Dim vReturn As Variant    ' The value returned by the invoked property or method
Dim vReturnArray As Variant   ' Return value
Dim vBasicObject As Variant   ' Alias of BasicObject to avoid "Object reference not set" error
Dim iNbArgs As Integer    ' Number of valid input arguments
Dim vArg As Variant     ' Alias for a single argument
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
Dim bDict As Boolean    ' Return value is a Basic SF_Dictionary class instance
Dim oDict As Object     ' SF_Dictionary class instance
Dim oObjDesc As Object    ' _ObjectDescriptor type
Dim iDims As Integer    ' # of dims of vReturn when array
Dim sess As Object     : Set sess = ScriptForge.SF_Session
Dim i As Long, j As Long

' Conventional special input or output values
Const cstNoArgs = "+++NOARGS+++", cstSymEmpty = "+++EMPTY+++", cstSymNull = "+++NULL+++", cstSymMissing = "+++MISSING+++"

https://support.office.com/en-us/article/CallByName-fonction-49ce9475-c315-4f13-8d35-e98cfe98729a
' Determines the CallType
Const vbGet = 2, vbLet = 4, vbMethod = 1, vbSet = 8
' Protocol flags
Const cstPost = 16   ' Requires a hardcoded post-processing
Const cstDictArg = 32  ' May contain a Dictionary argument
Const cstDateArg = 64  ' May contain a date argument
Const cstDateRet = 128  ' Return value can be a date
Const cstUno = 256   ' Return value can be a UNO object
Const cstArgArray = 512  ' Any argument can be a 2D array
Const cstRetArray = 1024 ' Return value can be an array
Const cstObject = 2048  ' 1st argument is a Basic object when numeric
Const cstHardCode = 4096 ' Method must not be executed with CallByName()
' Returned object nature
Const objMODULE = 1, objCLASS = 2, objDICT = 3, objUNO = 4

Check:
 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
 _PythonDispatcher = Null

 ' Ignore Null basic objects (Null = Null or Nothing)
 If IsNull(BasicObject) Or IsEmpty(BasicObject) Then GoTo Catch

 ' Reinterpret arguments one by one into vArgs
 ' - convert UNO dates/times
 ' - identify conventional NoArgs/Empty/Null/Missing constants
 ' - convert arrays of property values into Dictionary
 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
   ' 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, or a dictionary ?
   ElseIf VarType(vArg) = V_STRING Then
    If Len(vArg) = 0 Then
    ElseIf vArg = cstSymEmpty Then
     vArg = Empty
    ElseIf vArg = cstSymNull Then
     vArg = Null
    ElseIf vArg = cstSymMissing Then
     Exit For ' Next arguments must be missing also
    End If
   ElseIf  VarType(vArg) = V_OBJECT Then
    If ( CallType And cstDateArg ) = cstDateArg Then vArg = CDateFromUnoDateTime(vArg)
   ElseIf ( CallType And cstDictArg ) = cstDictArg Then
    If IsArray(vArg) Then
     If UBound(vArg) >= 0 Then
      If sess.UnoObjectType(vArg(0)) = "com.sun.star.beans.PropertyValue" Then
       ' Create a dictionary - keys in Python dicts are case-sensitive
       Set oDict = CreateScriptService("ScriptForge.Dictionary", True)
       oDict.ImportFromPropertyValues(vArg, Overwrite := True)
       vArg = oDict
      End If
     End If
    End If
   End If
   iNbArgs = iNbArgs + 1

   ReDim Preserve vArgs(iNbArgs)
   vArgs(iNbArgs) = vArg
  Next i
 End If

Try:
 ' Dispatching strategy: based on next constraints
 '   (1) Bug https://bugs.documentfoundation.org/show_bug.cgi?id=138155
 '    The CallByName function fails when returning an array
 '   (2) Python has tuples and tuple of tuples, not 2D arrays
 '   (3) Passing 2D arrays through a script provider always transform it into a sequence of sequences
 '   (4) The CallByName function takes exclusive control on the targeted object up to its exit
 '   (5) A script provider returns a Basic Date variable as Empty
 ' RULES:
 ' 1. All methods in any module are invoked with CallByName
 ' 2. Properties in any service are got and set with obj.GetProperty/SetProperty(...)
 ' EXCEPTIONS:
 ' 3. Methods in usual modules are called by ExecuteBasicScript() when they manipulate arrays
 ' 4. Methods in class modules using a 2D array or returning arrays, or methods using ParamArray,
'''   are hardcoded as exceptions or are not implemented
 ' 5. Due to constraint (4), a predefined list of method calls must be hardcoded to avoid blocking use of CallByName
 '  The concerned methods are flagged with cstHardCode

 With _SF_
  ' Initialize Python persistent storage at 1st call
  If IsEmpty(.PythonStorage) Then ._InitPythonStorage()
  ' Reset any error
  ._Stackreset()
  ' Set Python trigger to manage signatures in error messages
  .TriggeredByPython = True
 End With

 Select case VarType(BasicObject)
  Case V_STRING
   ' Special entry for CreateScriptService()
   vBasicObject = BasicObject
   If vBasicObject = "SF_Services" Then
    If UBound(vArgs) = 0 Then vParams = Array() Else vParams = SF_Array.Slice(vArgs, 1)
    Select Case UBound(vParams)
     Case -1 : vReturn = SF_Services.CreateScriptService(vArgs(0))
     Case 0 : vReturn = SF_Services.CreateScriptService(vArgs(0), vParams(0))
     Case 1 : vReturn = SF_Services.CreateScriptService(vArgs(0), vParams(0), vParams(1))
     Case 2 : vReturn = SF_Services.CreateScriptService(vArgs(0), vParams(0), vParams(1), vParams(2))
     Case 3 : vReturn = SF_Services.CreateScriptService(vArgs(0), vParams(0), vParams(1), vParams(2), vParams(3))
     Case 4 : vReturn = SF_Services.CreateScriptService(vArgs(0), vParams(0), vParams(1), vParams(2), vParams(3), vParams(4))
    End Select
   End If
   If VarType(vReturn) = V_OBJECT And Not IsNull(vReturn) Then
    vBasicObject = vReturn
    sObjectType = vBasicObject.ObjectType
    bBasicClass = ( Left(sObjectType, 3) <> "SF_" )
   End If

  ' Implement dispatching strategy
  Case V_INTEGER
   If BasicObject < 0 Or Not IsArray(_SF_.PythonStorage) Then GoTo Catch
   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(sServiceName, ".")(0)

   ' Methods in standard modules are called by ExecuteBasicScript() when arrays are returned
   If Not bBasicClass And (CallType And vbMethod) = vbMethod And (CallType And cstRetArray) = cstRetArray Then
    sScript = sLibrary & "." & sObjectType & "." & Script
    ' Force validation in targeted function, not in ExecuteBasicScript()
    _SF_.StackLevel = -1
    Select Case UBound(vArgs)
     Case -1 : vReturn = sess.ExecuteBasicScript(, sScript)
     Case 0 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0))
     Case 1 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1))
     Case 2 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2))
     Case 3 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2), vArgs(3))
     Case 4 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4))
     Case 5 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5))
     Case 6 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6))
     Case 7 : vReturn = sess.ExecuteBasicScript(, sScript, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7))
    End Select
    _SF_.StackLevel = 0

   ' Properties in any service are got and set with obj.GetProperty/SetProperty(...)
   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 = vBasicObject.SetProperty(Script, vArgs(0))

   ' Methods in class modules using a 2D array or returning arrays are hardcoded as exceptions. Bug #138155
   ElseIf ((CallType And vbMethod) + (CallType And cstArgArray)) = vbMethod + cstArgArray Or _
       ((CallType And vbMethod) + (CallType And cstRetArray)) = vbMethod + cstRetArray Then
    If Script = "Methods" Then
     vReturn = vBasicObject.Methods()
    ElseIf Script = "Properties" Then
     vReturn = vBasicObject.Properties()
    Else
     Select Case sServiceName
      Case "SFDatabases.Database"
       If Script = "GetRows" Then  vReturn = vBasicObject.GetRows(vArgs(0), vArgs(1), vArgs(2), vArgs(3))
      Case "SFDatabases.Dataset"
       If Script = "GetRows" Then  vReturn = vBasicObject.GetRows(vArgs(0), vArgs(1))
      Case "SFDialogs.Dialog"
       If Script = "Controls" Then  vReturn = vBasicObject.Controls(vArgs(0))
      Case "SFDialogs.DialogControl"
       If Script = "SetTableData" Then vReturn = vBasicObject.SetTableData(vArgs(0), vArgs(1), vArgs(2))
      Case "SFDocuments.Document"
       Select Case Script
        Case "ContextMenus"  : vReturn = vBasicObject.ContextMenus(vArgs(0), vArgs(1))
        Case "Forms"   : vReturn = vBasicObject.Forms(vArgs(0))
        Case "Styles"   : vReturn = vBasicObject.Styles(vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5))
        Case "Toolbars"   : vReturn = vBasicObject.Toolbars(vArgs(0))
       End Select
      Case "SFDocuments.Base"
       Select Case Script
        Case "ContextMenus"  : vReturn = vBasicObject.ContextMenus(vArgs(0), vArgs(1))
        Case "FormDocuments" : vReturn = vBasicObject.FormDocuments()
        Case "Forms"   : vReturn = vBasicObject.Forms(vArgs(0), vArgs(1))
        Case "Toolbars"   : vReturn = vBasicObject.Toolbars(vArgs(0))
       End Select
      Case "SFDocuments.Calc"
       Select Case Script
        Case "Charts"   : vReturn = vBasicObject.Charts(vArgs(0), vArgs(1))
        Case "ContextMenus"  : vReturn = vBasicObject.ContextMenus(vArgs(0), vArgs(1))
        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))
        Case "Styles"   : vReturn = vBasicObject.Styles(vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5))
        Case "Toolbars"   : vReturn = vBasicObject.Toolbars(vArgs(0))
       End Select
      Case "SFDocuments.Form"
       Select Case Script
        Case "Controls"   : vReturn = vBasicObject.Controls(vArgs(0))
        Case "Subforms"   : vReturn = vBasicObject.Subforms(vArgs(0))
       End Select
      Case "SFDocuments.FormControl"
       If Script = "Controls" Then  vReturn = vBasicObject.Controls(vArgs(0))
      Case "SFDocuments.FormDocument"
       Select Case Script
        Case "ContextMenus"  : vReturn = vBasicObject.ContextMenus(vArgs(0), vArgs(1))
        Case "Forms"   : vReturn = vBasicObject.Forms(vArgs(0))
        Case "Toolbars"   : vReturn = vBasicObject.Toolbars(vArgs(0))
       End Select
      Case "SFDocuments.Writer"
       Select Case Script
        Case "ContextMenus"  : vReturn = vBasicObject.ContextMenus(vArgs(0), vArgs(1))
        Case "Forms"   : vReturn = vBasicObject.Forms(vArgs(0))
        Case "Styles"   : vReturn = vBasicObject.Styles(vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5))
        Case "Toolbars"   : vReturn = vBasicObject.Toolbars(vArgs(0))
       End Select
      Case "SFWidgets.Toolbar"
       Select Case Script
        Case "ToolbarButtons" : vReturn = vBasicObject.ToolbarButtons(vArgs(0))
       End Select
     End Select
    End If

   ' Specific methods in class modules may better not be executed with CallByName() because they do not return immediately
   ElseIf bBasicClass And ((CallType And vbMethod) + (CallType And cstHardCode)) = vbMethod + cstHardCode Then
    Select Case sServiceName
     Case "SFDialogs.Dialog"
      Select Case Script
       Case "Execute"   : vReturn = vBasicObject.Execute(vArgs(0))
      End Select
    End Select

   ' Methods in all modules are invoked with CallByName
   ElseIf ((CallType And vbMethod) = vbMethod) Then
    Select Case UBound(vArgs)
     ' Dirty alternatives to process usual and ParamArray cases
     ' But, up to ... how many ?
     '  - The OFFSETADDRESSERROR has 12 arguments
     '  - The ".uno:DataSort" command may have 14 property name-value pairs
     Case -1 : vReturn = CallByName(vBasicObject, Script, vbMethod)
     Case 0 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0))
     Case 1 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1))
     Case 2 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2))
     Case 3 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3))
     Case 4 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4))
     Case 5 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5))
     Case 6 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6))
     Case 7 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7))
     Case 8 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8))
     Case 9 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9))
     Case 10 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10))
     Case 11 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11))
     Case 12, 13 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12))
     Case 14, 15 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14))
     Case 16, 17 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16))
     Case 18, 19 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18))
     Case 20, 21 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18) _
           , vArgs(19), vArgs(20))
     Case 22, 23 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18) _
           , vArgs(19), vArgs(20), vArgs(21), vArgs(22))
     Case 24, 25 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18) _
           , vArgs(19), vArgs(20), vArgs(21), vArgs(22), vArgs(23), vArgs(24))
     Case 26, 27 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18) _
           , vArgs(19), vArgs(20), vArgs(21), vArgs(22), vArgs(23), vArgs(24), vArgs(25), vArgs(26))
     Case >= 28 : vReturn = CallByName(vBasicObject, Script, vbMethod, vArgs(0), vArgs(1), vArgs(2), vArgs(3), vArgs(4), vArgs(5), vArgs(6), vArgs(7) _
           , vArgs(8), vArgs(9), vArgs(10), vArgs(11), vArgs(12), vArgs(13), vArgs(14), vArgs(15), vArgs(16), vArgs(17), vArgs(18) _
           , vArgs(19), vArgs(20), vArgs(21), vArgs(22), vArgs(23), vArgs(24), vArgs(25), vArgs(26), vArgs(27), vArgs(28))
    End Select
   End If

   ' Post processing
   If (CallType And cstPost) = cstPost Then
    If Script = "Dispose" Then
     ' Special case: Dispose() must update the cache for class objects created in Python scripts
     Set _SF_.PythonStorage(BasicObject) = Nothing
    End If
   End If
  Case Else
 End Select
 
 ' Format the returned array
 vReturnArray = Array()
 ' Distinguish: Basic object
 '     UNO object
 '     Dictionary
 '     Array
 '     Scalar
 If IsArray(vReturn) Then
  ReDim vReturnArray(0 To 2)
  iDims = SF_Array.CountDims(vReturn)
  ' Replace dates by UNO format
  If iDims = 1 Then
   For i = LBound(vReturn) To UBound(vReturn)
    If VarType(vReturn(i)) = V_DATE Then vReturn(i) = CDateToUnoDateTime(vReturn(i))
   Next i
  ElseIf iDims = 2 Then
   For i = LBound(vReturn, 1) To UBound(vReturn, 1)
    For j = LBound(vReturn, 2) To UBound(vReturn, 2)
     If VarType(vReturn(i, j)) = V_DATE Then vReturn(i, j) = CDateToUnoDateTime(vReturn(i, j))
    Next j
   Next i
  End If
  vReturnArray(0) = vReturn  ' 2D arrays are flattened by the script provider when returning to Python
  vReturnArray(1) = VarType(vReturn)
  vReturnArray(2) = iDims
 ElseIf VarType(vReturn) = V_OBJECT And Not IsNull(vReturn) Then
  ' Uno or not Uno ?
  bUno = False
  If (CallType And cstUno) = cstUno Then  ' UNO considered only when pre-announced in CallType
   Set oObjDesc = SF_Utils._VarTypeObj(vReturn)
   bUno = ( oObjDesc.iVarType = V_UNOOBJECT )
  End If
  If bUno Then
   ReDim vReturnArray(0 To 2)
   Set vReturnArray(0) = vReturn
  Else
   ReDim vReturnArray(0 To 5)
   bDict = ( vReturn.ObjectType = "DICTIONARY" )
   If bDict Then
    vReturnArray(0) = vReturn.ConvertToPropertyValues()
   Else
    vReturnArray(0) = _SF_._AddToPythonSTorage(vReturn)
   End If
  End If
  vReturnArray(1) = V_OBJECT
  Select Case True
   Case bUno   : vReturnArray(2) = objUNO
   Case bDict   : vReturnArray(2) = objDICT
   Case bBasicClass : vReturnArray(2) = objCLASS
   Case Else   : vReturnArray(2) = objMODULE
  End Select
  If Not bUno Then
   vReturnArray(3) = vReturn.ObjectType
   vReturnArray(4) = vReturn.ServiceName
   vReturnArray(5) = ""
   If vReturn.ObjectType <> "SF_CalcReference" And Not bDict 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)
  If VarType(vReturn) = V_DATE Then vReturnArray(0) = CDateToUnoDateTime(vReturn) Else vReturnArray(0) = vReturn
  vReturnArray(1) = VarType(vReturn)
 End If

 ' Tests with non-modal dialogs and sleeping (time.sleep) Python processes show
 ' a more fluid reactivity when next statement is present, at a minimal cost.
 Wait 0

 _PythonDispatcher = vReturnArray
  
Finally:
 _SF_.TriggeredByPython = False  ' Reset normal state
 Exit Function
Catch:
 GoTo Finally
End Function ' ScriptForge.SF_PythonHelper._PythonDispatcher

REM -----------------------------------------------------------------------------
Private Function _Repr() As String
''' Convert the Basic instance to a readable string, typically for debugging purposes (DebugPrint ...)
''' Args:
''' Return:
'''  "[PythonHelper]"

 _Repr = "[PythonHelper]"

End Function ' ScriptForge.SF_PythonHelper._Repr

REM ================================================= END OF SCRIPTFORGE.SF_PythonHelper
</script:module>

[ Verzeichnis aufwärts0.57unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]