summaryrefslogtreecommitdiffstats
path: root/wizards/source/scriptforge/SF_Exception.xba
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wizards/source/scriptforge/SF_Exception.xba1381
1 files changed, 1381 insertions, 0 deletions
diff --git a/wizards/source/scriptforge/SF_Exception.xba b/wizards/source/scriptforge/SF_Exception.xba
new file mode 100644
index 000000000..11e97b02b
--- /dev/null
+++ b/wizards/source/scriptforge/SF_Exception.xba
@@ -0,0 +1,1381 @@
+<?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_Exception" 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
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos; Exception (aka SF_Exception)
+&apos;&apos;&apos; =========
+&apos;&apos;&apos; Generic singleton class for Basic code debugging and error handling
+&apos;&apos;&apos;
+&apos;&apos;&apos; Errors may be generated by
+&apos;&apos;&apos; the Basic run-time error detection
+&apos;&apos;&apos; in the ScriptForge code =&gt; RaiseAbort()
+&apos;&apos;&apos; in a user code =&gt; Raise()
+&apos;&apos;&apos; an error detection implemented
+&apos;&apos;&apos; in the ScriptForge code =&gt; RaiseFatal()
+&apos;&apos;&apos; in a user code =&gt; Raise() or RaiseWarning()
+&apos;&apos;&apos;
+&apos;&apos;&apos; When a run-time error occurs, the properties of the Exception object are filled
+&apos;&apos;&apos; with information that uniquely identifies the error and information that can be used to handle it
+&apos;&apos;&apos; The SF_Exception object is in this context similar to the VBA Err object
+&apos;&apos;&apos; See https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/err-object
+&apos;&apos;&apos; The Number property identifies the error: it can be a numeric value or a string
+&apos;&apos;&apos; Numeric values up to 2000 are considered Basic run-time errors
+&apos;&apos;&apos;
+&apos;&apos;&apos; The &quot;console&quot; logs events, actual variable values, errors, ... It is an easy mean
+&apos;&apos;&apos; to debug Basic programs especially when the IDE is not usable, f.i. in Calc user defined functions
+&apos;&apos;&apos; or during control events processing
+&apos;&apos;&apos; =&gt; DebugPrint()
+&apos;&apos;&apos;
+&apos;&apos;&apos; The usual behaviour of the application when an error occurs is:
+&apos;&apos;&apos; 1. Log the error in the console
+&apos;&apos;&apos; 2, Inform the user about the error with either a standard or a customized message
+&apos;&apos;&apos; 3. Optionally, stop the execution of the current macro
+&apos;&apos;&apos;
+&apos;&apos;&apos; Detailed user documentation:
+&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_exception.html?DbPAR=BASIC
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================== EXCEPTIONS
+
+&apos; SF_Utils
+Const MISSINGARGERROR = &quot;MISSINGARGERROR&quot;
+Const ARGUMENTERROR = &quot;ARGUMENTERROR&quot;
+Const ARRAYERROR = &quot;ARRAYERROR&quot;
+Const FILEERROR = &quot;FILEERROR&quot;
+
+&apos; SF_Array
+Const ARRAYSEQUENCEERROR = &quot;ARRAYSEQUENCEERROR&quot;
+Const ARRAYINSERTERROR = &quot;ARRAYINSERTERROR&quot;
+Const ARRAYINDEX1ERROR = &quot;ARRAYINDEX1ERROR&quot;
+Const ARRAYINDEX2ERROR = &quot;ARRAYINDEX2ERROR&quot;
+Const CSVPARSINGERROR = &quot;CSVPARSINGERROR&quot;
+Const CSVOVERFLOWWARNING = &quot;CSVOVERFLOWWARNING&quot;
+
+&apos; SF_Dictionary
+Const DUPLICATEKEYERROR = &quot;DUPLICATEKEYERROR&quot;
+Const UNKNOWNKEYERROR = &quot;UNKNOWNKEYERROR&quot;
+Const INVALIDKEYERROR = &quot;INVALIDKEYERROR&quot;
+
+&apos; SF_FileSystem
+Const UNKNOWNFILEERROR = &quot;UNKNOWNFILEERROR&quot;
+Const UNKNOWNFOLDERERROR = &quot;UNKNOWNFOLDERERROR&quot;
+Const NOTAFILEERROR = &quot;NOTAFILEERROR&quot;
+Const NOTAFOLDERERROR = &quot;NOTAFOLDERERROR&quot;
+Const OVERWRITEERROR = &quot;OVERWRITEERROR&quot;
+Const READONLYERROR = &quot;READONLYERROR&quot;
+Const NOFILEMATCHERROR = &quot;NOFILEMATCHFOUND&quot;
+Const FOLDERCREATIONERROR = &quot;FOLDERCREATIONERROR&quot;
+
+&apos; SF_Services
+Const UNKNOWNSERVICEERROR = &quot;UNKNOWNSERVICEERROR&quot;
+Const SERVICESNOTLOADEDERROR = &quot;SERVICESNOTLOADEDERROR&quot;
+
+&apos; SF_Session
+Const CALCFUNCERROR = &quot;CALCFUNCERROR&quot;
+Const NOSCRIPTERROR = &quot;NOSCRIPTERROR&quot;
+Const SCRIPTEXECERROR = &quot;SCRIPTEXECERROR&quot;
+Const WRONGEMAILERROR = &quot;WRONGEMAILERROR&quot;
+Const SENDMAILERROR = &quot;SENDMAILERROR&quot;
+
+&apos; SF_TextStream
+Const FILENOTOPENERROR = &quot;FILENOTOPENERROR&quot;
+Const FILEOPENMODEERROR = &quot;FILEOPENMODEERROR&quot;
+Const ENDOFFILEERROR = &quot;ENDOFFILEERROR&quot;
+
+&apos; SF_UI
+Const DOCUMENTERROR = &quot;DOCUMENTERROR&quot;
+Const DOCUMENTCREATIONERROR = &quot;DOCUMENTCREATIONERROR&quot;
+Const DOCUMENTOPENERROR = &quot;DOCUMENTOPENERROR&quot;
+Const BASEDOCUMENTOPENERROR = &quot;BASEDOCUMENTOPENERROR&quot;
+
+&apos; SF_Document
+Const DOCUMENTDEADERROR = &quot;DOCUMENTDEADERROR&quot;
+Const DOCUMENTSAVEERROR = &quot;DOCUMENTSAVEERROR&quot;
+Const DOCUMENTSAVEASERROR = &quot;DOCUMENTSAVEASERROR&quot;
+Const DOCUMENTREADONLYERROR = &quot;DOCUMENTREADONLYERROR&quot;
+Const DBCONNECTERROR = &quot;DBCONNECTERROR&quot;
+
+&apos; SF_Calc
+Const CALCADDRESSERROR = &quot;CALCADDRESSERROR&quot;
+Const DUPLICATESHEETERROR = &quot;DUPLICATESHEETERROR&quot;
+Const OFFSETADDRESSERROR = &quot;OFFSETADDRESSERROR&quot;
+Const DUPLICATECHARTERROR = &quot;DUPLICATECHARTERROR&quot;
+Const RANGEEXPORTERROR = &quot;RANGEEXPORTERROR&quot;
+
+&apos; SF_Chart
+Const CHARTEXPORTERROR = &quot;CHARTEXPORTERROR&quot;
+
+&apos; SF_Form
+Const FORMDEADERROR = &quot;FORMDEADERROR&quot;
+Const CALCFORMNOTFOUNDERROR = &quot;CALCFORMNOTFOUNDERROR&quot;
+Const WRITERFORMNOTFOUNDERROR = &quot;WRITERFORMNOTFOUNDERROR&quot;
+Const BASEFORMNOTFOUNDERROR = &quot;BASEFORMNOTFOUNDERROR&quot;
+Const SUBFORMNOTFOUNDERROR = &quot;SUBFORMNOTFOUNDERROR&quot;
+Const FORMCONTROLTYPEERROR = &quot;FORMCONTROLTYPEERROR&quot;
+
+&apos; SF_Dialog
+Const DIALOGNOTFOUNDERROR = &quot;DIALOGNOTFOUNDERROR&quot;
+Const DIALOGDEADERROR = &quot;DIALOGDEADERROR&quot;
+Const CONTROLTYPEERROR = &quot;CONTROLTYPEERROR&quot;
+Const TEXTFIELDERROR = &quot;TEXTFIELDERROR&quot;
+
+&apos; SF_Database
+Const DBREADONLYERROR = &quot;DBREADONLYERROR&quot;
+Const SQLSYNTAXERROR = &quot;SQLSYNTAXERROR&quot;
+
+&apos; Python
+Const PYTHONSHELLERROR = &quot;PYTHONSHELLERROR&quot;
+
+&apos; SF_UnitTest
+Const UNITTESTLIBRARYERROR = &quot;UNITTESTLIBRARYERROR&quot;
+Const UNITTESTMETHODERROR = &quot;UNITTESTMETHODERROR&quot;
+
+REM ============================================================= PRIVATE MEMBERS
+
+&apos; User defined errors
+Private _Number As Variant &apos; Error number/code (Integer or String)
+Private _Source As Variant &apos; Where the error occurred: a module, a Sub/Function, ...
+Private _Description As String &apos; The error message
+
+&apos; System run-time errors
+Private _SysNumber As Long &apos; Alias of Err
+Private _SysSource As Long &apos; Alias of Erl
+Private _SysDescription As String &apos; Alias of Error$
+
+REM ============================================================ MODULE CONSTANTS
+
+Const RUNTIMEERRORS = 2000 &apos; Upper limit of Basic run-time errors
+Const CONSOLENAME = &quot;ConsoleLines&quot; &apos; Name of control in the console dialog
+
+REM ===================================================== CONSTRUCTOR/DESTRUCTOR
+
+REM -----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+ Set Dispose = Nothing
+End Function &apos; ScriptForge.SF_Exception Explicit destructor
+
+REM ================================================================== PROPERTIES
+
+REM -----------------------------------------------------------------------------
+Property Get Description() As Variant
+&apos;&apos;&apos; Returns the description of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Description
+ Description = _PropertyGet(&quot;Description&quot;)
+End Property &apos; ScriptForge.SF_Exception.Description (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Description(ByVal pvDescription As Variant)
+&apos;&apos;&apos; Set the description of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Description = &quot;Not smart to divide by zero&quot;
+ _PropertySet &quot;Description&quot;, pvDescription
+End Property &apos; ScriptForge.SF_Exception.Description (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Number() As Variant
+&apos;&apos;&apos; Returns the code of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Number
+ Number = _PropertyGet(&quot;Number&quot;)
+End Property &apos; ScriptForge.SF_Exception.Number (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Number(ByVal pvNumber As Variant)
+&apos;&apos;&apos; Set the code of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Number = 11 &apos; Division by 0
+ _PropertySet &quot;Number&quot;, pvNumber
+End Property &apos; ScriptForge.SF_Exception.Number (let)
+
+REM -----------------------------------------------------------------------------
+Property Get Source() As Variant
+&apos;&apos;&apos; Returns the location of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Source
+ Source = _PropertyGet(&quot;Source&quot;)
+End Property &apos; ScriptForge.SF_Exception.Source (get)
+
+REM -----------------------------------------------------------------------------
+Property Let Source(ByVal pvSource As Variant)
+&apos;&apos;&apos; Set the location of the last error that has occurred
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; myException.Source = 123 &apos; Line # 123. Source may also be a string
+ _PropertySet &quot;Source&quot;, pvSource
+End Property &apos; ScriptForge.SF_Exception.Source (let)
+
+REM -----------------------------------------------------------------------------
+Property Get ObjectType As String
+&apos;&apos;&apos; Only to enable object representation
+ ObjectType = &quot;SF_Exception&quot;
+End Property &apos; ScriptForge.SF_String.ObjectType
+
+REM -----------------------------------------------------------------------------
+Property Get ServiceName As String
+&apos;&apos;&apos; Internal use
+ ServiceName = &quot;ScriptForge.Exception&quot;
+End Property &apos; ScriptForge.SF_Exception.ServiceName
+
+REM ===================================================================== METHODS
+
+REM -----------------------------------------------------------------------------
+Public Sub Clear()
+&apos;&apos;&apos; Reset the current error status and clear the SF_Exception object
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; On Local Error GoTo Catch
+&apos;&apos;&apos; &apos; ...
+&apos;&apos;&apos; Catch:
+&apos;&apos;&apos; SF_Exception.Clear() &apos; Deny the error
+
+Const cstThisSub = &quot;Exception.Clear&quot;
+Const cstSubArgs = &quot;&quot;
+
+Check:
+
+Try:
+ With SF_Exception
+ ._Number = Empty
+ ._Source = Empty
+ ._Description = &quot;&quot;
+ ._SysNumber = 0
+ ._SysSource = 0
+ ._SysDescription = &quot;&quot;
+ End With
+
+Finally:
+ On Error GoTo 0
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; ScriptForge.SF_Exception.Clear
+
+REM -----------------------------------------------------------------------------
+Public Sub Console(Optional ByVal Modal As Variant, _
+ Optional ByRef _Context As Variant _
+ )
+&apos;&apos;&apos; Display the console messages in a modal or non-modal dialog
+&apos;&apos;&apos; If the dialog is already active, when non-modal, it is brought to front
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Modal: Boolean. Default = True
+&apos;&apos;&apos; _Context: From Python, the XComponentXontext (FOR INTERNAL USE ONLY)
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; SF_Exception.Console()
+
+Dim bConsoleActive As Boolean &apos; When True, dialog is active
+Dim oModalBtn As Object &apos; Modal close button
+Dim oNonModalBtn As Object &apos; Non modal close button
+Const cstThisSub = &quot;Exception.Console&quot;
+Const cstSubArgs = &quot;[Modal=True]&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Finally &apos; Never interrupt processing
+
+Check:
+ If IsMissing(Modal) Or IsEmpty(Modal) Then Modal = True
+ If IsMissing(_Context) Or IsEmpty(_Context) Then _Context = Nothing
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(Modal, &quot;Modal&quot;, V_BOOLEAN) Then GoTo Finally
+ End If
+
+Try:
+ With _SF_
+ bConsoleActive = False
+ If Not IsNull(.ConsoleDialog) Then bConsoleActive = .ConsoleDialog._IsStillAlive(False) &apos; False to not raise an error
+ If bConsoleActive And Modal = False Then
+ &apos; Bring to front
+ .ConsoleDialog.Activate()
+ Else
+ &apos; Initialize dialog and fill with actual data
+ &apos; The dual modes (modal and non-modal) require to have 2 close buttons o/w only 1 is visible
+ &apos; - a usual OK button
+ &apos; - a Default button triggering the Close action
+ Set .ConsoleDialog = CreateScriptService(&quot;SFDialogs.Dialog&quot;, &quot;GlobalScope&quot;, &quot;ScriptForge&quot;, &quot;dlgConsole&quot;, _Context)
+ &apos; Setup labels and visibility
+ Set oModalBtn = .ConsoleDialog.Controls(&quot;CloseModalButton&quot;)
+ Set oNonModalBtn = .ConsoleDialog.Controls(&quot;CloseNonModalButton&quot;)
+ oModalBtn.Visible = Modal
+ oNonModalBtn.Visible = CBool(Not Modal)
+ &apos; Load console lines
+ _ConsoleRefresh()
+ .ConsoleDialog.Execute(Modal)
+ &apos; Terminate the modal dialog
+ If Modal Then
+ Set .ConsoleControl = .ConsoleControl.Dispose()
+ Set .ConsoleDialog = .ConsoleDialog.Dispose()
+ End If
+ End If
+ End With
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception.Console
+
+REM -----------------------------------------------------------------------------
+Public Sub ConsoleClear(Optional ByVal Keep)
+&apos;&apos;&apos; Clear the console keeping an optional number of recent messages
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Keep: the number of messages to keep
+&apos;&apos;&apos; If Keep is bigger than the number of messages stored in the console,
+&apos;&apos;&apos; the console is not cleared
+&apos;&apos;&apos; Example:
+&apos;&apos;&apos; SF_Exception.ConsoleClear(5)
+
+Dim lConsole As Long &apos; UBound of ConsoleLines
+Const cstThisSub = &quot;Exception.ConsoleClear&quot;
+Const cstSubArgs = &quot;[Keep=0]&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Finally &apos; Never interrupt processing
+
+Check:
+ If IsMissing(Keep) Or IsEmpty(Keep) Then Keep = 0
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(Keep, &quot;Keep&quot;, V_NUMERIC) Then GoTo Finally
+ End If
+
+Try:
+ With _SF_
+ If Keep &lt;= 0 Then
+ .ConsoleLines = Array()
+ Else
+ lConsole = UBound(.ConsoleLines)
+ If Keep &lt; lConsole + 1 Then .ConsoleLines = SF_Array.Slice(.ConsoleLines, lConsole - Keep + 1)
+ End If
+ End With
+
+ &apos; If active, the console dialog needs to be refreshed
+ _ConsoleRefresh()
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception.ConsoleClear
+
+REM -----------------------------------------------------------------------------
+Public Function ConsoleToFile(Optional ByVal FileName As Variant) As Boolean
+&apos;&apos;&apos; Export the content of the console to a text file
+&apos;&apos;&apos; If the file exists and the console is not empty, it is overwritten without warning
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; FileName: the complete file name to export to. If it exists, is overwritten without warning
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if the file could be created
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; SF_Exception.ConsoleToFile(&quot;myFile.txt&quot;)
+
+Dim bExport As Boolean &apos; Return value
+Dim oFile As Object &apos; Output file handler
+Dim sLine As String &apos; A single line
+Const cstThisSub = &quot;Exception.ConsoleToFile&quot;
+Const cstSubArgs = &quot;FileName&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ bExport = False
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
+ End If
+
+Try:
+
+ If UBound(_SF_.ConsoleLines) &gt; -1 Then
+ Set oFile = SF_FileSystem.CreateTextFile(FileName, Overwrite := True)
+ If Not IsNull(oFile) Then
+ With oFile
+ For Each sLine In _SF_.ConsoleLines
+ .WriteLine(sLine)
+ Next sLine
+ .CloseFile()
+ End With
+ End If
+ bExport = True
+ End If
+
+Finally:
+ If Not IsNull(oFile) Then Set oFile = oFile.Dispose()
+ ConsoleToFile = bExport
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; ScriptForge.SF_Exception.ConsoleToFile
+
+REM -----------------------------------------------------------------------------
+Public Sub DebugDisplay(ParamArray pvArgs() As Variant)
+&apos;&apos;&apos; Display the list of arguments in a readable form in a message box
+&apos;&apos;&apos; Arguments are separated by a LINEFEED character
+&apos;&apos;&apos; The maximum length of each individual argument = 1024 characters
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Any number of arguments of any type
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; SF_Exception.DebugDisplay(a, Array(1, 2, 3), , &quot;line1&quot; &amp; Chr(10) &amp; &quot;Line2&quot;, DateSerial(2020, 04, 09))
+
+Dim sOutputMsg As String &apos; Line to display
+Dim sOutputCon As String &apos; Line to write in console
+Dim sArgMsg As String &apos; Single argument
+Dim sArgCon As String &apos; Single argument
+Dim i As Integer
+Const cstTab = 4
+Const cstMaxLength = 1024
+Const cstThisSub = &quot;Exception.DebugDisplay&quot;
+Const cstSubArgs = &quot;Arg0, [Arg1, ...]&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error Goto Finally &apos; Never interrupt processing
+ SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+Try:
+ &apos; Build new console line
+ sOutputMsg = &quot;&quot; : sOutputCon = &quot;&quot;
+ For i = 0 To UBound(pvArgs)
+ If IsError(pvArgs(i)) Then pvArgs(i) = &quot;&quot;
+ sArgMsg = Iif(i = 0, &quot;&quot;, SF_String.sfNEWLINE) &amp; SF_Utils._Repr(pvArgs(i), cstMaxLength) &apos;Do not use SF_String.Represent()
+ sArgCon = Iif(i = 0, &quot;&quot;, SF_String.sfTAB) &amp; SF_Utils._Repr(pvArgs(i), cstMaxLength)
+ sOutputMsg = sOutputMsg &amp; sArgMsg
+ sOutputCon = sOutputCon &amp; sArgCon
+ Next i
+
+ &apos; Add to actual console
+ _SF_._AddToConsole(SF_String.ExpandTabs(sOutputCon, cstTab))
+ &apos; Display the message
+ MsgBox(sOutputMsg, MB_OK + MB_ICONINFORMATION, &quot;DebugDisplay&quot;)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception.DebugDisplay
+
+REM -----------------------------------------------------------------------------
+Public Sub DebugPrint(ParamArray pvArgs() As Variant)
+&apos;&apos;&apos; Print the list of arguments in a readable form in the console
+&apos;&apos;&apos; Arguments are separated by a TAB character (simulated by spaces)
+&apos;&apos;&apos; The maximum length of each individual argument = 1024 characters
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Any number of arguments of any type
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; SF_Exception.DebugPrint(a, Array(1, 2, 3), , &quot;line1&quot; &amp; Chr(10) &amp; &quot;Line2&quot;, DateSerial(2020, 04, 09))
+
+Dim sOutput As String &apos; Line to write in console
+Dim sArg As String &apos; Single argument
+Dim i As Integer
+Const cstTab = 4
+Const cstMaxLength = 1024
+Const cstThisSub = &quot;Exception.DebugPrint&quot;
+Const cstSubArgs = &quot;Arg0, [Arg1, ...]&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error Goto Finally &apos; Never interrupt processing
+ SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+Try:
+ &apos; Build new console line
+ sOutput = &quot;&quot;
+ For i = 0 To UBound(pvArgs)
+ If IsError(pvArgs(i)) Then pvArgs(i) = &quot;&quot;
+ sArg = Iif(i = 0, &quot;&quot;, SF_String.sfTAB) &amp; SF_Utils._Repr(pvArgs(i), cstMaxLength) &apos;Do not use SF_String.Represent()
+ sOutput = sOutput &amp; sArg
+ Next i
+
+ &apos; Add to actual console
+ _SF_._AddToConsole(SF_String.ExpandTabs(sOutput, cstTab))
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception.DebugPrint
+
+REM -----------------------------------------------------------------------------
+Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
+&apos;&apos;&apos; Return the actual value of the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; The actual value of the property
+&apos;&apos;&apos; If the property does not exist, returns Null
+&apos;&apos;&apos; Exceptions
+&apos;&apos;&apos; ARGUMENTERROR The property does not exist
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; myException.GetProperty(&quot;MyProperty&quot;)
+
+Const cstThisSub = &quot;Exception.GetProperty&quot;
+Const cstSubArgs = &quot;&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ GetProperty = Null
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ GetProperty = _PropertyGet(PropertyName)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; ScriptForge.SF_Exception.GetProperty
+
+REM -----------------------------------------------------------------------------
+Public Function Methods() As Variant
+&apos;&apos;&apos; Return the list of public methods of the Exception service as an array
+
+ Methods = Array( _
+ &quot;Clear&quot; _
+ , &quot;Console&quot; _
+ , &quot;ConsoleClear&quot; _
+ , &quot;ConsoleToFile&quot; _
+ , &quot;DebugPrint&quot; _
+ , &quot;Raise&quot; _
+ , &quot;RaiseAbort&quot; _
+ , &quot;RaiseFatal&quot; _
+ , &quot;RaiseWarning&quot; _
+ )
+
+End Function &apos; ScriptForge.SF_Exception.Methods
+
+REM -----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos; Return the list or properties of the Timer class as an array
+
+ Properties = Array( _
+ &quot;Description&quot; _
+ , &quot;Number&quot; _
+ , &quot;Source&quot; _
+ )
+
+End Function &apos; ScriptForge.SF_Exception.Properties
+
+REM -----------------------------------------------------------------------------
+Public Sub PythonPrint(ParamArray pvArgs() As Variant)
+&apos;&apos;&apos; Display the list of arguments in a readable form in the Python console
+&apos;&apos;&apos; Arguments are separated by a TAB character (simulated by spaces)
+&apos;&apos;&apos; The maximum length of each individual argument = 1024 characters
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Any number of arguments of any type
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; SF_Exception.PythonPrint(a, Array(1, 2, 3), , &quot;line1&quot; &amp; Chr(10) &amp; &quot;Line2&quot;, DateSerial(2020, 04, 09))
+
+Dim sOutput As String &apos; Line to write in console
+Dim sArg As String &apos; Single argument
+Dim i As Integer
+Const cstTab = 4
+Const cstMaxLength = 1024
+Const cstPyHelper = &quot;$&quot; &amp; &quot;_SF_Exception__PythonPrint&quot;
+Const cstThisSub = &quot;Exception.PythonPrint&quot;
+Const cstSubArgs = &quot;Arg0, [Arg1, ...]&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error Goto Finally &apos; Never interrupt processing
+ SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+Try:
+ &apos; Build new console line
+ sOutput = &quot;&quot;
+ For i = 0 To UBound(pvArgs)
+ If IsError(pvArgs(i)) Then pvArgs(i) = &quot;&quot;
+ sArg = Iif(i = 0, &quot;&quot;, SF_String.sfTAB) &amp; SF_Utils._Repr(pvArgs(i), cstMaxLength)
+ sOutput = sOutput &amp; sArg
+ Next i
+
+ &apos; Add to actual console
+ sOutput = SF_String.ExpandTabs(sOutput, cstTab)
+ _SF_._AddToConsole(sOutput)
+ &apos; Display the message in the Python shell console
+ With ScriptForge.SF_Session
+ .ExecutePythonScript(.SCRIPTISSHARED, _SF_.PythonHelper &amp; cstPyHelper, sOutput)
+ End With
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception.PythonPrint
+
+REM -----------------------------------------------------------------------------
+Public Sub Raise(Optional ByVal Number As Variant _
+ , Optional ByVal Source As Variant _
+ , Optional ByVal Description As Variant _
+ )
+&apos;&apos;&apos; Generate a run-time error. An error message is displayed to the user and logged
+&apos;&apos;&apos; in the console. The execution is STOPPED
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Number: the error number, may be numeric or string
+&apos;&apos;&apos; If numeric and &lt;= 2000, it is considered a LibreOffice Basic run-time error (default = Err)
+&apos;&apos;&apos; Source: the line where the error occurred (default = Erl) or any string describing the location of the error
+&apos;&apos;&apos; Description: the error message to log in the console and to display to the user
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; On Local Error GoTo Catch
+&apos;&apos;&apos; &apos; ...
+&apos;&apos;&apos; Catch:
+&apos;&apos;&apos; SF_Exception.Raise() &apos; Standard behaviour
+&apos;&apos;&apos; SF_Exception.Raise(11) &apos; Force division by zero
+&apos;&apos;&apos; SF_Exception.Raise(&quot;MYAPPERROR&quot;, &quot;myFunction&quot;, &quot;Application error&quot;)
+&apos;&apos;&apos; SF_Exception.Raise(,, &quot;To divide by zero is not a good idea !&quot;)
+
+Dim sMessage As String &apos; Error message to log and to display
+Dim L10N As Object &apos; Alias to LocalizedInterface
+Const cstThisSub = &quot;Exception.Raise&quot;
+Const cstSubArgs = &quot;[Number=Err], [Source=Erl], [Description]&quot;
+
+ &apos; Save Err, Erl, .. values before any On Error ... statement
+ SF_Exception._CaptureSystemError()
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(Number) Or IsEmpty(Number) Then Number = -1
+ If IsMissing(Source) Or IsEmpty(Source) Then Source = -1
+ If IsMissing(Description) Or IsEmpty(Description) Then Description = &quot;&quot;
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(Number, &quot;Number&quot;, Array(V_STRING, V_NUMERIC)) Then GoTo Finally
+ If Not SF_Utils._Validate(Source, &quot;Source&quot;, Array(V_STRING, V_NUMERIC)) Then GoTo Finally
+ If Not SF_Utils._Validate(Description, &quot;Description&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ With SF_Exception
+ If Number &gt;= 0 Then .Number = Number
+ If VarType(Source) = V_STRING Then
+ If Len(Source) &gt; 0 Then .Source = Source
+ ElseIf Source &gt;= 0 Then &apos; -1 = Default =&gt; no change
+ .Source = Source
+ End If
+ If Len(Description) &gt; 0 Then .Description = Description
+
+ &apos; Log and display
+ Set L10N = _SF_._GetLocalizedInterface()
+ sMessage = L10N.GetText(&quot;LONGERRORDESC&quot;, .Number, .Source, .Description)
+ .DebugPrint(sMessage)
+ If _SF_.DisplayEnabled Then MsgBox L10N.GetText(&quot;ERRORNUMBER&quot;, .Number) _
+ &amp; SF_String.sfNewLine &amp; L10N.GetText(&quot;ERRORLOCATION&quot;, .Source) _
+ &amp; SF_String.sfNewLine &amp; .Description _
+ , MB_OK + MB_ICONSTOP _
+ , L10N.GetText(&quot;ERRORNUMBER&quot;, .Number)
+ .Clear()
+ End With
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ If _SF_.StopWhenError Then
+ _SF_._StackReset()
+ Stop
+ End If
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; ScriptForge.SF_Exception.Raise
+
+REM -----------------------------------------------------------------------------
+Public Sub RaiseAbort(Optional ByVal Source As Variant)
+&apos;&apos;&apos; Manage a run-time error that occurred inside the ScriptForge piece of software itself.
+&apos;&apos;&apos; The event is logged.
+&apos;&apos;&apos; The execution is STOPPED
+&apos;&apos;&apos; For INTERNAL USE only
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Source: the line where the error occurred
+
+Dim sLocation As String &apos; Common header in error messages: location of error
+Dim vLocation As Variant &apos; Split array (library, module, method)
+Dim sMessage As String &apos; Error message to log and to display
+Dim L10N As Object &apos; Alias to LocalizedInterface
+Const cstTabSize = 4
+Const cstThisSub = &quot;Exception.RaiseAbort&quot;
+Const cstSubArgs = &quot;[Source=Erl]&quot;
+
+ &apos; Save Err, Erl, .. values before any On Error ... statement
+ SF_Exception._CaptureSystemError()
+ On Local Error Resume Next
+
+Check:
+ If IsMissing(Source) Or IsEmpty(Source) Then Source = &quot;&quot;
+
+Try:
+ With SF_Exception
+
+ &apos; Prepare message header
+ Set L10N = _SF_._GetLocalizedInterface()
+ If Len(_SF_.MainFunction) &gt; 0 Then &apos; MainFunction = [Library.]Module.Method
+ vLocation = Split(_SF_.MainFunction, &quot;.&quot;)
+ If UBound(vLocation) &lt; 2 Then vLocation = SF_Array.Prepend(vLocation, &quot;ScriptForge&quot;)
+ sLocation = L10N.GetText(&quot;VALIDATESOURCE&quot;, vLocation(0), vLocation(1), vLocation(2)) &amp; &quot;\n\n\n&quot;
+ Else
+ sLocation = &quot;&quot;
+ End If
+
+ &apos; Log and display
+ sMessage = L10N.GetText(&quot;LONGERRORDESC&quot;, .Number, .Source, .Description)
+ .DebugPrint(sMessage)
+ If _SF_.DisplayEnabled Then
+ sMessage = sLocation _
+ &amp; L10N.GetText(&quot;INTERNALERROR&quot;) _
+ &amp; L10N.GetText(&quot;ERRORLOCATION&quot;, Source &amp; &quot;/&quot; &amp; .Source) &amp; SF_String.sfNewLine &amp; .Description _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; L10N.GetText(&quot;STOPEXECUTION&quot;)
+ MsgBox SF_String.ExpandTabs(SF_String.Unescape(sMessage), cstTabSize) _
+ , MB_OK + MB_ICONSTOP _
+ , L10N.GetText(&quot;ERRORNUMBER&quot;, .Number)
+ End If
+
+ .Clear()
+ End With
+
+Finally:
+ _SF_._StackReset()
+ If _SF_.StopWhenError Then Stop
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; ScriptForge.SF_Exception.RaiseAbort
+
+REM -----------------------------------------------------------------------------
+Public Sub RaiseFatal(Optional ByVal ErrorCode As Variant _
+ , ParamArray pvArgs _
+ )
+&apos;&apos;&apos; Generate a run-time error caused by an anomaly in a user script detected by ScriptForge
+&apos;&apos;&apos; The message is logged in the console. The execution is STOPPED
+&apos;&apos;&apos; For INTERNAL USE only
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; ErrorCode: as a string, the unique identifier of the error
+&apos;&apos;&apos; pvArgs: the arguments to insert in the error message
+
+Dim sLocation As String &apos; Common header in error messages: location of error
+Dim sService As String &apos; Service name having detected the error
+Dim sMethod As String &apos; Method name having detected the error
+Dim vLocation As Variant &apos; Split array (library, module, method)
+Dim sMessage As String &apos; Message to log and display
+Dim L10N As Object &apos; Alias of LocalizedInterface
+Dim sAlt As String &apos; Alternative error messages
+Dim iButtons As Integer &apos; MB_OK or MB_YESNO
+Dim iMsgBox As Integer &apos; Return value of the message box
+
+Const cstTabSize = 4
+Const cstThisSub = &quot;Exception.RaiseFatal&quot;
+Const cstSubArgs = &quot;ErrorCode, [Arg0[, Arg1 ...]]&quot;
+Const cstStop = &quot;⏻&quot; &apos; Chr(9211)
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(ErrorCode) Or IsEmpty(ErrorCode) Then ErrorCode = &quot;&quot;
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(ErrorCode, &quot;ErrorCode&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ Set L10N = _SF_._GetLocalizedInterface()
+ &apos; Location header common to all error messages
+ If Len(_SF_.MainFunction) &gt; 0 Then &apos; MainFunction = [Library.]Module.Method
+ vLocation = Split(_SF_.MainFunction, &quot;.&quot;)
+ If UBound(vLocation) &lt; 2 Then vLocation = SF_Array.Prepend(vLocation, &quot;ScriptForge&quot;)
+ sService = vLocation(1)
+ sMethod = vLocation(2)
+ sLocation = L10N.GetText(&quot;VALIDATESOURCE&quot;, vLocation(0), sService, sMethod) _
+ &amp; &quot;\n&quot; &amp; L10N.GetText(&quot;VALIDATEARGS&quot;, _RightCaseArgs(_SF_.MainFunctionArgs))
+ Else
+ sService = &quot;&quot;
+ sMethod = &quot;&quot;
+ sLocation = &quot;&quot;
+ End If
+
+ With L10N
+ Select Case UCase(ErrorCode)
+ Case MISSINGARGERROR &apos; SF_Utils._Validate(Name)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEMISSING&quot;, pvArgs(0))
+ Case ARGUMENTERROR &apos; SF_Utils._Validate(Value, Name, Types, Values, Regex, Class)
+ pvArgs(1) = _RightCase(pvArgs(1))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(1)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATIONRULES&quot;)
+ If Len(pvArgs(2)) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATETYPES&quot;, pvArgs(1), pvArgs(2))
+ If Len(pvArgs(3)) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEVALUES&quot;, pvArgs(1), pvArgs(3))
+ If Len(pvArgs(4)) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEREGEX&quot;, pvArgs(1), pvArgs(4))
+ If Len(pvArgs(5)) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATECLASS&quot;, pvArgs(1), pvArgs(5))
+ sMessage = sMessage &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEACTUAL&quot;, pvArgs(1), pvArgs(0))
+ Case ARRAYERROR &apos; SF_Utils._ValidateArray(Value, Name, Dimensions, Types, NotNull)
+ pvArgs(1) = _RightCase(pvArgs(1))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(1)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATIONRULES&quot;) _
+ &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEARRAY&quot;, pvArgs(1))
+ If pvArgs(2) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEDIMS&quot;, pvArgs(1), pvArgs(2))
+ If Len(pvArgs(3)) &gt; 0 Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEALLTYPES&quot;, pvArgs(1), pvArgs(3))
+ If pvArgs(4) Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATENOTNULL&quot;, pvArgs(1))
+ sMessage = sMessage &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEACTUAL&quot;, pvArgs(1), pvArgs(0))
+ Case FILEERROR &apos; SF_Utils._ValidateFile(Value, Name, WildCards)
+ pvArgs(1) = _RightCase(pvArgs(1))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(1)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATIONRULES&quot;) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEFILE&quot;, pvArgs(1))
+ sAlt = &quot;VALIDATEFILE&quot; &amp; SF_FileSystem.FileNaming
+ sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(sAlt, pvArgs(1))
+ If pvArgs(2) Then sMessage = sMessage &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEWILDCARD&quot;, pvArgs(1))
+ sMessage = sMessage &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEACTUAL&quot;, pvArgs(1), pvArgs(0))
+ Case ARRAYSEQUENCEERROR &apos; SF_Array.RangeInit(From, UpTo, ByStep)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;ARRAYSEQUENCE&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case ARRAYINSERTERROR &apos; SF_Array.AppendColumn/Row/PrependColumn/Row(VectorName, Array_2D, Vector)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;ARRAYINSERT&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case ARRAYINDEX1ERROR &apos; SF_Array.ExtractColumn/Row(IndexName, Array_2D, Index)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;ARRAYINDEX1&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case ARRAYINDEX2ERROR &apos; SF_Array.Slice(From, UpTo)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;ARRAYINDEX2&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case CSVPARSINGERROR &apos; SF_Array.ImportFromCSVFile(FileName, LineNumber, Line)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CSVPARSING&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case DUPLICATEKEYERROR &apos; SF_Dictionary.Add/ReplaceKey(&quot;Key&quot;, Key)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DUPLICATEKEY&quot;, pvArgs(0), pvArgs(1))
+ Case UNKNOWNKEYERROR &apos; SF_Dictionary.Remove/ReplaceItem/ReplaceKey(&quot;Key&quot;, Key)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNKNOWNKEY&quot;, pvArgs(0), pvArgs(1))
+ Case INVALIDKEYERROR &apos; SF_Dictionary.Add/ReplaceKey(Key)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;INVALIDKEY&quot;)
+ Case UNKNOWNFILEERROR &apos; SF_FileSystem.CopyFile/MoveFile/DeleteFile/CreateScriptService(&quot;L10N&quot;)(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNKNOWNFILE&quot;, pvArgs(0), pvArgs(1))
+ Case UNKNOWNFOLDERERROR &apos; SF_FileSystem.CopyFolder/MoveFolder/DeleteFolder/Files/SubFolders(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNKNOWNFOLDER&quot;, pvArgs(0), pvArgs(1))
+ Case NOTAFILEERROR &apos; SF_FileSystem.CopyFile/MoveFile/DeleteFile(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;NOTAFILE&quot;, pvArgs(0), pvArgs(1))
+ Case NOTAFOLDERERROR &apos; SF_FileSystem.CopyFolder/MoveFolder/DeleteFolder/Files/SubFolders(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;NOTAFOLDER&quot;, pvArgs(0), pvArgs(1))
+ Case OVERWRITEERROR &apos; SF_FileSystem.Copy+Move/File+Folder/CreateTextFile/OpenTextFile(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;OVERWRITE&quot;, pvArgs(0), pvArgs(1))
+ Case READONLYERROR &apos; SF_FileSystem.Copy+Move+Delete/File+Folder(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;READONLY&quot;, pvArgs(0), pvArgs(1))
+ Case NOFILEMATCHERROR &apos; SF_FileSystem.Copy+Move+Delete/File+Folder(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;NOFILEMATCH&quot;, pvArgs(0), pvArgs(1))
+ Case FOLDERCREATIONERROR &apos; SF_FileSystem.CreateFolder(ArgName, Filename)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FOLDERCREATION&quot;, pvArgs(0), pvArgs(1))
+ Case UNKNOWNSERVICEERROR &apos; SF_Services.CreateScriptService(ArgName, Value, Library, Service)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNKNOWNSERVICE&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case SERVICESNOTLOADEDERROR &apos; SF_Services.CreateScriptService(ArgName, Value, Library)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SERVICESNOTLOADED&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case CALCFUNCERROR &apos; SF_Session.ExecuteCalcFunction(CalcFunction)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, _RightCase(&quot;CalcFunction&quot;)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CALCFUNC&quot;, pvArgs(0))
+ Case NOSCRIPTERROR &apos; SF_Session._GetScript(Language, &quot;Scope&quot;, Scope, &quot;Script&quot;, Script)
+ pvArgs(1) = _RightCase(pvArgs(1)) : pvArgs(3) = _RightCase(pvArgs(3))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, _RightCase(&quot;Script&quot;)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;NOSCRIPT&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4))
+ Case SCRIPTEXECERROR &apos; SF_Session.ExecuteBasicScript(&quot;Script&quot;, Script, Cause)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SCRIPTEXEC&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case WRONGEMAILERROR &apos; SF_Session.SendMail(Arg, Email)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;WRONGEMAIL&quot;, pvArgs(1))
+ Case SENDMAILERROR &apos; SF_Session.SendMail()
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SENDMAIL&quot;)
+ Case FILENOTOPENERROR &apos; SF_TextStream._IsFileOpen(FileName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FILENOTOPEN&quot;, pvArgs(0))
+ Case FILEOPENMODEERROR &apos; SF_TextStream._IsFileOpen(FileName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FILEOPENMODE&quot;, pvArgs(0), pvArgs(1))
+ Case ENDOFFILEERROR &apos; SF_TextStream.ReadLine/ReadAll/SkipLine(FileName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;ENDOFFILE&quot;, pvArgs(0))
+ Case DOCUMENTERROR &apos; SF_UI.GetDocument(ArgName, WindowName)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENT&quot;, pvArgs(0), pvArgs(1))
+ Case DOCUMENTCREATIONERROR &apos; SF_UI.Create(Arg1Name, DocumentType, Arg2Name, TemplateFile)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTCREATION&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case DOCUMENTOPENERROR &apos; SF_UI.OpenDocument(Arg1Name, FileName, Arg2Name, Password, Arg3Name, FilterName)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2)) : pvArgs(4) = _RightCase(pvArgs(4))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTOPEN&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4), pvArgs(5))
+ Case BASEDOCUMENTOPENERROR &apos; SF_UI.OpenBaseDocument(Arg1Name, FileName, Arg2Name, RegistrationName)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;BASEDOCUMENTOPEN&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case DOCUMENTDEADERROR &apos; SF_Document._IsStillAlive(FileName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTDEAD&quot;, pvArgs(0))
+ Case DOCUMENTSAVEERROR &apos; SF_Document.Save(Arg1Name, FileName)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTSAVE&quot;, pvArgs(0), pvArgs(1))
+ Case DOCUMENTSAVEASERROR &apos; SF_Document.SaveAs(Arg1Name, FileName, Arg2, Overwrite, Arg3, FilterName)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2)) : pvArgs(4) = _RightCase(pvArgs(4))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTSAVEAS&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4), pvArgs(5))
+ Case DOCUMENTREADONLYERROR &apos; SF_Document.update property(&quot;Document&quot;, FileName)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DOCUMENTREADONLY&quot;, pvArgs(0), pvArgs(1))
+ Case DBCONNECTERROR &apos; SF_Base.GetDatabase(&quot;User&quot;, User, &quot;Password&quot;, Password, FileName)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DBCONNECT&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4))
+ Case CALCADDRESSERROR &apos; SF_Calc._ParseAddress(Address, &quot;Range&quot;/&quot;Sheet&quot;, Scope, Document)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CALCADDRESS&quot; &amp; Iif(pvArgs(0) = &quot;Sheet&quot;, &quot;1&quot;, &quot;2&quot;), pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case DUPLICATESHEETERROR &apos; SF_Calc.InsertSheet(arg, SheetName, Document)
+ pvArgs(0) = _RightCase(pvArgs(0))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DUPLICATESHEET&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case OFFSETADDRESSERROR &apos; SF_Calc.RangeOffset(&quot;Range&quot;, Range, &quot;Rows&quot;, Rows, &quot;Columns&quot;, Columns, &quot;Height&quot;, Height, &quot;Width&quot;, Width, &quot;Document, Document)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2)) : pvArgs(4) = _RightCase(pvArgs(4))
+ pvArgs(6) = _RightCase(pvArgs(6)) : pvArgs(8) = _RightCase(pvArgs(8)) : pvArgs(10) = _RightCase(pvArgs(10))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;OFFSETADDRESS&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4) _
+ , pvArgs(5), pvArgs(6), pvArgs(7), pvArgs(8), pvArgs(9), pvArgs(10), pvArgs(11))
+ Case DUPLICATECHARTERROR &apos; SF_Calc.CreateChart(chart, ChartName, sheet, SheetName, Document, file)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, pvArgs(0)) _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DUPLICATECHART&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4), pvArgs(5))
+ Case RANGEEXPORTERROR &apos; SF_Calc.ExportRangeToFile(Arg1Name, FileName, Arg2, Overwrite)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;RANGEEXPORT&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case CHARTEXPORTERROR &apos; SF_Chart.ExportToFile(Arg1Name, FileName, Arg2, Overwrite)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CHARTEXPORT&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case FORMDEADERROR &apos; SF_Form._IsStillAlive(FormName, DocumentName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FORMDEAD&quot;, pvArgs(0), pvArgs(1))
+ Case CALCFORMNOTFOUNDERROR &apos; SF_Calc.Forms(Index, SheetName, Document)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CALCFORMNOTFOUND&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case WRITERFORMNOTFOUNDERROR &apos; SF_Document.Forms(Index, Document)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;WRITERFORMNOTFOUND&quot;, pvArgs(0), pvArgs(1))
+ Case BASEFORMNOTFOUNDERROR &apos; SF_Base.Forms(Index, FormDocument, BaseDocument)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;BASEFORMNOTFOUND&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
+ Case SUBFORMNOTFOUNDERROR &apos; SF_Form.Subforms(Subform, Mainform)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SUBFORMNOTFOUND&quot;, pvArgs(0), pvArgs(1))
+ Case FORMCONTROLTYPEERROR &apos; SF_FormControl._SetProperty(ControlName, FormName, ControlType, Property)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FORMCONTROLTYPE&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case DIALOGNOTFOUNDERROR &apos; SF_Dialog._NewDialog(Service, DialogName, WindowName)
+ pvArgs(0) = _RightCase(pvArgs(0)) : pvArgs(2) = _RightCase(pvArgs(2)) : pvArgs(4) = _RightCase(pvArgs(4))
+ pvArgs(6) = _RightCase(pvArgs(6))
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DIALOGNOTFOUND&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4) _
+ , pvArgs(5), pvArgs(6), pvArgs(7))
+ Case DIALOGDEADERROR &apos; SF_Dialog._IsStillAlive(DialogName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DIALOGDEAD&quot;, pvArgs(0))
+ Case CONTROLTYPEERROR &apos; SF_DialogControl._SetProperty(ControlName, DialogName, ControlType, Property)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;CONTROLTYPE&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
+ Case TEXTFIELDERROR &apos; SF_DialogControl.WriteLine(ControlName, DialogName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;TEXTFIELD&quot;, pvArgs(0), pvArgs(1))
+ Case DBREADONLYERROR &apos; SF_Database.RunSql()
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;DBREADONLY&quot;, vLocation(2))
+ Case SQLSYNTAXERROR &apos; SF_Database._ExecuteSql(SQL)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SQLSYNTAX&quot;, pvArgs(0))
+ Case PYTHONSHELLERROR &apos; SF_Exception.PythonShell (Python only)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;PYTHONSHELL&quot;)
+ Case UNITTESTLIBRARYERROR &apos; SFUnitTests._NewUnitTest(LibraryName)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNITTESTLIBRARY&quot;, pvArgs(0))
+ Case UNITTESTMETHODERROR &apos; SFUnitTests.SF_UnitTest(Method)
+ sMessage = sLocation _
+ &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;UNITTESTMETHOD&quot;, pvArgs(0))
+ Case Else
+ End Select
+ End With
+
+ &apos; Log fatal event
+ _SF_._AddToConsole(sMessage)
+
+ &apos; Display fatal event, if relevant (default)
+ If _SF_.DisplayEnabled Then
+ If _SF_.StopWhenError Then sMessage = sMessage &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; L10N.GetText(&quot;STOPEXECUTION&quot;)
+ &apos; Do you need more help ?
+ If Len(sMethod) &gt; 0 Then
+ sMessage = sMessage &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; L10N.GetText(&quot;NEEDMOREHELP&quot;, sMethod)
+ iButtons = MB_YESNO + MB_DEFBUTTON2
+ Else
+ iButtons = MB_OK
+ End If
+ iMsgBox = MsgBox(SF_String.ExpandTabs(SF_String.Unescape(sMessage), cstTabSize) _
+ , iButtons + MB_ICONEXCLAMATION _
+ , L10N.GetText(&quot;ERRORNUMBER&quot;, ErrorCode) _
+ )
+ &apos; If more help needed ...
+ If iMsgBox = IDYES Then _OpenHelpInBrowser(sService, sMethod)
+ End If
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ _SF_._StackReset()
+ If _SF_.StopWhenError Then Stop
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; ScriptForge.SF_Exception.RaiseFatal
+
+REM -----------------------------------------------------------------------------
+Public Sub RaiseWarning(Optional ByVal Number As Variant _
+ , Optional ByVal Source As Variant _
+ , Optional ByVal Description As Variant _
+ )
+&apos;&apos;&apos; Generate a run-time error. An error message is displayed to the user and logged
+&apos;&apos;&apos; in the console. The execution is NOT STOPPED
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Number: the error number, may be numeric or string
+&apos;&apos;&apos; If numeric and &lt;= 2000, it is considered a LibreOffice Basic run-time error (default = Err)
+&apos;&apos;&apos; Source: the line where the error occurred (default = Erl) or any string describing the location of the error
+&apos;&apos;&apos; Description: the error message to log in the console and to display to the user
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; True if successful. Anyway, the execution continues
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; On Local Error GoTo Catch
+&apos;&apos;&apos; &apos; ...
+&apos;&apos;&apos; Catch:
+&apos;&apos;&apos; SF_Exception.RaiseWarning() &apos; Standard behaviour
+&apos;&apos;&apos; SF_Exception.RaiseWarning(11) &apos; Force division by zero
+&apos;&apos;&apos; SF_Exception.RaiseWarning(&quot;MYAPPERROR&quot;, &quot;myFunction&quot;, &quot;Application error&quot;)
+&apos;&apos;&apos; SF_Exception.RaiseWarning(,, &quot;To divide by zero is not a good idea !&quot;)
+
+Dim bStop As Boolean &apos; Alias for stop switch
+Const cstThisSub = &quot;Exception.RaiseWarning&quot;
+Const cstSubArgs = &quot;[Number=Err], [Source=Erl], [Description]&quot;
+
+ &apos; Save Err, Erl, .. values before any On Error ... statement
+ SF_Exception._CaptureSystemError()
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+ If IsMissing(Number) Or IsEmpty(Number) Then Number = -1
+ If IsMissing(Source) Or IsEmpty(Source) Then Source = -1
+ If IsMissing(Description) Or IsEmpty(Description) Then Description = &quot;&quot;
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(Number, &quot;Number&quot;, Array(V_STRING, V_NUMERIC, V_EMPTY)) Then GoTo Finally
+ If Not SF_Utils._Validate(Source, &quot;Source&quot;, Array(V_STRING, V_NUMERIC, V_EMPTY)) Then GoTo Finally
+ If Not SF_Utils._Validate(Description, &quot;Description&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ bStop = _SF_.StopWhenError &apos; Store current value to reset it before leaving the Sub
+ _SF_.StopWhenError = False
+ SF_Exception.Raise(Number, Source, Description)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ _SF_.StopWhenError = bStop
+ Exit Sub
+Catch:
+ GoTo Finally
+End Sub &apos; ScriptForge.SF_Exception.RaiseWarning
+
+REM -----------------------------------------------------------------------------
+Public Function SetProperty(Optional ByVal PropertyName As Variant _
+ , Optional ByRef Value As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set a new value to the given property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; PropertyName: the name of the property as a string
+&apos;&apos;&apos; Value: its new value
+&apos;&apos;&apos; Exceptions
+&apos;&apos;&apos; ARGUMENTERROR The property does not exist
+
+Const cstThisSub = &quot;Exception.SetProperty&quot;
+Const cstSubArgs = &quot;PropertyName, Value&quot;
+
+ If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ SetProperty = False
+
+Check:
+ If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+ End If
+
+Try:
+ SetProperty = _PropertySet(PropertyName, Value)
+
+Finally:
+ SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ GoTo Finally
+End Function &apos; ScriptForge.SF_Exception.SetProperty
+
+REM =========================================================== PRIVATE FUNCTIONS
+
+REM -----------------------------------------------------------------------------
+Private Sub _CaptureSystemError()
+&apos;&apos;&apos; Store system error status in system error properties
+&apos;&apos;&apos; Called at each invocation of an error management property or method
+&apos;&apos;&apos; Reset by SF_Exception.Clear()
+
+ If Err &gt; 0 And _SysNumber = 0 Then
+ _SysNumber = Err
+ _SysSource = Erl
+ _SysDescription = Error$
+ End If
+
+End Sub &apos; ScriptForge.SF_Exception._CaptureSystemError
+
+REM -----------------------------------------------------------------------------
+Public Sub _CloseConsole(Optional ByRef poEvent As Object)
+&apos;&apos;&apos; Close the console when opened in non-modal mode
+&apos;&apos;&apos; Triggered by the CloseNonModalButton from the dlgConsole dialog
+
+ On Local Error GoTo Finally
+
+Try:
+ With _SF_
+ If Not IsNull(.ConsoleDialog) Then
+ If .ConsoleDialog._IsStillAlive(False) Then &apos; False to not raise an error
+ Set .ConsoleControl = .ConsoleControl.Dispose()
+ Set .ConsoleDialog = .ConsoleDialog.Dispose()
+ End If
+ End If
+ End With
+
+Finally:
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception._CloseConsole
+
+REM -----------------------------------------------------------------------------
+Private Sub _ConsoleRefresh()
+&apos;&apos;&apos; Reload the content of the console in the dialog
+&apos;&apos;&apos; Needed when console first loaded or when totally or partially cleared
+
+ With _SF_
+ &apos; Do nothing if console inactive
+ If IsNull(.ConsoleDialog) Then GoTo Finally
+ If Not .ConsoleDialog._IsStillAlive(False) Then &apos; False to not generate an error when dead
+ Set .ConsoleControl = .ConsoleControl.Dispose()
+ Set .ConsoleDialog = Nothing
+ GoTo Finally
+ End If
+ &apos; Store the relevant text in the control
+ If IsNull(.ConsoleControl) Then Set .ConsoleControl = .ConsoleDialog.Controls(CONSOLENAME)
+ .ConsoleControl.Value = &quot;&quot;
+ If UBound(.ConsoleLines) &gt;= 0 Then .ConsoleControl.WriteLine(Join(.ConsoleLines, SF_String.sfNEWLINE))
+ End With
+
+Finally:
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception._ConsoleRefresh
+
+REM -----------------------------------------------------------------------------
+Private Sub _OpenHelpInBrowser(ByVal psService As String, ByVal psMethod As String)
+&apos;&apos;&apos; Open the help page and help anchor related to the given ScriptForge service and method
+
+Dim sUrl As String &apos; URL to open
+Const cstURL = &quot;https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_%1.html?&amp;DbPAR=BASIC#%2&quot;
+
+ On Local Error GoTo Finally &apos; No reason to risk abort here
+Try:
+ sUrl = SF_String.ReplaceStr(cstURL, Array(&quot;%1&quot;, &quot;%2&quot;), Array(LCase(psService), psMethod))
+ SF_Session.OpenUrlInBrowser(sUrl)
+
+Finally:
+ Exit Sub
+End Sub &apos; ScriptForge.SF_Exception._OpenHelpInBrowser
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos; Return the value of the named property
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SF_Exception.get&quot; &amp; psProperty
+
+ SF_Exception._CaptureSystemError()
+
+ Select Case psProperty
+ Case &quot;Description&quot;
+ If _Description = &quot;&quot; Then _PropertyGet = _SysDescription Else _PropertyGet = _Description
+ Case &quot;Number&quot;
+ If IsEmpty(_Number) Then _PropertyGet = _SysNumber Else _PropertyGet = _Number
+ Case &quot;Source&quot;
+ If IsEmpty(_Source) Then _PropertyGet = _SysSource Else _PropertyGet = _Source
+ Case Else
+ _PropertyGet = Null
+ End Select
+
+Finally:
+ Exit Function
+End Function &apos; ScriptForge.SF_Exception._PropertyGet
+
+REM -----------------------------------------------------------------------------
+Private Function _PropertySet(Optional ByVal psProperty As String _
+ , Optional ByVal pvValue As Variant _
+ ) As Boolean
+&apos;&apos;&apos; Set a new value to the named property
+&apos;&apos;&apos; Applicable only to user defined errors
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psProperty: the name of the property
+&apos;&apos;&apos; pvValue: the new value
+
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+ cstThisSub = &quot;SF_Exception.set&quot; &amp; psProperty
+ _PropertySet = False
+
+ SF_Exception._CaptureSystemError()
+
+ &apos; Argument validation must be manual to preserve system error status
+ &apos; If wrong VarType then property set is ignored
+ Select Case psProperty
+ Case &quot;Description&quot;
+ If VarType(pvValue) = V_STRING Then _Description = pvValue
+ Case &quot;Number&quot;
+ Select Case SF_Utils._VarTypeExt(pvValue)
+ Case V_STRING
+ _Number = pvValue
+ Case V_NUMERIC
+ _Number = CLng(pvValue)
+ If _Number &lt;= RUNTIMEERRORS And Len(_Description) = 0 Then _Description = Error(_Number)
+ Case V_EMPTY
+ _Number = Empty
+ Case Else
+ End Select
+ Case &quot;Source&quot;
+ Select Case SF_Utils._VarTypeExt(pvValue)
+ Case V_STRING
+ _Source = pvValue
+ Case V_NUMERIC
+ _Source = CLng(pvValue)
+ Case Else
+ End Select
+ Case Else
+ End Select
+
+ _PropertySet = True
+
+Finally:
+ Exit Function
+End Function &apos; ScriptForge.SF_Exception._PropertySet
+
+REM -----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos; Convert the Exception instance to a readable string, typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; &quot;[Exception]: A readable string&quot;
+
+ _Repr = &quot;[Exception]: &quot; &amp; _Number &amp; &quot; (&quot; &amp; _Description &amp; &quot;)&quot;
+
+End Function &apos; ScriptForge.SF_Exception._Repr
+
+REM -----------------------------------------------------------------------------
+Private Function _RightCase(psString As String) As String
+&apos;&apos;&apos; Return the input argument in lower case only when the procedure in execution
+&apos;&apos;&apos; has been triggered from a Python script
+&apos;&apos;&apos; Indeed, Python requires lower case arguments
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psString: probably an identifier in ProperCase
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; The input argument in lower case or left unchanged depending on the execution context
+
+Try:
+ If _SF_.TriggeredByPython Then _RightCase = LCase(psString) Else _RightCase = psString
+
+Finally:
+ Exit Function
+End Function &apos; ScriptForge.SF_Exception._RightCase
+
+REM -----------------------------------------------------------------------------
+Private Function _RightCaseArgs(psString As String) As String
+&apos;&apos;&apos; Return the input argument unchanged when the execution context is Basic
+&apos;&apos;&apos; When it is Python, the argument names are lowercased.
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; psString: one of the cstSubArgs strings located in each official method
+&apos;&apos;&apos; Return:
+&apos;&apos;&apos; The input string in which the argument names are put in lower case when called from Python scripts
+
+Dim sSubArgs As String &apos; Return value
+Dim vArgs As Variant &apos; Input string split on the comma character
+Dim sSingleArg As String &apos; Single vArgs item
+Dim vSingleArgs As Variant &apos; vSingleArg split on equal sign
+Dim i As Integer
+
+Const cstComma = &quot;,&quot;
+Const cstEqual = &quot;=&quot;
+
+Try:
+ If Len(psString) = 0 Then
+ sSubArgs = &quot;&quot;
+ ElseIf _SF_.TriggeredByPython Then
+ vArgs = SF_String.SplitNotQuoted(psString, cstComma, QuoteChar := &quot;&quot;&quot;&quot;)
+ For i = 0 To UBound(vArgs)
+ sSingleArg = vArgs(i)
+ vSingleArgs = Split(sSingleArg, cstEqual)
+ vSingleArgs(0) = LCase(vSingleArgs(0))
+ vArgs(i) = join(vSingleArgs, cstEqual)
+ Next i
+ sSubArgs = Join(vArgs, cstComma)
+ Else
+ sSubArgs = psString
+ End If
+
+Finally:
+ _RightCaseArgs = sSubArgs
+ Exit Function
+End Function &apos; ScriptForge.SF_Exception._RightCaseArgs
+
+REM ============================================ END OF SCRIPTFORGE.SF_EXCEPTION
+</script:module> \ No newline at end of file