file-online-preview/office-plugin/windows-office/share/basic/ScriptForge/SF_Exception.xba

1107 lines
53 KiB
Java
Raw Normal View History

2021-06-23 02:26:22 +00:00
<?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;&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;
&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;
&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;
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)
&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; Example:
&apos;&apos;&apos; SF_Exception.Console()
Dim bConsoleActive As Boolean &apos; When True, dialog is active
Dim sClose As String &apos; Caption of the close buttons
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 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;)
&apos; Setup labels and visibility
sClose = .Interface.GetText(&quot;CLOSEBUTTON&quot;)
Set oModalBtn = .ConsoleDialog.Controls(&quot;CloseModalButton&quot;)
Set oNonModalBtn = .ConsoleDialog.Controls(&quot;CloseNonModalButton&quot;)
If Modal Then oModalBtn.Caption = sClose Else oNonModalBtn.Caption = sClose
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 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 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 sMainSub As String &apos; Temporary storage for main function
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)
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 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 Interface
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_.Interface
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; Splitted array (library, module, method)
Dim sMessage As String &apos; Error message to log and to display
Dim L10N As Object &apos; Alias to Interface
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_.Interface
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
Set L10N = _SF_.Interface
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 vLocation As Variant &apos; Splitted array (library, module, method)
Dim sMessage As String &apos; Message to log and display
Dim L10N As Object &apos; Alias of Interface
Dim sAlt As String &apos; Alternative error messages
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_.Interface
&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;)
sLocation = L10N.GetText(&quot;VALIDATESOURCE&quot;, vLocation(0), vLocation(1), vLocation(2)) _
&amp; &quot;\n&quot; &amp; L10N.GetText(&quot;VALIDATEARGS&quot;, _SF_.MainFunctionArgs)
Else
sLocation = &quot;&quot;
End If
With L10N
Select Case UCase(ErrorCode)
Case MISSINGARGERROR &apos; SF_Utils._Validate(Name)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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;, &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)
sMessage = sLocation _
&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, &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)
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)
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 DOCUMENTERROR &apos; SF_UI.GetDocument(ArgName, WindowName)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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 DIALOGNOTFOUNDERROR &apos; SF_Dialog._NewDialog(Service, DialogName, WindowName)
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 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;)
MsgBox SF_String.ExpandTabs(SF_String.Unescape(sMessage), cstTabSize) _
, MB_OK + MB_ICONEXCLAMATION _
, L10N.GetText(&quot;ERRORNUMBER&quot;, ErrorCode)
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 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 ============================================ END OF SCRIPTFORGE.SF_EXCEPTION
</script:module>