<?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 behaviour of the application when an error occurs is:
&apos;&apos;&apos;			1.	Log the error in the console. This is always done
&apos;&apos;&apos;			2.	Inform the user about the error with either a standard or a localized message
&apos;&apos;&apos;				To force a silent mode, set :
&apos;&apos;&apos;					exception.ReportScriptErrors = False	&apos;	Default = True
&apos;&apos;&apos;			3.	To not stop the execution of the current macro when ScriptForge detects
&apos;&apos;&apos;				a user script error, set :
&apos;&apos;&apos;					exception.StopWhenError = False			&apos;	Default = True
&apos;&apos;&apos;				It then makes sense before further processing to explore the values of
&apos;&apos;&apos;					exception.ReturnCode					&apos;	Short error description
&apos;&apos;&apos;					exception.ReturnCodeDescription			&apos;	Long error description
&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;
Const FILESYSTEMERROR			=	&quot;FILESYSTEMERROR&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_SHAPE
Const DUPLICATESHAPEERROR		=	&quot;DUPLICATESHAPEERROR&quot;
Const SHAPEEXPORTERROR			=	&quot;SHAPEEXPORTERROR&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_Writer
Const WRITERRANGEERROR			=	&quot;WRITERRANGEERROR&quot;

&apos;	SF_Dialog
Const DIALOGNOTFOUNDERROR		=	&quot;DIALOGNOTFOUNDERROR&quot;
Const DIALOGDEADERROR			=	&quot;DIALOGDEADERROR&quot;
Const CONTROLTYPEERROR			=	&quot;CONTROLTYPEERROR&quot;
Const TEXTFIELDERROR			=	&quot;TEXTFIELDERROR&quot;
Const PAGEMANAGERERROR			=	&quot;PAGEMANAGERERROR&quot;
Const DUPLICATECONTROLERROR		=	&quot;DUPLICATECONTROLERROR&quot;

&apos;	SF_Database
Const DBREADONLYERROR			=	&quot;DBREADONLYERROR&quot;
Const SQLSYNTAXERROR			=	&quot;SQLSYNTAXERROR&quot;
Const SQLSYNTAX2ERROR			=	&quot;SQLSYNTAX2ERROR&quot;
Const NOCURRENTRECORDERROR		=	&quot;NOCURRENTRECORDERROR&quot;
Const RECORDUPDATEERROR			=	&quot;RECORDUPDATEERROR&quot;
Const FIELDEXPORTERROR			=	&quot;FIELDEXPORTERROR&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 ReportScriptErrors() As Variant
&apos;&apos;&apos;	Indicates whether script errors are displayed in a message box when they occur
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.ReportScriptErrors
	ReportScriptErrors = _PropertyGet(&quot;ReportScriptErrors&quot;)
End Property	&apos;	ScriptForge.SF_Exception.ReportScriptErrors (get)

REM -----------------------------------------------------------------------------
Property Let ReportScriptErrors(ByVal pvReportScriptErrors As Variant)
&apos;&apos;&apos;	When set to False, an error occur silently. Useful f.i. in Calc user-defined functions.
&apos;&apos;&apos;	The set value is preserved until it is explicitly set again.
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.ReportScriptErrors = False
	_PropertySet &quot;ReportScriptErrors&quot;, pvReportScriptErrors
End Property	&apos;	ScriptForge.SF_Exception.ReportScriptErrors (let)

REM -----------------------------------------------------------------------------
Property Get ReturnCode() As String
&apos;&apos;&apos;	Returns the code returned by  the last call to the ScriptForge API from a user script.
&apos;&apos;&apos;	It is the zero-length string if everything ran without error
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.ReturnCode
	ReturnCode = _PropertyGet(&quot;ReturnCode&quot;)
End Property	&apos;	ScriptForge.SF_Exception.ReturnCode (get)

REM -----------------------------------------------------------------------------
Property Get ReturnCodeDescription() As String
&apos;&apos;&apos;	Returns the localized description of the code returned by  the last call to the ScriptForge API from a user script.
&apos;&apos;&apos;	It is the zero-length string if everything ran without error
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.ReturnCodeDescription
	ReturnCodeDescription = _PropertyGet(&quot;ReturnCodeDescription&quot;)
End Property	&apos;	ScriptForge.SF_Exception.ReturnCodeDescription (get)

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 StopWhenError() As Variant
&apos;&apos;&apos;	Indicates whether the Basic process is stopped when ScriptForge detects a user script error
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.StopWhenError
	StopWhenError = _PropertyGet(&quot;StopWhenError&quot;)
End Property	&apos;	ScriptForge.SF_Exception.StopWhenError (get)

REM -----------------------------------------------------------------------------
Property Let StopWhenError(ByVal pvStopWhenError As Variant)
&apos;&apos;&apos;	When set to False, the Basic process continues when ScriptForge detects a user script error. Default = True.
&apos;&apos;&apos;	The set value is preserved until it is explicitly set again.
&apos;&apos;&apos;	Example:
&apos;&apos;&apos;		myException.StopWhenError = False
	_PropertySet &quot;StopWhenError&quot;, pvStopWhenError
End Property	&apos;	ScriptForge.SF_Exception.StopWhenError (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, clear the SF_Exception object and reinitialize the return code.
&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

	With _SF_
		.ReturnCode = &quot;&quot;
		.ReturnCodeDescription = &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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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 _CloseConsole()

		&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()
			.ConsoleDialog.Terminate()
		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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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, pbReinitRC := False) Then		&apos;	Keep return codes untouched
		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;ReportScriptErrors&quot; _
					, &quot;ReturnCode&quot; _
					, &quot;ReturnCodeDescription&quot; _
					, &quot;Source&quot; _
					, &quot;StopWhenError&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;

	&apos;	Save Err, Erl, .. values before any On Error ... statement
	SF_Exception._CaptureSystemError()
	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 _
								, Optional ByVal _Warning 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;		_Warning: When True, do not stop the process. FOR INTERNAL USE ONLY
&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 IsMissing(_Warning) Or IsEmpty(_Warning) Then _Warning = False
	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_.ReportScriptErrors 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)
	End With

Finally:
	SF_Utils._ExitFunction(cstThisSub)
	If Not _Warning Then
		SF_Exception.Clear()
		_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 = Split(&quot;ScriptForge.&quot; &amp; _SF_.MainFunction, &quot;.&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_.ReportScriptErrors 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()
	Stop		&apos;	Unconditional stop whatever the value of the StopWhenError flag
	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)

	&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(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 = Split(&quot;ScriptForge.&quot; &amp; _SF_.MainFunction, &quot;.&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, CaseSensitive, 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(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 FILESYSTEMERROR		&apos;	SF_FileSystem.---(ArgName, MethodName, ArgValue)
				pvArgs(0) = _RightCase(pvArgs(0))
				sMessage = sLocation _
					&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;FILESYSTEM&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
			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(Left(pvArgs(0), 5) = &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 DUPLICATESHAPEERROR	&apos;	SF_Calc.CreateShapeFromFile(shape, ShapeName, 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;DUPLICATESHAPE&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 SHAPEEXPORTERROR	&apos;	SF_Shape.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;SHAPEEXPORT&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 WRITERRANGEERROR		&apos;	SF_Writer._ParseRange(TextRange, &quot;TextRange&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;WRITERRANGE&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 PAGEMANAGERERROR	&apos;	SF_Dialog.SetPageManager(PilotsList, TabsList, WizardsList)
				sMessage = sLocation _
					&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;PAGEMANAGER&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3), pvArgs(4), pvArgs(5))
			Case DUPLICATECONTROLERROR	&apos;	SF_Dialog.CreateControl(ControlName, DialogName)
				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;DUPLICATECONTROL&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
			Case DBREADONLYERROR	&apos;	SF_Database.RunSql(), SF_Dataset.Delete(), Insert(), Update()
				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 SQLSYNTAX2ERROR	&apos;	SF_Dataset.Reload/_Initialize(SQL, Filter, OrderBy)
				sMessage = sLocation _
					&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;SQLSYNTAX2&quot;, pvArgs(0), pvArgs(1), pvArgs(2))
			Case NOCURRENTRECORDERROR	&apos;	SF_Dataset.Insert/Update/GetValue/Delete
				sMessage = sLocation _
					&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;NOCURRENTRECORD&quot;)
			Case RECORDUPDATEERROR	&apos;	SF_Dataset.Insert/Update(FieldName, FieldValue, FieldType)
				sMessage = sLocation _
					&amp; &quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;RECORDUPDATE&quot;, pvArgs(0), pvArgs(1), pvARgs(2))
			Case FIELDEXPORTERROR	&apos;	SF_Dataset.ExportFieldToFile(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;FIELDEXPORT&quot;, pvArgs(0), pvArgs(1), pvArgs(2), pvArgs(3))
			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_.ReportScriptErrors 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)
	With _SF_
		._StackReset()
		If .StopWhenError Then Stop
		.ReturnCode = ErrorCode
		.ReturnCodeDescription = sMessage			
	End With
	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;)

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:
	SF_Exception.Raise(Number, Source, Description, _Warning := True)

Finally:
	SF_Utils._ExitFunction(cstThisSub)
	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
				.ConsoleDialog.Terminate()
				Set .ConsoleControl = Nothing
				Set .ConsoleDialog = Nothing
			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 loaded for the first time 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
			If Not IsNull(.ConsoleControl) Then 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;ReportScriptErrors&quot;
			_PropertyGet = _SF_.ReportScriptErrors
		Case &quot;ReturnCode&quot;
			_PropertyGet = _SF_.ReturnCode
		Case &quot;ReturnCodeDescription&quot;
			_PropertyGet = _SF_.ReturnCodeDescription
		Case &quot;Source&quot;
			If IsEmpty(_Source) Then _PropertyGet = _SysSource Else _PropertyGet = _Source
		Case &quot;StopWhenError&quot;
			_PropertyGet = _SF_.StopWhenError
		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;ReportScriptErrors&quot;
			If VarType(pvValue) = V_BOOLEAN Then _SF_.ReportScriptErrors = pvValue
		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 &quot;StopWhenError&quot;
			If VarType(pvValue) = V_BOOLEAN Then _SF_.StopWhenError = pvValue
		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>