From 88a67c50af61fa9ee5fa677589ce5db2039d6f2e Mon Sep 17 00:00:00 2001 From: Jean-Pierre Ledure Date: Thu, 5 Jan 2023 13:47:01 +0100 Subject: [PATCH] ScriptForge - (SFDocuments) new FormDocument service The SF_FormDocument service is focused on : - The orchestration of Base form documents (aka Base Forms, but this is confusing) and the identification of and the access to their controls. - Form documents are always contained in a Base document. A form document may be opened either: - via code or user interface from the Base file welcome page - via code only, without having its Base container opened first In any mode, a form document can be opened only in 1 single copy. The FormDocument service is triggered either by base.OpenFormDocument(...) database.OpenFormDocument(...) ' Base file may be closed ui.GetDocument(...) Specific methods: CloseDocument() Forms() GetDatabase() PrintOut() Next methods are inherited from the Document superclass: Activate() CreateMenu(), RemoveMenu() ExportAsPdf() RunCommand() SaveCopyAs() SetPrinter() As a consequence, next methods remain available but should be declared as deprecated in the help: base.CloseFormDocument() base.Forms() base.PrintOut() base.SetPrinter() Above changes have several more minor impacts : - beside IsCalc, IsWriter, ... , a new IsFormDocument property - the UI service identifies open form documents - a new service means a new entry to register in the Services catalog - management of form events has been reviewed - the connection between Base, FormDocument, Form and Database services is reinforced - menus were available on components, now also on sub-components The new service is available for both Basic and Python user scripts. It requires in the help - a new sf_formdocument page - a review of the sf_base, sf_database, sf_form, sf_ui pages Change-Id: Ib06d1c4565ca093af2f068fa5b8082082641752e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145080 Tested-by: Jean-Pierre Ledure Reviewed-by: Jean-Pierre Ledure Tested-by: Jenkins --- wizards/Package_sfdocuments.mk | 1 + .../source/scriptforge/SF_PythonHelper.xba | 2 + wizards/source/scriptforge/SF_Services.xba | 2 +- wizards/source/scriptforge/SF_UI.xba | 2 + .../source/scriptforge/python/scriptforge.py | 67 +- wizards/source/sfdatabases/SF_Database.xba | 91 +++ wizards/source/sfdocuments/SF_Base.xba | 36 +- wizards/source/sfdocuments/SF_Calc.xba | 6 + wizards/source/sfdocuments/SF_Document.xba | 16 +- wizards/source/sfdocuments/SF_Form.xba | 75 +- wizards/source/sfdocuments/SF_FormControl.xba | 5 +- .../source/sfdocuments/SF_FormDocument.xba | 642 ++++++++++++++++++ wizards/source/sfdocuments/SF_Register.xba | 8 + wizards/source/sfdocuments/SF_Writer.xba | 10 +- wizards/source/sfdocuments/script.xlb | 1 + wizards/source/sfwidgets/SF_MenuListener.xba | 7 +- 16 files changed, 908 insertions(+), 63 deletions(-) create mode 100644 wizards/source/sfdocuments/SF_FormDocument.xba diff --git a/wizards/Package_sfdocuments.mk b/wizards/Package_sfdocuments.mk index a2a03178736a..4dcebfc84140 100644 --- a/wizards/Package_sfdocuments.mk +++ b/wizards/Package_sfdocuments.mk @@ -27,6 +27,7 @@ $(eval $(call gb_Package_add_files,wizards_basicsrvsfdocuments,$(LIBO_SHARE_FOLD SF_DocumentListener.xba \ SF_Form.xba \ SF_FormControl.xba \ + SF_FormDocument.xba \ SF_Register.xba \ SF_Writer.xba \ __License.xba \ diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba index 99d9f86c610c..ffec0af7586c 100644 --- a/wizards/source/scriptforge/SF_PythonHelper.xba +++ b/wizards/source/scriptforge/SF_PythonHelper.xba @@ -814,6 +814,8 @@ Try: End Select Case "SFDocuments.FormControl" If Script = "Controls" Then vReturn = vBasicObject.Controls(vArgs(0)) + Case "SFDocuments.FormDocument" + If Script = "Forms" Then vReturn = vBasicObject.Forms(vArgs(0)) End Select End If diff --git a/wizards/source/scriptforge/SF_Services.xba b/wizards/source/scriptforge/SF_Services.xba index b72298ea3046..8de43d389581 100644 --- a/wizards/source/scriptforge/SF_Services.xba +++ b/wizards/source/scriptforge/SF_Services.xba @@ -126,7 +126,7 @@ Try: sService = vSplit(0) ' Accept other default values for associated libraries Select Case LCase(sService) - Case "document", "calc", "writer", "base", "documentevent", "formevent" + Case "document", "calc", "writer", "base", "formdocument", "documentevent", "formevent" sLibrary = "SFDocuments" Case "dialog", "dialogevent" : sLibrary = "SFDialogs" Case "database", "datasheet" : sLibrary = "SFDatabases" diff --git a/wizards/source/scriptforge/SF_UI.xba b/wizards/source/scriptforge/SF_UI.xba index 186d88244d75..4b96ac3274fc 100644 --- a/wizards/source/scriptforge/SF_UI.xba +++ b/wizards/source/scriptforge/SF_UI.xba @@ -69,6 +69,7 @@ Const WELCOMESCREEN = "WELCOMESCREEN" Const BASEDOCUMENT = "Base" Const CALCDOCUMENT = "Calc" Const DRAWDOCUMENT = "Draw" +Const FORMDOCUMENT = "FormDocument" Const IMPRESSDOCUMENT = "Impress" Const MATHDOCUMENT = "Math" Const WRITERDOCUMENT = "Writer" @@ -1303,6 +1304,7 @@ Dim FSO As Object ' Alias for SF_FileSystem If SF_Session.HasUnoProperty(poComponent, "Title") Then .WindowTitle = poComponent.Title Select Case sIdentifier Case "com.sun.star.sdb.FormDesign" ' Form + .DocumentType = FORMDOCUMENT Case "com.sun.star.sdb.TextReportDesign" ' Report Case "com.sun.star.text.TextDocument" ' Writer .DocumentType = WRITERDOCUMENT diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index b3b79132d4b2..a15261caed58 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -1751,6 +1751,9 @@ class SFDatabases: def GetRows(self, sqlcommand, directsql = False, header = False, maxrows = 0): return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetRows', sqlcommand, directsql, header, maxrows) + def OpenFormDocument(self, formdocument): + return self.ExecMethod(self.vbMethod, 'OpenFormDocument', formdocument) + def OpenQuery(self, queryname): return self.ExecMethod(self.vbMethod, 'OpenQuery', queryname) @@ -1968,9 +1971,9 @@ class SFDocuments: servicename = 'SFDocuments.Document' servicesynonyms = ('document', 'sfdocuments.document') serviceproperties = dict(Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False, - IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False, - IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True, - XComponent = False) + IsBase = False, IsCalc = False, IsDraw = False, IsFormDocument = False, + IsImpress = False, IsMath = False, IsWriter = False, Keywords = True, Readonly = False, + Subject = True, Title = True, XComponent = False) # Force for each property to get its value from Basic - due to intense interactivity with user forceGetProperty = True @@ -2029,8 +2032,8 @@ class SFDocuments: serviceimplementation = 'basic' servicename = 'SFDocuments.Base' servicesynonyms = ('base', 'scriptforge.base') - serviceproperties = dict(DocumentType = False, IsBase = False, IsCalc = False, - IsDraw = False, IsImpress = False, IsMath = False, IsWriter = False, + serviceproperties = dict(DocumentType = False, IsBase = False, IsCalc = False, IsDraw = False, + IsFormDocument = False, IsImpress = False, IsMath = False, IsWriter = False, XComponent = False) @classmethod @@ -2088,9 +2091,9 @@ class SFDocuments: servicesynonyms = ('calc', 'sfdocuments.calc') serviceproperties = dict(CurrentSelection = True, Sheets = False, Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False, - IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False, - IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True, - XComponent = False) + IsBase = False, IsCalc = False, IsDraw = False, IsFormDocument = False, + IsImpress = False, IsMath = False, IsWriter = False, Keywords = True, Readonly = False, + Subject = True, Title = True, XComponent = False) # Force for each property to get its value from Basic - due to intense interactivity with user forceGetProperty = True @@ -2343,7 +2346,7 @@ class SFDocuments: It includes the management of subforms Each instance of the current class represents a single form or a single subform A form may optionally be (understand "is often") linked to a data source manageable with - the SFDatabases.Database service. The current service offers a rapid access to that service. + the SFDatabases.Database service. The current service offers rapid access to that service. """ # Mandatory class properties for service registration serviceimplementation = 'basic' @@ -2426,6 +2429,46 @@ class SFDocuments: def SetFocus(self): return self.ExecMethod(self.vbMethod, 'SetFocus') + # ######################################################################### + # SF_FormDocument CLASS + # ######################################################################### + class SF_FormDocument(SF_Document, SFServices): + """ + The orchestration of Base form documents (aka Base Forms, but this is confusing) + and the identification of and the access to their controls. + Form documents are always contained in a Base document. + They should not be confused with Writer documents containing forms, + even if it is easy to convert the former to the latter. + """ + # Mandatory class properties for service registration + serviceimplementation = 'basic' + servicename = 'SFDocuments.FormDocument' + servicesynonyms = ('formdocument', 'sfdocuments.formdocument') + serviceproperties = dict(DocumentType = False, IsBase = False, IsCalc = False, IsDraw = False, + IsFormDocument = False, IsImpress = False, IsMath = False, IsWriter = False, + Readonly = False, XComponent = False) + + @classmethod + def ReviewServiceArgs(cls, windowname = ''): + """ + Transform positional and keyword arguments into positional only + """ + return windowname, + + def CloseDocument(self): + return self.ExecMethod(self.vbMethod, 'CloseDocument') + + def Forms(self, form = ''): + return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', form) + + def GetDatabase(self, user = '', password = ''): + return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password) + + def PrintOut(self, pages = '', copies = 1, printbackground = True, printblankpages = False, + printevenpages = True, printoddpages = True, printimages = True): + return self.ExecMethod(self.vbMethod, 'PrintOut', pages, copies, printbackground, printblankpages, + printevenpages, printoddpages, printimages) + # ######################################################################### # SF_Writer CLASS # ######################################################################### @@ -2439,9 +2482,9 @@ class SFDocuments: servicename = 'SFDocuments.Writer' servicesynonyms = ('writer', 'sfdocuments.writer') serviceproperties = dict(Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False, - IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False, - IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True, - XComponent = False) + IsBase = False, IsCalc = False, IsDraw = False, IsFormDocument = False, + IsImpress = False, IsMath = False, IsWriter = False, Keywords = True, Readonly = False, + Subject = True, Title = True, XComponent = False) # Force for each property to get its value from Basic - due to intense interactivity with user forceGetProperty = True diff --git a/wizards/source/sfdatabases/SF_Database.xba b/wizards/source/sfdatabases/SF_Database.xba index f0dec87c294e..de891935be69 100644 --- a/wizards/source/sfdatabases/SF_Database.xba +++ b/wizards/source/sfdatabases/SF_Database.xba @@ -69,6 +69,8 @@ Private _MetaData As Object ' com.sun.star.sdbc.XDatabaseMetaData REM ============================================================ MODULE CONSTANTS +Const cstToken = "//" ' Form names accept special characters but not slashes + REM ===================================================== CONSTRUCTOR/DESTRUCTOR REM ----------------------------------------------------------------------------- @@ -401,6 +403,7 @@ Public Function Methods() As Variant , "DMin" _ , "DSum" _ , "GetRows" _ + , "OpenFormDocument" _ , "OpenQuery" _ , "OpenSql" _ , "OpenTable" _ @@ -409,6 +412,56 @@ Public Function Methods() As Variant End Function ' SFDatabases.SF_Database.Methods +REM ----------------------------------------------------------------------------- +Public Function OpenFormDocument(Optional ByVal FormDocument As Variant) As Object +''' Open the FormDocument given by its hierarchical name in normal mode +''' If the form document is already open, the form document is made active +''' Args: +''' FormDocument: a valid form document name as a case-sensitive string +''' When hierarchical, the hierarchy must be rendered with forward slashes ("/") +''' Returns: +''' A FormDocument instance or Nothing +''' Exceptions: +''' Form name is invalid +''' Example: +''' Set oForm = oDb.OpenFormDocument("Folder1/myFormDocument") + +Dim oOpen As Object ' Return value +Dim oFormDocuments As Variant ' com.sun.star.comp.dba.ODocumentContainer +Dim vFormNames As Variant ' Array of all document form names present in the document +Dim vOpenArgs As Variant ' Array of property values +Dim oNewForm As Object ' Output of loadComponent() +Const cstThisSub = "SFDatabases.Database.OpenFormDocument" +Const cstSubArgs = "FormDocument" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + Set oOpen = Nothing + +Check: + ' Build list of available FormDocuments recursively with _CollectFormDocuments + Set oFormDocuments = _Connection.Parent.DataBaseDocument.FormDocuments + + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + vFormNames = Split(_CollectFormDocuments(oFormDocuments), cstToken) + If Not ScriptForge.SF_Utils._Validate(FormDocument, "FormDocument", V_STRING, vFormNames) Then GoTo Finally + End If + +Try: + vOpenArgs = Array(SF_Utils._MakePropertyValue("ActiveConnection", _Connection) _ + , SF_Utils._MakePropertyValue("OpenMode", "open") _ + ) + Set oNewForm = oFormDocuments.loadComponentFromURL(FormDocument, "", 0, vOpenArgs) + + Set oOpen = ScriptForge.SF_Services.CreateScriptService("SFDocuments.FormDocument", oNewForm) + +Finally: + Set OpenFormDocument = oOpen + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' SF_Databases.SF_Database.OpenFormDocument + REM ----------------------------------------------------------------------------- Public Function OpenQuery(Optional ByVal QueryName As Variant) As Object ''' Open the query given by its name @@ -632,6 +685,44 @@ End Function ' SFDatabases.SF_Database.SetProperty REM =========================================================== PRIVATE FUNCTIONS +REM ----------------------------------------------------------------------------- +Private Function _CollectFormDocuments(ByRef poContainer As Object) As String +''' Returns a token-separated string of all hierarchical formdocument names +''' depending on the formdocuments container in argument +''' The function traverses recursively the whole tree below the container +''' The initial call starts from the container _Component.getFormDocuments +''' The list contains closed and open forms + +Dim sCollectNames As String ' Return value +Dim oSubItem As Object ' com.sun.star.container.XNameAccess (folder) or com.sun.star.ucb.XContent (form) +Dim i As Long +Const cstFormType = "application/vnd.oasis.opendocument.text" + ' Identifies forms. Folders have a zero-length content type + + On Local Error GoTo Finally + +Try: + sCollectNames = "" + With poContainer + For i = 0 To .Count - 1 + Set oSubItem = .getByIndex(i) + If oSubItem.ContentType = cstFormType Then ' Add the form to the list + sCollectNames = sCollectNames & cstToken & oSubItem.HierarchicalName + Else + sCollectNames = sCollectNames & cstToken & _CollectFormDocuments(oSubItem) + End If + Next i + End With + +Finally: + If Len(sCollectNames) > 0 Then + _CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) ' Skip the initial token + Else + _CollectFormDocuments = "" + End If + Exit Function +End Function ' SFDocuments.SF_Base._CollectFormDocuments + REM ----------------------------------------------------------------------------------------------------------------------- Private Function _DFunction(ByVal psFunction As String _ , Optional ByVal pvExpression As Variant _ diff --git a/wizards/source/sfdocuments/SF_Base.xba b/wizards/source/sfdocuments/SF_Base.xba index 8970b7c05b96..24d1e1b0997b 100644 --- a/wizards/source/sfdocuments/SF_Base.xba +++ b/wizards/source/sfdocuments/SF_Base.xba @@ -145,6 +145,7 @@ Public Function CloseFormDocument(Optional ByVal FormDocument As Variant) As Boo ''' True if closure is successful ''' Example: ''' oDoc.CloseFormDocument("Folder1/myFormDocument") +''' DEPRECATED - Use preferably the CloseDocument() method of the FormDocument service Dim bClose As Boolean ' Return value Dim oMainForm As Object ' com.sun.star.comp.sdb.Content @@ -235,6 +236,7 @@ Public Function Forms(Optional ByVal FormDocument As Variant _ ''' Dim myForm As Object, myList As Variant ''' myList = oDoc.Forms("Folder1/myFormDocument") ''' Set myForm = oDoc.Forms("Folder1/myFormDocument", 0) +''' DEPRECATED - Use preferably the Forms() method of the FormDocument service Dim oForm As Object ' The new Form class instance Dim oFormDocument As Object ' com.sun.star.comp.sdb.Content @@ -283,7 +285,8 @@ Try: ._Name = oXForm.Name Set .[Me] = oForm Set .[_Parent] = [Me] - Set ._Component = _Component + Set ._Component = oFormDocument.Component + Set ._BaseComponent = _Component ._FormDocumentName = FormDocument Set ._FormDocument = oFormDocument ._FormType = ISBASEFORM @@ -455,28 +458,28 @@ End Function ' SFDocuments.SF_Base.Methods REM ----------------------------------------------------------------------------- Public Function OpenFormDocument(Optional ByVal FormDocument As Variant _ , Optional ByVal DesignMode As Variant _ - ) As Boolean + ) As Object ''' Open the FormDocument given by its hierarchical name either in normal or in design mode ''' If the form document is already open, the form document is made active without changing its mode ''' Args: ''' FormDocument: a valid form document name as a case-sensitive string +''' When hierarchical, the hierarchy must be rendered with forward slashes ("/") ''' DesignMode: when True the form document is opened in design mode (Default = False) ''' Returns: -''' True if the form document could be opened, otherwise False +''' A FormDocument instance or Nothing ''' Exceptions: ''' Form name is invalid ''' Example: -''' oDoc.OpenFormDocument("Folder1/myFormDocument") +''' Set oForm = oDoc.OpenFormDocument("Folbder1/myFormDocument") -Dim bOpen As Boolean ' Return value +Dim oOpen As Object ' Return value Dim vFormNames As Variant ' Array of all document form names present in the document -Dim oContainer As Object ' com.sun.star.awt.XWindow Dim oNewForm As Object ' Output of loadComponent() Const cstThisSub = "SFDocuments.Base.OpenFormDocument" Const cstSubArgs = "FormDocument, [DesignMode=False]" If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch - bOpen = False + Set oOpen = Nothing Check: If IsMissing(DesignMode) Or IsEmpty(DesignMode) Then DesignMode = False @@ -499,10 +502,11 @@ Try: If .isFormDesignMode() <> DesignMode Then .setFormDesignMode(DesignMode) End With End With - bOpen = True + + Set oOpen = ScriptForge.SF_Services.CreateScriptService("SFDocuments.FormDocument", oNewForm) Finally: - OpenFormDocument = bOpen + Set OpenFormDocument = oOpen ScriptForge.SF_Utils._ExitFunction(cstThisSub) Exit Function Catch: @@ -632,6 +636,7 @@ Public Function PrintOut(Optional ByVal FormDocument As Variant _ ''' True when successful ''' Examples: ''' oDoc.PrintOut("myForm", "1-4;10;15-18", Copies := 2) +''' DEPRECATED - Use preferably the PrintOut() method of the FormDocument service Dim bPrint As Boolean ' Return value Dim vFormNames As Variant ' Array of all document form names present in the document @@ -681,6 +686,7 @@ Public Function Properties() As Variant , "IsBase" _ , "IsCalc" _ , "IsDraw " _ + , "IsFormDocument" _ , "IsImpress" _ , "IsMath" _ , "IsWriter" _ @@ -708,6 +714,7 @@ Public Function SetPrinter(Optional ByVal FormDocument As Variant _ ''' True when successful ''' Examples: ''' oDoc.SetPrinter("myForm", Orientation := "PORTRAIT") +''' DEPRECATED - Use preferably the SetPrinter() method of the FormDocument service Dim bPrinter As Boolean ' Return value Dim vFormDocuments As Variant ' Array of form documents @@ -829,6 +836,11 @@ Property Get IsDraw() As Boolean IsDraw = [_Super].GetProperty("IsDraw") End Property ' SFDocuments.SF_Base.IsDraw +REM ----------------------------------------------------------------------------- +Property Get IsFormDocument() As Boolean + IsFormDocument = [_Super].GetProperty("IsFormDocument") +End Property ' SFDocuments.SF_Writer.IsFormDocument + REM ----------------------------------------------------------------------------- Property Get IsImpress() As Boolean IsImpress = [_Super].GetProperty("IsImpress") @@ -968,7 +980,11 @@ Try: End With Finally: - _CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) ' Skip the initial token + If Len(sCollectNames) > 0 Then + _CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) ' Skip the initial token + Else + _CollectFormDocuments = "" + End If Exit Function End Function ' SFDocuments.SF_Base._CollectFormDocuments diff --git a/wizards/source/sfdocuments/SF_Calc.xba b/wizards/source/sfdocuments/SF_Calc.xba index 0733be07eb6a..806f30bd7cad 100644 --- a/wizards/source/sfdocuments/SF_Calc.xba +++ b/wizards/source/sfdocuments/SF_Calc.xba @@ -2556,6 +2556,7 @@ Public Function Properties() As Variant , "IsBase" _ , "IsCalc" _ , "IsDraw" _ + , "IsFormDocument" _ , "IsImpress" _ , "IsMath" _ , "IsWriter" _ @@ -3482,6 +3483,11 @@ Property Get IsDraw() As Boolean IsDraw = [_Super].GetProperty("IsDraw") End Property ' SFDocuments.SF_Calc.IsDraw +REM ----------------------------------------------------------------------------- +Property Get IsFormDocument() As Boolean + IsFormDocument = [_Super].GetProperty("IsFormDocument") +End Property ' SFDocuments.SF_Writer.IsFormDocument + REM ----------------------------------------------------------------------------- Property Get IsImpress() As Boolean IsImpress = [_Super].GetProperty("IsImpress") diff --git a/wizards/source/sfdocuments/SF_Document.xba b/wizards/source/sfdocuments/SF_Document.xba index bba8b3c21bd5..03fb215369ea 100644 --- a/wizards/source/sfdocuments/SF_Document.xba +++ b/wizards/source/sfdocuments/SF_Document.xba @@ -268,6 +268,11 @@ Property Get IsDraw() As Boolean IsDraw = _PropertyGet("IsDraw") End Property ' SFDocuments.SF_Document.IsDraw +REM ----------------------------------------------------------------------------- +Property Get IsFormDocument() As Boolean + IsFormDocument = _PropertyGet("IsFormDocument") +End Property ' SFDocuments.SF_Document.IsFormDocument + REM ----------------------------------------------------------------------------- Property Get IsImpress() As Boolean IsImpress = _PropertyGet("IsImpress") @@ -459,7 +464,7 @@ Try: If SaveAsk And _Component.IsModified Then ' Execute closure with the File/Close menu command Activate() RunCommand("CloseDoc") - bClosed = _IsStillAlive(, False) ' Do not raise error + bClosed = Not _IsStillAlive(, False) ' Do not raise error Else _Frame.close(True) _Frame.dispose() @@ -472,6 +477,7 @@ Finally: ScriptForge.SF_Utils._ExitFunction(cstThisSub) Exit Function Catch: + On Local Error GoTo 0 GoTo Finally End Function ' SFDocuments.SF_Document.CloseDocument @@ -592,7 +598,10 @@ Check: Try: ' Setup arguments - sFilter = LCase(_DocumentType) & "_pdf_Export" + Select Case _DocumentType ' Disguise form documents as a Writer document + Case "FormDocument" : sFilter = "Writer_pdf_Export" + Case Else : sFilter = LCase(_DocumentType) & "_pdf_Export" + End Select ' FilterData parameters are added only if they are meaningful vFilterData = Array() If Len(Pages) > 0 Then @@ -751,6 +760,7 @@ Public Function Properties() As Variant , "IsBase" _ , "IsCalc" _ , "IsDraw" _ + , "IsFormDocument" _ , "IsImpress" _ , "IsMath" _ , "IsWriter" _ @@ -1471,7 +1481,7 @@ Const cstSubArgs = "" _PropertyGet = _GetFilterNames(True) Case "ImportFilters" _PropertyGet = _GetFilterNames(False) - Case "IsBase", "IsCalc", "IsDraw", "IsImpress", "IsMath", "IsWriter" + Case "IsBase", "IsCalc", "IsDraw", "IsFormDocument", "IsImpress", "IsMath", "IsWriter" _PropertyGet = ( Mid(psProperty, 3) = _DocumentType ) Case "Keywords" _PropertyGet = Join(_Component.DocumentProperties.Keywords, ", ") diff --git a/wizards/source/sfdocuments/SF_Form.xba b/wizards/source/sfdocuments/SF_Form.xba index 2879536efb6f..10b84622d5e5 100644 --- a/wizards/source/sfdocuments/SF_Form.xba +++ b/wizards/source/sfdocuments/SF_Form.xba @@ -23,8 +23,8 @@ Option Explicit ''' ''' Definitions: ''' -''' FormDocument: -''' For usual documents, there is only 1 form document. It is in fact the document itself. +''' FormDocument: BASE DOCUMENTS ONLY +''' For usual documents, there is only 1 forms cpntainer. It is either the document itself or one of its sheets (Calc) ''' A Base document may contain an unlimited number of form documents. ''' In the Base terminology they are called "forms" or "Base forms". This could create some confusion. ''' They can be organized in folders. Their name is then always the full path of folders + form @@ -34,29 +34,36 @@ Option Explicit ''' the user experience significantly ''' ''' Form: WHERE IT IS ABOUT IN THE CURRENT "Form" SERVICE -''' Is an abstract set of Controls in an OPEN FormDocument +''' Is an abstract set of Controls in an OPEN Document or FormDocument ''' Each form is usually linked to one single dataset (table, query or Select statement), ''' located in any database (provided the user may access it) ''' A usual document may contain several forms. Each of which may have its own data source (database + dataset) ''' A Base form document may contain several forms. Each of which may address its own dataset. The database however is unique -''' A form is defined by its owning FormDocument and its FormName or FormIndex +''' A form is defined by its owning Document or FormDocument and its FormName or FormIndex ''' ''' Service invocations: ''' -''' REM the form is stored in a not-Base document (Calc, Writer) +''' REM the form is stored in a Writer document ''' Dim oDoc As Object, myForm As Object ''' Set oDoc = CreateScriptService("SFDocuments.Document", ThisComponent) ''' Set myForm = oDoc.Forms("Form1") ''' ' or, alternatively, when there is only 1 form ''' Set myForm = oDoc.Forms(0) ''' -''' REM the form is stored in one of the FormDocuments of a Base document -''' Dim oDoc As Object, myForm As Object, mySubForm As Object -''' Set oDoc = CreateScriptService("SFDocuments.Document", ThisDatabaseDocument) -''' oDoc.OpenFormDocument("thisFormDocument") -''' Set myForm = oDoc.Forms("thisFormDocument", "MainForm") +''' REM the form is stored in a Calc document +''' Dim oCalc As Object, myForm As Object +''' Set oCalc = CreateScriptService("SFDocuments.Document", ThisComponent) +''' Set myForm = oCalc.Forms("Sheet1", "Form1") ''' ' or, alternatively, when there is only 1 form -''' Set myForm = oDoc.Forms("thisFormDocument", 0) +''' Set myForm = oCalc.Forms("Sheet1", 0) +''' +''' REM the form is stored in one of the FormDocuments of a Base document +''' Dim oBase As Object, myFormDoc As Object, myForm As Object, mySubForm As Object +''' Set oBase = CreateScriptService("SFDocuments.Document", ThisDatabaseDocument) +''' Set oFormDoc = oBase.OpenFormDocument("thisFormDocument") +''' Set myForm = oFormDoc.Forms("MainForm") +''' ' or, alternatively, when there is only 1 form +''' Set myForm = oFormDoc.Forms(0) ''' ' To access a subform: myForm and mySubForm become distinct instances of the current class ''' Set mySubForm = myForm.SubForms("mySubForm") ''' @@ -87,9 +94,10 @@ Private _Name As String ' Internal name of the form Private _FormType As Integer ' One of the ISxxxFORM constants Private _SheetName As String ' Name as the sheet containing the form (Calc only) Private _FormDocumentName As String ' The hierarchical name of the containing form document (Base only) -Private _FormDocument As Object ' com.sun.star.comp.sdb.Content - the containing form document - ' The form topmost container -Private _Component As Object ' com.sun.star.lang.XComponent or com.sun.star.comp.dba.ODatabaseDocument +Private _FormDocument As Object ' com.sun.star.comp.sdb.Content - the form document container +' The form topmost containers +Private _Component As Object ' com.sun.star.lang.XComponent +Private _BaseComponent As Object ' com.sun.star.comp.dba.ODatabaseDocument ' Events management Private _CacheIndex As Long ' Index in central cache storage @@ -98,9 +106,9 @@ Private _CacheIndex As Long ' Index in central cache storage ' The entry to the interactions with the form. Validity checked by the _IsStillAlive() method ' Each method or property requiring that the form is opened should first invoke that method Private _Form As Object ' com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm -Private _Database As Object ' Database class instance ' Form attributes +Private _Database As Object ' Database class instance ' Cache storage for controls Private _ControlNames As Variant ' Array of control names @@ -110,7 +118,7 @@ REM ============================================================ MODULE CONSTANT Const ISDOCFORM = 1 ' Form is stored in a Writer document Const ISCALCFORM = 2 ' Form is stored in a Calc document -Const ISBASEFORM = 3 ' Form is stored in a Base document +Const ISBASEFORM = 3 ' Form is stored in a Base form document Const ISSUBFORM = 4 ' Form is a subform of a form or of another subform Const ISUNDEFINED = -1 ' Undefined form type @@ -126,6 +134,8 @@ Private Sub Class_Initialize() _SheetName = "" _FormDocumentName = "" Set _FormDocument = Nothing + Set _Component = Nothing + Set _BaseComponent = Nothing _FormType = ISUNDEFINED _CacheIndex = -1 Set _Form = Nothing @@ -535,11 +545,14 @@ Check: End If Try: Select Case _FormType - Case ISDOCFORM, ISCALCFORM, ISSUBFORM - Case ISBASEFORM - _FormDocument.close() - Dispose() - bClose = True + Case ISDOCFORM, ISCALCFORM + Case ISBASEFORM, ISSUBFORM + If Not IsNull(_FormDocument) Then + _FormDocument.close() + Dispose() + bClose = True + End If + Case Else End Select Finally: @@ -673,7 +686,7 @@ Check: If IsMissing(User) Or IsEmpty(User) Then User = "" If IsMissing(Password) Or IsEmpty(Password) Then Password = "" If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then - If Not [_Parent]._IsStillAlive(True) Then GoTo Finally + If Not [_Parent]._IsStillAlive(False) Then GoTo Finally If Not ScriptForge.SF_Utils._Validate(User, "User", V_STRING) Then GoTo Finally If Not ScriptForge.SF_Utils._Validate(Password, "Password", V_STRING) Then GoTo Finally End If @@ -691,7 +704,7 @@ Try: ' Connect to database, avoiding multiple requests If IsNull(_Database) Then ' 1st connection request from the current form instance - If _FormType = ISBASEFORM Then + If _FormType = ISBASEFORM And Not IsNull(_BaseComponent) Then ' Fetch the shared connection Set _Database = [_Parent].GetDatabase(User, Password) ElseIf _FormType = ISSUBFORM Then @@ -1123,6 +1136,7 @@ Try: Set .[_Parent] = [Me] ._FormType = ISSUBFORM Set ._Component = _Component + Set ._BaseComponent = _BaseComponent Set ._FormDocument = _FormDocument ._SheetName = _SheetName ._FormDocumentName = _FormDocumentName @@ -1208,8 +1222,8 @@ Private Sub _GetParents() Dim oParent As Object ' Successive bottom-up parents Dim sType As String ' UNO object type -Dim sPersistentName As String ' The Obj... name of a Base form Dim iLevel As Integer ' When = 1 => first parent +Dim oBase As Object ' Empty Base instance Dim oSession As Object : Set oSession = ScriptForge.SF_Session On Local Error GoTo Finally ' Being probably called from events, this method should avoid failures @@ -1243,12 +1257,15 @@ Try: Case "com.sun.star.form.OFormsCollection" ' The collection of forms inside a drawpage Case "SwXTextDocument" ' The parent document: a Writer document or a Base form document If oParent.Identifier = "com.sun.star.sdb.FormDesign" Then - sPersistentName = ScriptForge._GetPropertyValue(oParent.Args, "HierarchicalDocumentName") + _FormType = ISBASEFORM + ' Make a new SF_FormDocument instance + Set [_Parent] = ScriptForge.SF_Services.CreateScriptService("SFDocuments.FormDocument", oParent) + Set _FormDocument = [_Parent]._FormDocument ElseIf oParent.Identifier = "com.sun.star.text.TextDocument" Then _FormType = ISDOCFORM Set [_Parent] = ScriptForge.SF_Services.CreateScriptService("SFDocuments.Document", oParent) - Set _Component = [_Parent]._Component End If + Set _Component = oParent Case "ScModelObj" ' The parent document: a Calc document _FormType = ISCALCFORM Set [_Parent] = ScriptForge.SF_Services.CreateScriptService("SFDocuments.Document", oParent) @@ -1256,12 +1273,6 @@ Try: ' The triggered form event is presumed to be located in the (drawpage of the) active sheet _SheetName = [_Parent].XSpreadsheet("~") Case "com.sun.star.comp.dba.ODatabaseDocument" ' The Base document - _FormType = ISBASEFORM - Set [_Parent] = ScriptForge.SF_Services.CreateScriptService("SFDocuments.Document", oParent) - Set _Component = oParent - If IsNull([_Parent]._FormDocuments) Then Set [_Parent]._FormDocuments = _Component.getFormDocuments() - Set _FormDocument = [_Parent]._FindByPersistentName([_Parent]._FormDocuments, sPersistentName) - _FormDocumentName = _FormDocument.HierarchicalName Case Else End Select If oSession.HasUnoProperty(oParent, "Parent") Then Set oParent = oParent.Parent Else Set oParent = Nothing diff --git a/wizards/source/sfdocuments/SF_FormControl.xba b/wizards/source/sfdocuments/SF_FormControl.xba index a48c22b6c1c5..180cb682b381 100644 --- a/wizards/source/sfdocuments/SF_FormControl.xba +++ b/wizards/source/sfdocuments/SF_FormControl.xba @@ -13,7 +13,8 @@ Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''' SF_FormControl -''' ================ +''' ============== +''' ''' Manage the controls belonging to a form or subform stored in a document ''' Each instance of the current class represents a single control within a form, a subform or a tablecontrol ''' A prerequisite is that all controls within the same form, subform or tablecontrol must have @@ -1131,7 +1132,7 @@ Try: End With ' Store the SF_FormControl object in the parent cache - Set _Parent._ControlCache(_IndexOfNames) = [Me] + Set [_Parent]._ControlCache(_IndexOfNames) = [Me] Finally: Exit Sub diff --git a/wizards/source/sfdocuments/SF_FormDocument.xba b/wizards/source/sfdocuments/SF_FormDocument.xba new file mode 100644 index 000000000000..8d13d86e96e4 --- /dev/null +++ b/wizards/source/sfdocuments/SF_FormDocument.xba @@ -0,0 +1,642 @@ + + +REM ======================================================================================================================= +REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. === +REM === The SFDocuments library is one of the associated libraries. === +REM === Full documentation is available on https://help.libreoffice.org/ === +REM ======================================================================================================================= + +Option Compatible +Option ClassModule + +Option Explicit + +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +''' SF_FormDocument +''' =============== +''' +''' The SFDocuments library gathers a number of methods and properties making easy +''' managing and manipulating LibreOffice documents +''' +''' Some methods are generic for all types of documents: they are combined in the SF_Document module. +''' Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Writer, SF_Base, ... +''' +''' To workaround the absence of class inheritance in LibreOffice Basic, some redundancy is necessary +''' Each subclass MUST implement also the generic methods and properties, even if they only call +''' the parent methods and properties. +''' They should also duplicate some generic private members as a subset of their own set of members +''' +''' The SF_FormDocument module is focused on : +''' The orchestration of Base form documents (aka Base Forms, but this is confusing) +''' and the identification of and the access to their controls. +''' Form documents are always contained in a Base document. +''' They should not be confused with Writer documents containing forms, +''' even if it is easy to convert the former to the latter. +''' +''' The current module is closely related to +''' the "Base" service of the current library +''' the "Database" service of the SFDatabases library +''' +''' A form document may be opened either: +''' via code or user interface from the Base file welcome page +''' via code only, without having its Base container opened first +''' The Base document remains hidden but the user might be prompted about the macro execution mode +''' In any mode, a form document can be opened only in 1 single copy +''' +''' Service invocation examples: +''' 1) From the Base service +''' Dim oBase As Object, oFormDoc As Object +''' ' oBase is presumed to represent an open Base document +''' Set oFormDoc = oBade.OpenFormDocument("Folder1/Form1") +''' 2) Directly without making the Base document visible +''' Dim oDatabase As Object, oFormDoc As Object +''' Set oDatabase = CreateScriptService("SFDatabases.Database", ".../myFile.odb", ReadOnly := False) +''' ' The substring "SFDatabases." in the service name is optional +''' Set oFormDoc = oDatabase.OpenFormDocument("Folder1/Form1") +''' +''' Definitions: +''' None +''' +''' Detailed user documentation: +''' https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_formdocument.html?DbPAR=BASIC +''' +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +REM ================================================================== EXCEPTIONS + +Private Const BASEFORMNOTFOUNDERROR = "BASEFORMNOTFOUNDERROR" + +REM ============================================================= PRIVATE MEMBERS + +Private [Me] As Object +Private [_Parent] As Object ' Unused +Private [_Super] As Object ' Document superclass, which the current instance is a subclass of +Private ObjectType As String ' Must be FormDocument +Private ServiceName As String + +' Components +Private _Component As Object ' com.sun.star.lang.XComponent +Private _BaseComponent As Object ' com.sun.star.comp.dba.ODatabaseDocument +Private _FormDocument As Object ' com.sun.star.comp.sdb.Content + +' Form document description +Private _PersistentName As String ' Typically Objxx +Private _HierarchicalName As String +Private _DataSource As Object ' com.sun.star.sdbc.XDataSource +Private _User As String ' Credentials +Private _Password As String + +REM ============================================================ MODULE CONSTANTS + +Const ISBASEFORM = 3 ' Form is stored in a Form document + +REM ====================================================== CONSTRUCTOR/DESTRUCTOR + +REM ----------------------------------------------------------------------------- +Private Sub Class_Initialize() + Set [Me] = Nothing + Set [_Parent] = Nothing + Set [_Super] = Nothing + ObjectType = "FormDocument" + ServiceName = "SFDocuments.FormDocument" + Set _Component = Nothing + Set _BaseComponent = Nothing + Set _FormDocument = Nothing + Set _DataSource = Nothing + Set _Database = Nothing + _PersistentName = "" + _HierarchicalName = "" +End Sub ' SFDocuments.SF_FormDocument Constructor + +REM ----------------------------------------------------------------------------- +Private Sub Class_Terminate() + Call Class_Initialize() +End Sub ' SFDocuments.SF_FormDocument Destructor + +REM ----------------------------------------------------------------------------- +Public Function Dispose() As Variant + If Not IsNull([_Super]) Then Set [_Super] = [_Super].Dispose() + Call Class_Terminate() + Set Dispose = Nothing +End Function ' SFDocuments.SF_FormDocument Explicit Destructor + +REM ================================================================== PROPERTIES + +REM ===================================================================== METHODS + +REM ----------------------------------------------------------------------------- +Public Function CloseDocument() As Boolean +''' Close the form document and dispose the actual instance +''' Args: +''' Returns: +''' True if closure is successful +''' Example: +''' myFormDoc.CloseDocument() + +Dim bClose As Boolean ' Return value +Dim oContainer As Object ' com.sun.star.awt.XWindow +Const cstThisSub = "SFDocuments.FormDocument.CloseDocument" +Const cstSubArgs = "" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + bClose = False + +Check: + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not _IsStillAlive() Then GoTo Finally + End If +Try: + _FormDocument.close() + Dispose() + bClose = True + +Finally: + CloseDocument = bClose + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' SFDocuments.SF_FormDocument.CloseDocument + +REM ----------------------------------------------------------------------------- +Public Function Forms(Optional ByVal Form As Variant) As Variant +''' Return either +''' - the list of the Forms contained in the form document +''' - a SFDocuments.Form object based on its name or its index +''' Args: +''' Form: a form stored in the document given by its name or its index +''' When absent, the list of available forms is returned +''' To get the first (unique ?) form stored in the form document, set Form = 0 +''' Exceptions: +''' BASEFORMNOTFOUNDERROR Form not found +''' Returns: +''' A zero-based array of strings if Form is absent +''' An instance of the SF_Form class if Form exists +''' Example: +''' Dim myForm As Object, myList As Variant +''' myList = oDoc.Forms() +''' Set myForm = oDoc.Forms("myForm") + +Dim oForm As Object ' The new Form class instance +Dim oMainForm As Object ' com.sun.star.comp.sdb.Content +Dim oXForm As Object ' com.sun.star.form.XForm +Dim vFormNames As Variant ' Array of form names +Dim oForms As Object ' Forms collection +Const cstDrawPage = 0 ' Only 1 drawpage in a FormDocument document + +Const cstThisSub = "SFDocuments.FormDocument.Forms" +Const cstSubArgs = "[Form=""""]" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + +Check: + If IsMissing(Form) Or IsEmpty(Form) Then Form = "" + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not _IsStillAlive() Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(Form, "Form", Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally + End If + +Try: + ' Start from the document component and go down to forms + Set oForms = _Component.DrawPages(cstDrawPage).Forms + vFormNames = oForms.getElementNames() + + If Len(Form) = 0 Then ' Return the list of valid form names + Forms = vFormNames + Else + If VarType(Form) = V_STRING Then ' Find the form by name + If Not ScriptForge.SF_Array.Contains(vFormNames, Form, CaseSensitive := True) Then GoTo CatchNotFound + Set oXForm = oForms.getByName(Form) + Else ' Find the form by index + If Form < 0 Or Form >= oForms.Count Then GoTo CatchNotFound + Set oXForm = oForms.getByIndex(Form) + End If + ' Create the new Form class instance + Set oForm = SF_Register._NewForm(oXForm) + With oForm + Set .[_Parent] = [Me] + ._FormType = ISBASEFORM + Set ._Component = _Component + Set ._BaseComponent = _BaseComponent + ._FormDocumentName = _HierarchicalName + ._FormDocument = _FormDocument + ._Initialize() + End With + Set Forms = oForm + End If + +Finally: + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +CatchNotFound: + ScriptForge.SF_Exception.RaiseFatal(BASEFORMNOTFOUNDERROR, Form, _FileIdent()) +End Function ' SFDocuments.SF_FormDocument.Forms + +REM ----------------------------------------------------------------------------- +Public Function GetDatabase(Optional ByVal User As Variant _ + , Optional ByVal Password As Variant _ + ) As Object +''' Returns a Database instance (service = SFDatabases.Database) giving access +''' to the execution of SQL commands on the database defined and/or stored in +''' the actual form document +''' Args: +''' User, Password: the login parameters as strings. Defaults = "" +''' Returns: +''' A SFDatabases.Database instance or Nothing +''' Example: +''' Dim myDb As Object +''' Set myDb = oFormDoc.GetDatabase() + +Dim oDatabase As Object ' Return value +Const cstThisSub = "SFDocuments.FormDocument.GetDatabase" +Const cstSubArgs = "[User=""""], [Password=""""]" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + Set oDatabase = Nothing + +Check: + If IsMissing(User) Or IsEmpty(User) Then User = "" + If IsMissing(Password) Or IsEmpty(Password) Then Password = "" + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not _IsStillAlive(False) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(User, "User", V_STRING) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(Password, "Password", V_STRING) Then GoTo Finally + End If + +Try: + If IsNull(_DataSource) Then GoTo CatchConnect + Set oDatabase = ScriptForge.SF_Services.CreateScriptService("SFDatabases.DatabaseFromDocument" _ + , _DataSource, Iif(User = "", _User, User), Iif(Password = "", _Password, "")) + If IsNull(oDatabase) Then GoTo CatchConnect + oDatabase._Location = _DataSource.Name + +Finally: + Set GetDatabase = oDatabase + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +CatchConnect: + ScriptForge.SF_Exception.RaiseFatal(DBCONNECTERROR, "User", User, "Password", Password, [_Super]._FileIdent()) + GoTo Finally +End Function ' SFDocuments.SF_FormDocument.GetDatabase + +REM ----------------------------------------------------------------------------- +Public Function GetProperty(Optional ByVal PropertyName As Variant _ + , Optional ObjectName As Variant _ + ) As Variant +''' Return the actual value of the given property +''' Args: +''' PropertyName: the name of the property as a string +''' ObjectName: a sheet or range name +''' Returns: +''' The actual value of the property +''' Exceptions: +''' ARGUMENTERROR The property does not exist + +Const cstThisSub = "SFDocuments.FormDocument.GetProperty" +Const cstSubArgs = "" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + GetProperty = Null + +Check: + If IsMissing(ObjectName) Or IsEmpty(ObjectName) Then ObjectName = "" + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not ScriptForge.SF_Utils._Validate(PropertyName, "PropertyName", V_STRING, Properties()) Then GoTo Catch + If Not ScriptForge.SF_Utils._Validate(ObjectName, "ObjectName", V_STRING) Then GoTo Catch + End If + +Try: + ' Superclass or subclass property ? + If ScriptForge.SF_Array.Contains([_Super].Properties(), PropertyName) Then + GetProperty = [_Super].GetProperty(PropertyName) + ElseIf Len(ObjectName) = 0 Then + GetProperty = _PropertyGet(PropertyName) + Else + GetProperty = _PropertyGet(PropertyName, ObjectName) + End If + +Finally: + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' SFDocuments.SF_FormDocument.GetProperty + +REM ----------------------------------------------------------------------------- +Public Function Methods() As Variant +''' Return the list of public methods of the FormDocument service as an array + + Methods = Array( _ + "CloseDocument" _ + , "Forms" _ + , "PrintOut" _ + ) + +End Function ' SFDocuments.SF_FormDocument.Methods + +REM ----------------------------------------------------------------------------- +Public Function PrintOut(Optional ByVal Pages As Variant _ + , Optional ByVal Copies As Variant _ + , Optional ByVal PrintBackground As Variant _ + , Optional ByVal PrintBlankPages As Variant _ + , Optional ByVal PrintEvenPages As Variant _ + , Optional ByVal PrintOddPages As Variant _ + , Optional ByVal PrintImages As Variant _ + ) As Boolean +''' Send the content of the document to the printer. +''' The printer might be defined previously by default, by the user or by the SetPrinter() method +''' Args: +''' Pages: the pages to print as a string, like in the user interface. Example: "1-4;10;15-18". Default = all pages +''' Copies: the number of copies +''' PrintBackground: print the background image when True (default) +''' PrintBlankPages: when False (default), omit empty pages +''' PrintEvenPages: print the left pages when True (default) +''' PrintOddPages: print the right pages when True (default) +''' PrintImages: print the graphic objects when True (default) +''' Returns: +''' True when successful +''' Examples: +''' oDoc.PrintOut("1-4;10;15-18", Copies := 2, PrintImages := False) + +Dim bPrint As Boolean ' Return value +Dim vPrintOptions As Variant ' com.sun.star.text.DocumentSettings + +Const cstThisSub = "SFDocuments.FormDocument.PrintOut" +Const cstSubArgs = "[Pages=""""], [Copies=1], [PrintBackground=True], [PrintBlankPages=False], [PrintEvenPages=True]" _ + & ", [PrintOddPages=True], [PrintImages=True]" + + If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + bPrint = False + +Check: + If IsMissing(Pages) Or IsEmpty(Pages) Then Pages = "" + If IsMissing(Copies) Or IsEmpty(Copies) Then Copies = 1 + If IsMissing(PrintBackground) Or IsEmpty(PrintBackground) Then PrintBackground = True + If IsMissing(PrintBlankPages) Or IsEmpty(PrintBlankPages) Then PrintBlankPages = False + If IsMissing(PrintEvenPages) Or IsEmpty(PrintEvenPages) Then PrintEvenPages = True + If IsMissing(PrintOddPages) Or IsEmpty(PrintOddPages) Then PrintOddPages = True + If IsMissing(PrintImages) Or IsEmpty(PrintImages) Then PrintImages = True + + If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not _IsStillAlive() Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(Pages, "Pages", V_STRING) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(Copies, "Copies", ScriptForge.V_NUMERIC) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(PrintBackground, "PrintBackground", ScriptForge.V_BOOLEAN) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(PrintBlankPages, "PrintBlankPages", ScriptForge.V_BOOLEAN) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(PrintEvenPages, "PrintEvenPages", ScriptForge.V_BOOLEAN) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(PrintOddPages, "PrintOddPages", ScriptForge.V_BOOLEAN) Then GoTo Finally + If Not ScriptForge.SF_Utils._Validate(PrintImages, "PrintImages", ScriptForge.V_BOOLEAN) Then GoTo Finally + End If + +Try: + vPrintOptions = _Component.createInstance("com.sun.star.text.DocumentSettings") + With vPrintOptions + .PrintPageBackground = PrintBackground + .PrintEmptyPages = PrintBlankPages + .PrintLeftPages = PrintEvenPages + .PrintRightPages = PrintOddPages + .PrintGraphics = PrintImages + .PrintDrawings = PrintImages + End With + + bPrint = [_Super].PrintOut(Pages, Copies, _Component) + +Finally: + PrintOut = bPrint + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' SFDocuments.SF_FormDocument.PrintOut + +REM ----------------------------------------------------------------------------- +Public Function Properties() As Variant +''' Return the list or properties of the FormDocument class as an array + + Properties = Array( _ + "DocumentType" _ + , "IsBase" _ + , "IsCalc" _ + , "IsDraw" _ + , "IsFormDocument" _ + , "IsImpress" _ + , "IsMath" _ + , "Readonly" _ + , "XComponent" _ + ) + +End Function ' SFDocuments.SF_FormDocument.Properties + +REM ======================================================= SUPERCLASS PROPERTIES + +REM ----------------------------------------------------------------------------- +Property Get IsBase() As Boolean + IsBase = [_Super].GetProperty("IsBase") +End Property ' SFDocuments.SF_FormDocument.IsBase + +REM ----------------------------------------------------------------------------- +Property Get IsCalc() As Boolean + IsCalc = [_Super].GetProperty("IsCalc") +End Property ' SFDocuments.SF_FormDocument.IsCalc + +REM ----------------------------------------------------------------------------- +Property Get IsDraw() As Boolean + IsDraw = [_Super].GetProperty("IsDraw") +End Property ' SFDocuments.SF_FormDocument.IsDraw + +REM ----------------------------------------------------------------------------- +Property Get IsFormDocument() As Boolean + IsFormDocument = [_Super].GetProperty("IsFormDocument") +End Property ' SFDocuments.SF_Writer.IsFormDocument + +REM ----------------------------------------------------------------------------- +Property Get IsImpress() As Boolean + IsImpress = [_Super].GetProperty("IsImpress") +End Property ' SFDocuments.SF_FormDocument.IsImpress + +REM ----------------------------------------------------------------------------- +Property Get IsMath() As Boolean + IsMath = [_Super].GetProperty("IsMath") +End Property ' SFDocuments.SF_FormDocument.IsMath + +REM ----------------------------------------------------------------------------- +Property Get Readonly() As Variant + Readonly = [_Super].GetProperty("Readonly") +End Property ' SFDocuments.SF_FormDocument.Readonly + +REM ----------------------------------------------------------------------------- +Property Get XComponent() As Variant + XComponent = [_Super].GetProperty("XComponent") +End Property ' SFDocuments.SF_FormDocument.XComponent + +REM ========================================================== SUPERCLASS METHODS + +REM ----------------------------------------------------------------------------- +Public Function Activate() As Boolean + Activate = [_Super].Activate() +End Function ' SFDocuments.SF_FormDocument.Activate + +REM ----------------------------------------------------------------------------- +Public Function CreateMenu(Optional ByVal MenuHeader As Variant _ + , Optional ByVal Before As Variant _ + , Optional ByVal SubmenuChar As Variant _ + ) As Object + Set CreateMenu = [_Super].CreateMenu(MenuHeader, Before, SubmenuChar) +End Function ' SFDocuments.SF_FormDocument.CreateMenu + +REM ----------------------------------------------------------------------------- +Public Function ExportAsPDF(Optional ByVal FileName As Variant _ + , Optional ByVal Overwrite As Variant _ + , Optional ByVal Pages As Variant _ + , Optional ByVal Password As Variant _ + , Optional ByVal Watermark As Variant _ + ) As Boolean + ExportAsPDF = [_Super].ExportAsPDF(FileName, Overwrite, Pages, Password, Watermark) +End Function ' SFDocuments.SF_FormDocument.ExportAsPDF + +REM ----------------------------------------------------------------------------- +Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean + RemoveMenu = [_Super].RemoveMenu(MenuHeader) +End Function ' SFDocuments.SF_FormDocument.RemoveMenu + +REM ----------------------------------------------------------------------------- +Public Sub RunCommand(Optional ByVal Command As Variant _ + , ParamArray Args As Variant _ + ) + [_Super].RunCommand(Command, Args) +End Sub ' SFDocuments.SF_FormDocument.RunCommand + +REM ----------------------------------------------------------------------------- +Public Function SaveCopyAs(Optional ByVal FileName As Variant _ + , Optional ByVal Overwrite As Variant _ + , Optional ByVal Password As Variant _ + , Optional ByVal FilterName As Variant _ + , Optional ByVal FilterOptions As Variant _ + ) As Boolean + SaveCopyAs = [_Super].SaveCopyAs(FileName, Overwrite, Password, FilterName, FilterOptions) +End Function ' SFDocuments.SF_FormDocument.SaveCopyAs + +REM ----------------------------------------------------------------------------- +Public Function SetPrinter(Optional ByVal Printer As Variant _ + , Optional ByVal Orientation As Variant _ + , Optional ByVal PaperFormat As Variant _ + ) As Boolean + SetPrinter = [_Super].SetPrinter(Printer, Orientation, PaperFormat) +End Function ' SFDocuments.SF_FormDocument.SetPrinter + +REM =========================================================== PRIVATE FUNCTIONS + +REM ----------------------------------------------------------------------------- +Private Function _FileIdent() As String +''' Returns a file identification from the information that is currently available +''' Useful e.g. for display in error messages + + _FileIdent = [_Super]._FileIdent() + +End Function ' SFDocuments.SF_FormDocument._FileIdent + +REM ----------------------------------------------------------------------------- +Public Sub _Initialize() +''' Achieve the creation of a SF_Form instance +''' - the database file +''' - the database connection +''' the internal and external names + +Dim oBase As Object ' A temporary Base instance + + On Local Error GoTo Catch + +Try: + ' Base file where form document is stored + Set _BaseComponent = _Component.Parent + + ' Connection arguments + Set _DataSource = _BaseComponent.DataSource + With _DataSource + _User = .User + _Password = .Password + End With + + ' External and internal names + _PersistentName = ScriptForge.SF_Utils._GetPropertyValue(_Component.Args, "HierarchicalDocumentName") + Set oBase = New SF_Base ' Only to be able to call the _FindByPersistentName() method + With oBase + Set _FormDocument = ._FindByPersistentName(_BaseComponent.getFormDocuments(), _PersistentName) + _HierarchicalName = _FormDocument.HierarchicalName + Set oBase = .Dispose() + End With + +Finally: + Exit Sub +Catch: + On Local Error GoTo 0 + GoTo Finally +End Sub ' SFDocuments.SF_FormDocument._Initialize + +REM ----------------------------------------------------------------------------- +Private Function _IsStillAlive(Optional ByVal pbForUpdate As Boolean _ + , Optional ByVal pbError As Boolean _ + ) As Boolean +''' Returns True if the document has not been closed manually or incidentally since the last use +''' If dead the actual instance is disposed. The execution is cancelled when pbError = True (default) +''' Args: +''' pbForUpdate: if True (default = False), check additionally if document is open for editing +''' pbError: if True (default), raise a fatal error + +Dim bAlive As Boolean ' Return value + + If IsMissing(pbForUpdate) Then pbForUpdate = False + If IsMissing(pbError) Then pbError = True + +Try: + bAlive = [_Super]._IsStillAlive(pbForUpdate, pbError) + +Finally: + _IsStillAlive = bAlive + Exit Function +End Function ' SFDocuments.SF_FormDocument._IsStillAlive + +REM ----------------------------------------------------------------------------- +Private Function _PropertyGet(Optional ByVal psProperty As String _ + , Optional ByVal pvArg As Variant _ + ) As Variant +''' Return the value of the named property +''' Args: +''' psProperty: the name of the property + +Dim cstThisSub As String +Const cstSubArgs = "" + + _PropertyGet = False + + cstThisSub = "SFDocuments.FormDocument.get" & psProperty + ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) + If Not _IsStillAlive() Then GoTo Finally + + Select Case psProperty + Case Else + _PropertyGet = Null + End Select + +Finally: + ScriptForge.SF_Utils._ExitFunction(cstThisSub) + Exit Function +End Function ' SFDocuments.SF_FormDocument._PropertyGet + +REM ----------------------------------------------------------------------------- +Private Function _Repr() As String +''' Convert the SF_FormDocument instance to a readable string, typically for debugging purposes (DebugPrint ...) +''' Args: +''' Return: +''' "[DOCUMENT]: Type/File" + + _Repr = "[FormDocument]: " & [_Super]._FileIdent() + +End Function ' SFDocuments.SF_FormDocument._Repr + +REM ============================================ END OF SFDOCUMENTS.SF_FORMDOCUMENT + \ No newline at end of file diff --git a/wizards/source/sfdocuments/SF_Register.xba b/wizards/source/sfdocuments/SF_Register.xba index 5baf37afb484..c2a58bc61a8d 100644 --- a/wizards/source/sfdocuments/SF_Register.xba +++ b/wizards/source/sfdocuments/SF_Register.xba @@ -69,6 +69,7 @@ Public Sub RegisterScriptServices() As Variant .RegisterService("Base", "SFDocuments.SF_Register._NewDocument") ' Same reference, distinction is made inside the function .RegisterService("Calc", "SFDocuments.SF_Register._NewDocument") ' Same reference, distinction is made inside the function .RegisterService("Writer", "SFDocuments.SF_Register._NewDocument") ' Same reference, distinction is made inside the function + .RegisterService("FormDocument", "SFDocuments.SF_Register._NewDocument") ' Same reference, distinction is made inside the function .RegisterEventManager("DocumentEvent", "SFDocuments.SF_Register._EventManager") ' Reference to the events manager .RegisterEventManager("FormEvent", "SFDocuments.SF_Register._FormEventManager")' Reference to the form and controls events manager End With @@ -408,6 +409,11 @@ Try: Set oSuperDocument = New SF_Document Set oDocument.[_Super] = oSuperDocument ' Now both super and subclass are twinned Set oSuperDocument.[_SubClass] = oDocument + Case "FormDocument" + Set oDocument = New SF_FormDocument + Set oSuperDocument = New SF_Document + Set oDocument.[_Super] = oSuperDocument ' Now both super and subclass are twinned + Set oSuperDocument.[_SubClass] = oDocument Case "Writer" Set oDocument = New SF_Writer Set oSuperDocument = New SF_Document @@ -424,6 +430,8 @@ Try: Select Case vWindow.DocumentType Case "Base" Set ._DataSource = ._Component.DataSource + Case "FormDocument" + ._Initialize() Case Else End Select End With diff --git a/wizards/source/sfdocuments/SF_Writer.xba b/wizards/source/sfdocuments/SF_Writer.xba index eded35de9a96..6f3f258dcb75 100644 --- a/wizards/source/sfdocuments/SF_Writer.xba +++ b/wizards/source/sfdocuments/SF_Writer.xba @@ -47,7 +47,7 @@ Option Explicit ''' TBD ''' ''' Detailed user documentation: -''' https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/SF_Writer.html?DbPAR=BASIC +''' https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_writer.html?DbPAR=BASIC ''' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' @@ -68,6 +68,8 @@ Private _Component As Object ' com.sun.star.lang.XComponent REM ============================================================ MODULE CONSTANTS +Const ISDOCFORM = 1 ' Form is stored in a Writer document + REM ====================================================== CONSTRUCTOR/DESTRUCTOR REM ----------------------------------------------------------------------------- @@ -312,6 +314,7 @@ Public Function Properties() As Variant , "IsBase" _ , "IsCalc" _ , "IsDraw" _ + , "IsFormDocument" _ , "IsImpress" _ , "IsMath" _ , "IsWriter" _ @@ -429,6 +432,11 @@ Property Get IsDraw() As Boolean IsDraw = [_Super].GetProperty("IsDraw") End Property ' SFDocuments.SF_Writer.IsDraw +REM ----------------------------------------------------------------------------- +Property Get IsFormDocument() As Boolean + IsFormDocument = [_Super].GetProperty("IsFormDocument") +End Property ' SFDocuments.SF_Writer.IsFormDocument + REM ----------------------------------------------------------------------------- Property Get IsImpress() As Boolean IsImpress = [_Super].GetProperty("IsImpress") diff --git a/wizards/source/sfdocuments/script.xlb b/wizards/source/sfdocuments/script.xlb index ff4495124f98..6945460dda77 100644 --- a/wizards/source/sfdocuments/script.xlb +++ b/wizards/source/sfdocuments/script.xlb @@ -11,4 +11,5 @@ + \ No newline at end of file diff --git a/wizards/source/sfwidgets/SF_MenuListener.xba b/wizards/source/sfwidgets/SF_MenuListener.xba index 9ab018f77b8b..cb7839de5804 100644 --- a/wizards/source/sfwidgets/SF_MenuListener.xba +++ b/wizards/source/sfwidgets/SF_MenuListener.xba @@ -88,7 +88,10 @@ Try: End With If Len(sCommand) > 0 Then - Set oFrame = StarDesktop.ActiveFrame ' A menu has been clicked necessarily in the current window + ' A menu has been clicked necessarily in the current window (Document) or one of its subcomponents (FormDocument) + Set oFrame = StarDesktop.ActiveFrame + If oFrame.Frames.Count > 0 Then Set oFrame = oFrame.getActiveFrame() + ' Command or script ? If Left(sCommand, Len(cstUnoPrefix)) = cstUnoPrefix Then ' Execute uno command Set oDispatcher = ScriptForge.SF_Utils._GetUNOService("DispatchHelper") @@ -124,5 +127,5 @@ Sub _SFMENU_disposing(Optional poEvent As Object) ' com.sun.star.awt.Menu Exit Sub End Sub ' SFWidgets.SF_MenuListener._SFMENU_disposing -REM ============================================ END OF SFDIALOGS.SF_DIALOGLISTENER +REM ============================================ END OF SFWIDGETS.SF_MENULISTENER \ No newline at end of file