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 ClassModule Option Private Module Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''' SF_Root ''' ======= ''' FOR INTERNAL USE ONLY ''' Singleton class holding all persistent variables shared ''' by all the modules of the ScriptForge library ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' REM ============================================================= PRIVATE MEMBERS ' Internals Private [Me] As Object Private [_Parent] As Object Private ObjectType As String ' Must be "ROOT" Private MainFunction As String ' Name of method or property called by user script Private MainFunctionArgs As String ' Syntax of method called by user script Private StackLevel As Integer ' Depth of calls between internal methods ' Error management Private ErrorHandler As Boolean ' True = error handling active, False = internal debugging Private ConsoleLines() As Variant ' Array of messages displayable in console Private ConsoleDialog As Object ' SFDialogs.Dialog object Private ConsoleControl As Object ' SFDialogs.DialogControl object Private DisplayEnabled As Boolean ' When True, display of console or error messages is allowed Private StopWhenError As Boolean ' When True, process stops after error > "WARNING" Private TriggeredByPython As Boolean ' When True, the actual user script is a Python script Private DebugMode As Boolean ' When True, log enter/exit each official Sub ' Progress and status bars Private ProgressBarDialog As Object ' SFDialogs.Dialog object Private ProgressBarText As Object ' SFDialogs.DialogControl object Private ProgressBarBar As Object ' SFDialogs.DialogControl object Private Statusbar As Object ' Services management Private ServicesList As Variant ' Dictionary of provided services ' Usual UNO services Private FunctionAccess As Object ' com.sun.star.sheet.FunctionAccess Private PathSettings As Object ' com.sun.star.util.PathSettings Private PathSubstitution As Object ' com.sun.star.util.PathSubstitution Private ScriptProvider As Object ' com.sun.star.script.provider.MasterScriptProviderFactory Private SystemShellExecute As Object ' com.sun.star.system.SystemShellExecute Private CoreReflection As Object ' com.sun.star.reflection.CoreReflection Private DispatchHelper As Object ' com.sun.star.frame.DispatchHelper Private TextSearch As Object ' com.sun.star.util.TextSearch Private SearchOptions As Object ' com.sun.star.util.SearchOptions Private SystemLocale As Object ' com.sun.star.lang.Locale Private OfficeLocale As Object ' com.sun.star.lang.Locale Private FormatLocale As Object ' com.sun.star.lang.Locale Private LocaleData As Object ' com.sun.star.i18n.LocaleData Private CalendarImpl As Object ' com.sun.star.i18n.CalendarImpl Private Number2Text As Object ' com.sun.star.linguistic2.NumberText Private PrinterServer As Object ' com.sun.star.awt.PrinterServer Private CharacterClass As Object ' com.sun.star.i18n.CharacterClassification Private FileAccess As Object ' com.sun.star.ucb.SimpleFileAccess Private FilterFactory As Object ' com.sun.star.document.FilterFactory Private FolderPicker As Object ' com.sun.star.ui.dialogs.FolderPicker Private FilePicker As Object ' com.sun.star.ui.dialogs.FilePicker Private URLTransformer As Object ' com.sun.star.util.URLTransformer Private Introspection As Object ' com.sun.star.beans.Introspection Private BrowseNodeFactory As Object ' com.sun.star.script.browse.BrowseNodeFactory Private DatabaseContext As Object ' com.sun.star.sdb.DatabaseContext Private ConfigurationProvider _ As Object ' com.sun.star.configuration.ConfigurationProvider Private PackageProvider As Object ' com.sun.star.comp.deployment.PackageInformationProvider Private MailService As Object ' com.sun.star.system.SimpleCommandMail or com.sun.star.system.SimpleSystemMail Private GraphicExportFilter As Object ' com.sun.star.drawing.GraphicExportFilter Private Toolkit As Object ' com.sun.star.awt.Toolkit ' Specific persistent services objects or properties Private FileSystemNaming As String ' If "SYS", file and folder naming is based on operating system notation Private PythonHelper As String ' File name of Python helper functions (stored in $(inst)/share/Scripts/python) Private PythonHelper2 As String ' Alternate Python helper file name for test purposes Private LocalizedInterface As Object ' ScriptForge own L10N service Private OSName As String ' WIN, LINUX, MACOS Private SFDialogs As Variant ' Persistent storage for the SFDialogs library Private SFForms As Variant ' Persistent storage for the SF_Form class in the SFDocuments library Private PythonStorage As Variant ' Persistent storage for the objects created and processed in Python Private PythonPermanent As Long ' Number of permanent entries in PythonStorage containing standard module objects REM ====================================================== CONSTRUCTOR/DESTRUCTOR REM ----------------------------------------------------------------------------- Private Sub Class_Initialize() Set [Me] = Nothing Set [_Parent] = Nothing ObjectType = "ROOT" MainFunction = "" MainFunctionArgs = "" StackLevel = 0 ErrorHandler = True ConsoleLines = Array() Set ConsoleDialog = Nothing Set ConsoleControl = Nothing DisplayEnabled = True StopWhenError = True TriggeredByPython = False DebugMode = False Set ProgressBarDialog = Nothing Set ProgressBarText = Nothing Set progressBarBar = Nothing Set Statusbar = Nothing ServicesList = Empty Set FunctionAccess = Nothing Set PathSettings = Nothing Set PathSubstitution = Nothing Set ScriptProvider = Nothing Set SystemShellExecute = Nothing Set CoreReflection = Nothing Set DispatchHelper = Nothing Set TextSearch = Nothing Set SearchOptions = Nothing Set SystemLocale = Nothing Set OfficeLocale = Nothing Set FormatLocale = Nothing Set LocaleData = Nothing Set CalendarImpl = Nothing Set Number2Text = Nothing Set PrinterServer = Nothing Set CharacterClass = Nothing Set FileAccess = Nothing Set FilterFactory = Nothing Set FolderPicker = Nothing Set FilePicker = Nothing Set URLTransformer = Nothing Set Introspection = Nothing FileSystemNaming = "ANY" PythonHelper = "ScriptForgeHelper.py" PythonHelper2 = "" Set LocalizedInterface = Nothing Set BrowseNodeFactory = Nothing Set DatabaseContext = Nothing Set ConfigurationProvider = Nothing Set PackageProvider = Nothing Set MailService = Nothing Set GraphicExportFilter = Nothing Set Toolkit = Nothing OSName = "" SFDialogs = Empty SFForms = Empty PythonStorage = Empty PythonPermanent = -1 End Sub ' ScriptForge.SF_Root Constructor REM ----------------------------------------------------------------------------- Private Sub Class_Terminate() Call Class_Initialize() End Sub ' ScriptForge.SF_Root Destructor REM ----------------------------------------------------------------------------- Public Function Dispose() As Variant Call Class_Terminate() Set Dispose = Nothing End Function ' ScriptForge.SF_Root Explicit destructor REM =========================================================== PRIVATE FUNCTIONS REM ----------------------------------------------------------------------------- Public Sub _AddToConsole(ByVal psLine As String) ''' Add a new line to the console ''' TAB characters are expanded before the insertion of the line ''' NB: Array redimensioning of a member of an object must be done in the class module ''' Args: ''' psLine: the line to add Dim lConsole As Long ' UBound of ConsoleLines Dim sLine As String ' Alias of psLine ' Resize ConsoleLines lConsole = UBound(ConsoleLines) If lConsole < 0 Then ReDim ConsoleLines(0) Else ReDim Preserve ConsoleLines(0 To lConsole + 1) End If ' Add a timestamp to the line and insert it (without date) sLine = Mid(SF_Utils._Repr(Now()), 12) & " -> " & psLine ConsoleLines(lConsole + 1) = sLine ' Add the new line to the actual (probably non-modal) console, if active If Not IsNull(ConsoleDialog) Then If ConsoleDialog._IsStillAlive(False) Then ' False to not raise an error If IsNull(ConsoleControl) Then Set ConsoleControl = ConsoleDialog.Controls(SF_Exception.CONSOLENAME) ' Should not happen ... ConsoleControl.WriteLine(sLine) End If End If End Sub ' ScriptForge.SF_Root._AddToConsole REM ----------------------------------------------------------------------------- Public Function _AddToPythonStorage(ByRef poObject As Object) As Long ''' Insert a newly created object in the Python persistent storage ''' and return the index of the used entry ''' The persistent storage is a simple array of objects ''' Args: ''' poObject: the object to insert Dim lIndex As Long ' Return value Dim lSize As Long ' UBound of the persistent storage Dim i As Long Check: lIndex = -1 If IsNull(poObject) Then Exit Function On Local Error GoTo Finally lSize = UBound(PythonStorage) Try: ' Can an empty entry be reused ? For i = PythonPermanent + 1 To lSize If IsNull(PythonStorage(i)) Then lIndex = i Exit For End If Next i ' Resize Python storage if no empty space If lIndex < 0 Then lSize = lSize + 1 ReDim Preserve PythonStorage(0 To lSize) lIndex = lSize End If ' Insert new object Set PythonStorage(lIndex) = poObject Finally: _AddToPythonStorage = lIndex Exit Function End Function ' ScriptForge.SF_Root._AddToPythonStorage REM ------------------------------------------------------------------------------ Public Function _GetLocalizedInterface() As Object ''' Returns the LN object instance related to the ScriptForge internal localization ''' If not yet done, load it from the shipped po files ''' Makes that the localized user interface is loaded only when needed Try: If IsNull(LocalizedInterface) Then _LoadLocalizedInterface() Finally: Set _GetLocalizedInterface = LocalizedInterface Exit Function End Function ' ScriptForge.SF_Root._GetLocalizedInterface REM ----------------------------------------------------------------------------- Public Sub _InitPythonStorage() ''' Make PythonStorage an array ''' In prevision to an abundant use of those objects in Python, hardcode to optimize the performance and memory : ''' Initialize the first entries with the standard module objects located in the ScriptForge library Try: If Not IsArray(PythonStorage) Then PythonPermanent = 8 PythonStorage = Array() ReDim PythonStorage(0 To PythonPermanent) ' Initialize each entry PythonStorage(0) = ScriptForge.SF_Array PythonStorage(1) = ScriptForge.SF_Exception PythonStorage(2) = ScriptForge.SF_FileSystem PythonStorage(3) = ScriptForge.SF_Platform PythonStorage(4) = ScriptForge.SF_Region PythonStorage(5) = ScriptForge.SF_Services PythonStorage(6) = ScriptForge.SF_Session PythonStorage(7) = ScriptForge.SF_String PythonStorage(8) = ScriptForge.SF_UI End If Finally: Exit Sub End Sub ' ScriptForge.SF_Root._InitPythonStorage REM ----------------------------------------------------------------------------- Public Sub _LoadLocalizedInterface(Optional ByVal psMode As String) ''' Build the user interface in a persistent L10N object ''' Executed - only once - at first request of a label inside the LocalizedInterface dictionary ''' Args: ''' psMode: ADDTEXT => the (english) labels are loaded from code below ''' POFILE => the localized labels are loaded from a PO file ''' the name of the file is "la.po" where la = language part of locale ''' (fallback to ADDTEXT mode if file does not exist) Dim sInstallFolder As String ' ScriptForge installation directory Dim sPOFolder As String ' Folder containing the PO files Dim sPOFile As String ' PO File to load Dim sLocale As String ' Locale If ErrorHandler Then On Local Error GoTo Catch Try: 'TODO: Modify default value If IsMissing(psMode) Then psMode = "POFILE" If psMode = "POFILE" Then ' Use this mode in production ' Build the po file name With SF_FileSystem sInstallFolder = ._SFInstallFolder() ' ScriptForge installation folder sLocale = SF_Utils._GetUNOService("OfficeLocale").Language sPOFolder = .BuildPath(sInstallFolder, "po") sPOFile = .BuildPath(sPOFolder, sLocale & ".po") If sLocale = "en" Then ' LocalizedInterface loaded by code i.o. read from po file psMode = "ADDTEXT" ElseIf Not .FileExists(sPOFile) Then ' File not found => load texts from code below psMode = "ADDTEXT" Else Set LocalizedInterface = CreateScriptService("L10N", sPOFolder, sLocale) End If End With End If If psMode = "ADDTEXT" Then ' Use this mode in development to prepare a new POT file Set LocalizedInterface = CreateScriptService("L10N") With LocalizedInterface ' SF_Exception.Raise .AddText( Context := "ERRORNUMBER" _ , MsgId := "Error %1" _ , Comment := "Title in error message box\n" _ & "%1: an error number" _ ) .AddText( Context := "ERRORLOCATION" _ , MsgId := "Location : %1" _ , Comment := "Error message box\n" _ & "%1: a line number" _ ) .AddText( Context := "LONGERRORDESC" _ , MsgId := "Error %1 - Location = %2 - Description = %3" _ , Comment := "Logfile record" _ ) .AddText( Context := "STOPEXECUTION" _ , MsgId := "THE EXECUTION IS CANCELLED." _ , Comment := "Any blocking error message" _ ) .AddText( Context := "NEEDMOREHELP" _ , MsgId := "Do you want to receive more information about the '%1' method ?" _ , Comment := "Any blocking error message\n" _ & "%1: a method name" _ ) ' SF_Exception.RaiseAbort .AddText( Context := "INTERNALERROR" _ , MsgId := "The ScriptForge library has crashed. The reason is unknown.\n" _ & "Maybe a bug that could be reported on\n" _ & "\thttps://bugs.documentfoundation.org/\n\n" _ & "More details : \n\n" _ , Comment := "SF_Exception.RaiseAbort error message" _ ) ' SF_Utils._Validate .AddText( Context := "VALIDATESOURCE" _ , MsgId := "Library : \t%1\nService : \t%2\nMethod : \t%3" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: probably ScriptForge\n" _ & "%2: service or module name\n" _ & "%3: property or method name where the error occurred" _ ) .AddText( Context := "VALIDATEARGS" _ , MsgId := "Arguments: %1" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: list of arguments of the method" _ ) .AddText( Context := "VALIDATEERROR" _ , MsgId := "A serious error has been detected in your code on argument : « %1 »." _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name" _ ) .AddText( Context := "VALIDATIONRULES" _ , MsgId := "\tValidation rules :", Comment := "SF_Utils.Validate error message" _ ) .AddText( Context := "VALIDATETYPES" _ , MsgId := "\t\t« %1 » must have next type (or one of next types) : %2" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name\n" _ & "%2: Comma separated list of allowed types" _ ) .AddText( Context := "VALIDATEVALUES" _ , MsgId := "\t\t« %1 » must contain one of next values : %2" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name\n" _ & "%2: Comma separated list of allowed values" _ ) .AddText( Context := "VALIDATEREGEX" _ , MsgId := "\t\t« %1 » must match next regular expression : %2" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name\n" _ & "%2: A regular expression" _ ) .AddText( Context := "VALIDATECLASS" _ , MsgId := "\t\t« %1 » must be a Basic object of class : %2" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name\n" _ & "%2: The name of a Basic class" _ ) .AddText( Context := "VALIDATEACTUAL" _ , MsgId := "The actual value of « %1 » is : '%2'" _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name\n" _ & "%2: The value of the argument as a string" _ ) .AddText( Context := "VALIDATEMISSING" _ , MsgId := "The « %1 » argument is mandatory, yet it is missing." _ , Comment := "SF_Utils._Validate error message\n" _ & "%1: Wrong argument name" _ ) ' SF_Utils._ValidateArray .AddText( Context := "VALIDATEARRAY" _ , MsgId := "\t\t« %1 » must be an array." _ , Comment := "SF_Utils._ValidateArray error message\n" _ & "%1: Wrong argument name" _ ) .AddText( Context := "VALIDATEDIMS" _ , MsgId := "\t\t« %1 » must have exactly %2 dimension(s)." _ , Comment := "SF_Utils._ValidateArray error message\n" _ & "%1: Wrong argument name\n" _ & "%2: Number of dimensions of the array" _ ) .AddText( Context := "VALIDATEALLTYPES" _ , MsgId := "\t\t« %1 » must have all elements of the same type : %2" _ , Comment := "SF_Utils._ValidateArray error message\n" _ & "%1: Wrong argument name\n" _ & "%2: Either one single type or 'String, Date, Numeric'" _ ) .AddText( Context := "VALIDATENOTNULL" _ , MsgId := "\t\t« %1 » must not contain any NULL or EMPTY elements." _ , Comment := "SF_Utils._ValidateArray error message\n" _ & "%1: Wrong argument name\n" _ & "NULL and EMPTY should not be translated" _ ) ' SF_Utils._ValidateFile .AddText( Context := "VALIDATEFILE" _ , MsgId := "\t\t« %1 » must be of type String." _ , Comment := "SF_Utils._ValidateFile error message\n" _ & "%1: Wrong argument name\n" _ & "'String' should not be translated" _ ) .AddText( Context := "VALIDATEFILESYS" _ , MsgId := "\t\t« %1 » must be a valid file or folder name expressed in the operating system native notation." _ , Comment := "SF_Utils._ValidateFile error message\n" _ & "%1: Wrong argument name" _ ) .AddText( Context := "VALIDATEFILEURL" _ , MsgId := "\t\t« %1 » must be a valid file or folder name expressed in the portable URL notation." _ , Comment := "SF_Utils._ValidateFile error message\n" _ & "%1: Wrong argument name\n" _ & "'URL' should not be translated" _ ) .AddText( Context := "VALIDATEFILEANY" _ , MsgId := "\t\t« %1 » must be a valid file or folder name." _ , Comment := "SF_Utils._ValidateFile error message\n" _ & "%1: Wrong argument name" _ ) .AddText( Context := "VALIDATEWILDCARD" _ , MsgId := "\t\t« %1 » may contain one or more wildcard characters (?, *) in its last path component only." _ , Comment := "SF_Utils._ValidateFile error message\n" _ & "%1: Wrong argument name\n" _ & "'(?, *)' is to be left as is" _ ) ' SF_Array.RangeInit .AddText( Context := "ARRAYSEQUENCE" _ , MsgId := "The respective values of 'From', 'UpTo' and 'ByStep' are incoherent.\n\n" _ & "\t« From » = %1\n" _ & "\t« UpTo » = %2\n" _ & "\t« ByStep » = %3" _ , Comment := "SF_Array.RangeInit error message\n" _ & "%1, %2, %3: Numeric values\n" _ & "'From', 'UpTo', 'ByStep' should not be translated" _ ) ' SF_Array.AppendColumn, AppendRow, PrependColumn, PrependRow .AddText( Context := "ARRAYINSERT" _ , MsgId := "The array and the vector to insert have incompatible sizes.\n\n" _ & "\t« Array_2D » = %2\n" _ & "\t« %1 » = %3" _ , Comment := "SF_Array.AppendColumn (...) error message\n" _ & "%1: 'Column' or 'Row' of a matrix\n" _ & "%2, %3: array contents\n" _ & "'Array_2D' should not be translated" _ ) ' SF_Array.ExtractColumn, ExtractRow .AddText( Context := "ARRAYINDEX1" _ , MsgId := "The given index does not fit within the bounds of the array.\n\n" _ & "\t« Array_2D » = %2\n" _ & "\t« %1 » = %3" _ , Comment := "SF_Array.ExtractColumn (...) error message\n" _ & "%1: 'Column' or 'Row' of a matrix\n" _ & "%2, %3: array contents\n" _ & "'Array_2D' should not be translated" _ ) ' SF_Array.ExtractColumn, ExtractRow .AddText( Context := "ARRAYINDEX2" _ , MsgId := "The given slice limits do not fit within the bounds of the array.\n\n" _ & "\t« Array_1D » = %1\n" _ & "\t« From » = %2\n" _ & "\t« UpTo » = %3" _ , Comment := "SF_Array.ExtractColumn (...) error message\n" _ & "%1: 'Column' or 'Row' of a matrix\n" _ & "%2, %3: array contents\n" _ & "'Array_1D', 'From' and 'UpTo' should not be translated" _ ) ' SF_Array.ImportFromCSVFile .AddText( Context := "CSVPARSING" _ , MsgId := "The given file could not be parsed as a valid CSV file.\n\n" _ & "\t« File name » = %1\n" _ & "\tLine number = %2\n" _ & "\tContent = %3" _ , Comment := "SF_Array.ImportFromCSVFile error message\n" _ & "%1: a file name\n" _ & "%2: numeric\n" _ & "%3: a long string" _ ) ' SF_Dictionary.Add/ReplaceKey .AddText( Context := "DUPLICATEKEY" _ , MsgId := "The insertion of a new key " _ & "into a dictionary failed because the key already exists.\n" _ & "Note that the comparison between keys is NOT case-sensitive.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_Dictionary Add/ReplaceKey error message\n" _ & "%1: An identifier" _ & "%2: a (potentially long) string" _ ) ' SF_Dictionary.Remove/ReplaceKey/ReplaceItem .AddText( Context := "UNKNOWNKEY" _ , MsgId := "The requested key does not exist in the dictionary.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_Dictionary Remove/ReplaceKey/ReplaceItem error message\n" _ & "%1: An identifier" _ & "%2: a (potentially long) string" _ ) ' SF_Dictionary.Add/ReplaceKey .AddText( Context := "INVALIDKEY" _ , MsgId := "The insertion or the update of an entry " _ & "into a dictionary failed because the given key contains only spaces." _ , Comment := "SF_Dictionary Add/ReplaceKey error message\n" _ ) ' SF_FileSystem.CopyFile/MoveFile/DeleteFile/CreateScriptService("L10N") .AddText( Context := "UNKNOWNFILE" _ , MsgId := "The given file could not be found on your system.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A file name" _ ) ' SF_FileSystem.CopyFolder/MoveFolder/DeleteFolder/Files/SubFolders .AddText( Context := "UNKNOWNFOLDER" _ , MsgId := "The given folder could not be found on your system.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A folder name" _ ) ' SF_FileSystem.CopyFile/MoveFolder/DeleteFile .AddText( Context := "NOTAFILE" _ , MsgId := "« %1 » contains the name of an existing folder, not that of a file.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A file name" _ ) ' SF_FileSystem.CopyFolder/MoveFolder/DeleteFolder/Files/SubFolders .AddText( Context := "NOTAFOLDER" _ , MsgId := "« %1 » contains the name of an existing file, not that of a folder.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A folder name" _ ) ' SF_FileSystem.Copy+Move/File+Folder/CreateTextFile/OpenTextFile .AddText( Context := "OVERWRITE" _ , MsgId := "You tried to create a new file which already exists. Overwriting it has been rejected.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/... error message\n" _ & "%1: An identifier\n" _ & "%2: A file name" _ ) ' SF_FileSystem.Copy+Move+Delete/File+Folder .AddText( Context := "READONLY" _ , MsgId := "Copying or moving a file to a destination which has its read-only attribute set, or deleting such a file or folder is forbidden.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A file name" _ ) ' SF_FileSystem.Copy+Move+Delete/File+Folder .AddText( Context := "NOFILEMATCH" _ , MsgId := "When « %1 » contains wildcards. at least one file or folder must match the given filter. Otherwise the operation is rejected.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem copy/move/delete error message\n" _ & "%1: An identifier\n" _ & "%2: A file or folder name with wildcards" _ ) ' SF_FileSystem.CreateFolder .AddText( Context := "FOLDERCREATION" _ , MsgId := "« %1 » contains the name of an existing file or an existing folder. The operation is rejected.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_FileSystem CreateFolder error message\n" _ & "%1: An identifier\n" _ & "%2: A file or folder name" _ ) ' SF_Services.CreateScriptService .AddText( Context := "UNKNOWNSERVICE" _ , MsgId := "No service named '%4' has been registered for the library '%3'.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_Services.CreateScriptService error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: A Basic library name\n" _ & "%4: A service (1 word) name" _ ) ' SF_Services.CreateScriptService .AddText( Context := "SERVICESNOTLOADED" _ , MsgId := "The library '%3' and its services could not been loaded.\n" _ & "The reason is unknown.\n" _ & "However, checking the '%3.SF_Services.RegisterScriptServices()' function and its return value can be a good starting point.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_Services.CreateScriptService error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: A Basic library name" _ ) ' SF_Session.ExecuteCalcFunction .AddText( Context := "CALCFUNC" _ , MsgId := "The Calc '%1' function encountered an error. Either the given function does not exist or its arguments are invalid." _ , Comment := "SF_Session.ExecuteCalcFunction error message\n" _ & "'Calc' should not be translated" _ ) ' SF_Session._GetScript .AddText( Context := "NOSCRIPT" _ , MsgId := "The requested %1 script could not be located in the given libraries and modules.\n" _ & "« %2 » = %3\n" _ & "« %4 » = %5" _ , Comment := "SF_Session._GetScript error message\n" _ & "%1: 'Basic' or 'Python'\n" _ & "%2: An identifier\n" _ & "%3: A string\n" _ & "%4: An identifier\n" _ & "%5: A string" _ ) ' SF_Session.ExecuteBasicScript .AddText( Context := "SCRIPTEXEC" _ , MsgId := "An exception occurred during the execution of the Basic script.\n" _ & "Cause: %3\n" _ & "« %1 » = %2" _ , Comment := "SF_Session.ExecuteBasicScript error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: A (long) string" _ ) ' SF_Session.SendMail .AddText( Context := "WRONGEMAIL" _ , MsgId := "One of the email addresses has been found invalid.\n" _ & "Invalid mail = « %1 »" _ , Comment := "SF_Session.SendMail error message\n" _ & "%1 = a mail address" _ ) ' SF_Session.SendMail .AddText( Context := "SENDMAIL" _ , MsgId := "The message could not be sent due to a system error.\n" _ & "A possible cause is that LibreOffice could not find any mail client." _ , Comment := "SF_Session.SendMail error message" _ ) ' SF_TextStream._IsFileOpen .AddText( Context := "FILENOTOPEN" _ , MsgId := "The requested file operation could not be executed because the file was closed previously.\n\n" _ & "File name = '%1'" _ , Comment := "SF_TextStream._IsFileOpen error message\n" _ & "%1: A file name" _ ) ' SF_TextStream._IsFileOpen .AddText( Context := "FILEOPENMODE" _ , MsgId := "The requested file operation could not be executed because it is incompatible with the mode in which the file was opened.\n\n" _ & "File name = '%1'\n" _ & "Open mode = %2" _ , Comment := "SF_TextStream._IsFileOpen error message\n" _ & "%1: A file name\n" _ & "%2: READ, WRITE or APPEND" _ ) ' SF_TextStream.ReadLine, ReadAll, SkipLine .AddText( Context := "ENDOFFILE" _ , MsgId := "The requested file read operation could not be completed because an unexpected end-of-file was encountered.\n\n" _ & "File name = '%1'" _ , Comment := "SF_TextStream.ReadLine/ReadAll/SkipLine error message\n" _ & "%1: A file name" _ ) ' SF_UI.Document .AddText( Context := "DOCUMENT" _ , MsgId := "The requested document could not be found.\n\n" _ & "%1 = '%2'" _ , Comment := "SF_UI.GetDocument error message\n" _ & "%1: An identifier\n" _ & "%2: A string" _ ) ' SF_UI.Create .AddText( Context := "DOCUMENTCREATION" _ , MsgId := "The creation of a new document failed.\n" _ & "Something must be wrong with some arguments.\n\n" _ & "Either the document type is unknown, or no template file was given,\n" _ & "or the given template file was not found on your system.\n\n" _ & "%1 = '%2'\n" _ & "%3 = '%4'" _ , Comment := "SF_UI.GetDocument error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A string" _ ) ' SF_UI.OpenDocument .AddText( Context := "DOCUMENTOPEN" _ , MsgId := "The opening of the document failed.\n" _ & "Something must be wrong with some arguments.\n\n" _ & "Either the file does not exist, or the password is wrong, or the given filter is invalid.\n\n" _ & "%1 = '%2'\n" _ & "%3 = '%4'\n" _ & "%5 = '%6'" _ , Comment := "SF_UI.OpenDocument error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A string\n" _ & "%5: An identifier\n" _ & "%6: A string" _ ) ' SF_UI.OpenBaseDocument .AddText( Context := "BASEDOCUMENTOPEN" _ , MsgId := "The opening of the Base document failed.\n" _ & "Something must be wrong with some arguments.\n\n" _ & "Either the file does not exist, or the file is not registered under the given name.\n\n" _ & "%1 = '%2'\n" _ & "%3 = '%4'" _ , Comment := "SF_UI.OpenDocument error message\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A string" _ ) ' SF_Document._IsStillAlive .AddText( Context := "DOCUMENTDEAD" _ , MsgId := "The requested action could not be executed because the document was closed inadvertently.\n\n" _ & "The concerned document is '%1'" _ , Comment := "SF_Document._IsStillAlive error message\n" _ & "%1: A file name" _ ) ' SF_Document.Save .AddText( Context := "DOCUMENTSAVE" _ , MsgId := "The document could not be saved.\n" _ & "Either the document has been opened read-only, or the destination file has a read-only attribute set, " _ & "or the file where to save to is undefined.\n\n" _ & "%1 = '%2'" _ , Comment := "SF_Document.SaveAs error message\n" _ & "%1: An identifier\n" _ & "%2: A file name\n" _ ) ' SF_Document.SaveAs .AddText( Context := "DOCUMENTSAVEAS" _ , MsgId := "The document could not be saved.\n" _ & "Either the document must not be overwritten, or the destination file has a read-only attribute set, " _ & "or the given filter is invalid.\n\n" _ & "%1 = '%2'\n" _ & "%3 = %4\n" _ & "%5 = '%6'" _ , Comment := "SF_Document.SaveAs error message\n" _ & "%1: An identifier\n" _ & "%2: A file name\n" _ & "%3: An identifier\n" _ & "%4: True or False\n" _ & "%5: An identifier\n" _ & "%6: A string" _ ) ' SF_Document.any update .AddText( Context := "DOCUMENTREADONLY" _ , MsgId := "You tried to edit a document which is not modifiable. The document has not been changed.\n\n" _ & "« %1 » = %2" _ , Comment := "SF_Document any update\n" _ & "%1: An identifier\n" _ & "%2: A file name" _ ) ' SF_Base.GetDatabase .AddText( Context := "DBCONNECT" _ , MsgId := "The database related to the actual Base document could not be retrieved.\n" _ & "Check the connection/login parameters.\n\n" _ & "« %1 » = '%2'\n" _ & "« %3 » = '%4'\n" _ & "« Document » = %5" _ , Comment := "SF_Base GetDatabase\n" _ & "%1: An identifier\n" _ & "%2: A user name\n" _ & "%3: An identifier\n" _ & "%4: A password\n" _ & "%5: A file name" _ ) ' SF_Calc._ParseAddress (sheet) .AddText( Context := "CALCADDRESS1" _ , MsgId := "The given address does not correspond with a valid sheet name.\n\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4" _ , Comment := "SF_Calc _ParseAddress (sheet)\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A file name" _ ) ' SF_Calc._ParseAddress (range) .AddText( Context := "CALCADDRESS2" _ , MsgId := "The given address does not correspond with a valid range of cells.\n\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4" _ , Comment := "SF_Calc _ParseAddress (range)\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A file name" _ ) ' SF_Calc.InsertSheet .AddText( Context := "DUPLICATESHEET" _ , MsgId := "There exists already in the document a sheet with the same name.\n\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4" _ , Comment := "SF_Calc InsertSheet\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A file name" _ ) ' SF_Calc.Offset .AddText( Context := "OFFSETADDRESS" _ , MsgId := "The computed range falls beyond the sheet boundaries or is meaningless.\n\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4\n" _ & "« %5 » = %6\n" _ & "« %7 » = %8\n" _ & "« %9 » = %10\n" _ & "« %11 » = %12" _ , Comment := "SF_Calc Offset\n" _ & "%1: An identifier\n" _ & "%2: A Calc reference\n" _ & "%3: An identifier\n" _ & "%4: A number\n" _ & "%5: An identifier\n" _ & "%6: A number\n" _ & "%7: An identifier\n" _ & "%8: A number\n" _ & "%9: An identifier\n" _ & "%10: A number\n" _ & "%11: An identifier\n" _ & "%12: A file name" _ ) ' SF_Calc.CreateChart .AddText( Context := "DUPLICATECHART" _ , MsgId := "A chart with the same name exists already in the sheet.\n\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4\n" _ & "« %5 » = %6\n" _ , Comment := "SF_Calc CreateChart\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A string\n" _ & "%5: An identifier\n" _ & "%6: A file name" _ ) ' SF_Calc.ExportRangeToFile .AddText( Context := "RANGEEXPORT" _ , MsgId := "The given range could not be exported.\n" _ & "Either the destination file must not be overwritten, or it has a read-only attribute set.\n\n" _ & "%1 = '%2'\n" _ & "%3 = %4" _ , Comment := "SF_Calc.ExportRangeToFile error message\n" _ & "%1: An identifier\n" _ & "%2: A file name\n" _ & "%3: An identifier\n" _ & "%4: True or False\n" _ ) ' SF_Chart.ExportToFile .AddText( Context := "CHARTEXPORT" _ , MsgId := "The chart could not be exported.\n" _ & "Either the destination file must not be overwritten, or it has a read-only attribute set.\n\n" _ & "%1 = '%2'\n" _ & "%3 = %4" _ , Comment := "SF_Chart.ExportToFile error message\n" _ & "%1: An identifier\n" _ & "%2: A file name\n" _ & "%3: An identifier\n" _ & "%4: True or False\n" _ ) ' SF_Form._IsStillAlive .AddText( Context := "FORMDEAD" _ , MsgId := "The requested action could not be executed because the form is not open or the document was closed inadvertently.\n\n" _ & "The concerned form is '%1' in document '%2'." _ , Comment := "SF_Dialog._IsStillAlive error message\n" _ & "%1: An identifier" _ & "%2: A file name" _ ) ' SF_Calc.Forms .AddText( Context := "CALCFORMNOTFOUND" _ , MsgId := "The requested form could not be found in the Calc sheet. The given index is off-limits.\n\n" _ & "The concerned Calc document is '%3'.\n\n" _ & "The name of the sheet = '%2'\n" _ & "The index = %1." _ , Comment := "SF_Form determination\n" _ & "%1: A number\n" _ & "%2: A sheet name\n" _ & "%3: A file name" _ ) ' SF_Document.Forms .AddText( Context := "WRITERFORMNOTFOUND" _ , MsgId := "The requested form could not be found in the Writer document. The given index is off-limits.\n\n" _ & "The concerned Writer document is '%2'.\n\n" _ & "The index = %1." _ , Comment := "SF_Form determination\n" _ & "%1: A number\n" _ & "%2: A file name" _ ) ' SF_Base.Forms .AddText( Context := "BASEFORMNOTFOUND" _ , MsgId := "The requested form could not be found in the form document '%2'. The given index is off-limits.\n\n" _ & "The concerned Base document is '%3'.\n\n" _ & "The index = %1." _ , Comment := "SF_Form determination\n" _ & "%1: A number\n" _ & "%2: A string\n" _ & "%3: A file name" _ ) ' SF_Form.Subforms .AddText( Context := "SUBFORMNOTFOUND" _ , MsgId := "The requested subform could not be found below the given main form.\n\n" _ & "The main form = '%2'.\n" _ & "The subform = '%1'." _ , Comment := "SF_Form determination\n" _ & "%1: A form name\n" _ & "%2: A form name" _ ) ' SF_FormControl._SetProperty .AddText( Context := "FORMCONTROLTYPE" _ , MsgId := "The control '%1' in form '%2' is of type '%3'.\n" _ & "The property or method '%4' is not applicable on that type of form controls." _ , Comment := "SF_FormControl property setting\n" _ & "%1: An identifier\n" _ & "%2: An identifier\n" _ & "%3: A string\n" _ & "%4: An identifier" _ ) ' SF_Dialog._NewDialog .AddText( Context := "DIALOGNOTFOUND" _ , MsgId := "The requested dialog could not be located in the given container or library.\n" _ & "« %1 » = %2\n" _ & "« %3 » = %4\n" _ & "« %5 » = %6\n" _ & "« %7 » = %8" _ , Comment := "SF_Dialog creation\n" _ & "%1: An identifier\n" _ & "%2: A string\n" _ & "%3: An identifier\n" _ & "%4: A file name\n" _ & "%5: An identifier\n" _ & "%6: A string\n" _ & "%7: An identifier\n" _ & "%8: A string" _ ) ' SF_Dialog._IsStillAlive .AddText( Context := "DIALOGDEAD" _ , MsgId := "The requested action could not be executed because the dialog was closed inadvertently.\n\n" _ & "The concerned dialog is '%1'." _ , Comment := "SF_Dialog._IsStillAlive error message\n" _ & "%1: An identifier" _ ) ' SF_DialogControl._SetProperty .AddText( Context := "CONTROLTYPE" _ , MsgId := "The control '%1' in dialog '%2' is of type '%3'.\n" _ & "The property or method '%4' is not applicable on that type of dialog controls." _ , Comment := "SF_DialogControl property setting\n" _ & "%1: An identifier\n" _ & "%2: An identifier\n" _ & "%3: A string\n" _ & "%4: An identifier" _ ) ' SF_DialogControl.WriteLine .AddText( Context := "TEXTFIELD" _ , MsgId := "The control '%1' in dialog '%2' is not a multiline text field.\n" _ & "The requested method could not be executed." _ , Comment := "SF_DialogControl add line in textbox\n" _ & "%1: An identifier\n" _ & "%2: An identifier" _ ) ' SF_Database.RunSql .AddText( Context := "DBREADONLY" _ , MsgId := "The database has been opened in read-only mode.\n" _ & "The '%1' method must not be executed in this context." _ , Comment := "SF_Database when running update SQL statement\n" _ & "%1: The concerned method" _ ) ' SF_Database._ExecuteSql .AddText( Context := "SQLSYNTAX" _ , MsgId := "An SQL statement could not be interpreted or executed by the database system.\n" _ & "Check its syntax, table and/or field names, ...\n\n" _ & "SQL Statement : « %1 »" _ , Comment := "SF_Database can't interpret SQL statement\n" _ & "%1: The statement" _ ) ' SF_Exception.PythonShell (Python only) .AddText( Context := "PYTHONSHELL" _ , MsgId := "The APSO extension could not be located in your LibreOffice installation." _ , Comment := "SF_Exception.PythonShell error message" _ & "APSO: to leave unchanged" _ ) ' SFUnitTests._NewUnitTest .AddText( Context := "UNITTESTLIBRARY" _ , MsgId := "The requested library could not be located.\n" _ & "The UnitTest service has not been initialized.\n\n" _ & "Library name : « %1 »" _ , Comment := "SFUnitTest could not locate the library gven as argument\n" _ & "%1: The name of the library" _ ) ' SFUnitTests.SF_UnitTest .AddText( Context := "UNITTESTMETHOD" _ , MsgId := "The method '%1' is unexpected in the current context.\n" _ & "The UnitTest service cannot proceed further with the on-going test." _ , Comment := "SFUnitTest finds a RunTest() call in a inappropriate location\n" _ & "%1: The name of a method" _ ) End With End If Finally: Exit Sub Catch: GoTo Finally End Sub ' ScriptForge.SF_Root._LoadLocalizedInterface REM ----------------------------------------------------------------------------- Public Function _Repr() As String ''' Convert the unique SF_Root instance to a readable string, typically for debugging purposes (DebugPrint ...) ''' Args: ''' Return: ''' "[Root] (MainFunction: xxx, Console: yyy lines, ServicesList)" Dim sRoot As String ' Return value Const cstRoot = "[Root] (" sRoot = cstRoot & "MainFunction: " & MainFunction & ", Console: " & UBound(ConsoleLines) + 1 & " lines" _ & ", Libraries:" & SF_Utils._Repr(ServicesList.Keys) _ & ")" _Repr = sRoot End Function ' ScriptForge.SF_Root._Repr REM ----------------------------------------------------------------------------- Public Sub _StackReset() ''' Reset private members after a fatal/abort error to leave ''' a stable persistent storage after an unwanted interrupt MainFunction = "" MainFunctionArgs = "" StackLevel = 0 TriggeredByPython = False End Sub ' ScriptForge.SF_Root._StackReset REM ================================================== END OF SCRIPTFORGE.SF_ROOT