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 <jp@ledure.be>
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Tested-by: Jenkins
This commit is contained in:
Jean-Pierre Ledure 2023-01-05 13:47:01 +01:00
parent b4c3291630
commit 88a67c50af
16 changed files with 908 additions and 63 deletions

View file

@ -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 \

View file

@ -814,6 +814,8 @@ Try:
End Select
Case &quot;SFDocuments.FormControl&quot;
If Script = &quot;Controls&quot; Then vReturn = vBasicObject.Controls(vArgs(0))
Case &quot;SFDocuments.FormDocument&quot;
If Script = &quot;Forms&quot; Then vReturn = vBasicObject.Forms(vArgs(0))
End Select
End If

View file

@ -126,7 +126,7 @@ Try:
sService = vSplit(0)
&apos; Accept other default values for associated libraries
Select Case LCase(sService)
Case &quot;document&quot;, &quot;calc&quot;, &quot;writer&quot;, &quot;base&quot;, &quot;documentevent&quot;, &quot;formevent&quot;
Case &quot;document&quot;, &quot;calc&quot;, &quot;writer&quot;, &quot;base&quot;, &quot;formdocument&quot;, &quot;documentevent&quot;, &quot;formevent&quot;
sLibrary = &quot;SFDocuments&quot;
Case &quot;dialog&quot;, &quot;dialogevent&quot; : sLibrary = &quot;SFDialogs&quot;
Case &quot;database&quot;, &quot;datasheet&quot; : sLibrary = &quot;SFDatabases&quot;

View file

@ -69,6 +69,7 @@ Const WELCOMESCREEN = &quot;WELCOMESCREEN&quot;
Const BASEDOCUMENT = &quot;Base&quot;
Const CALCDOCUMENT = &quot;Calc&quot;
Const DRAWDOCUMENT = &quot;Draw&quot;
Const FORMDOCUMENT = &quot;FormDocument&quot;
Const IMPRESSDOCUMENT = &quot;Impress&quot;
Const MATHDOCUMENT = &quot;Math&quot;
Const WRITERDOCUMENT = &quot;Writer&quot;
@ -1303,6 +1304,7 @@ Dim FSO As Object &apos; Alias for SF_FileSystem
If SF_Session.HasUnoProperty(poComponent, &quot;Title&quot;) Then .WindowTitle = poComponent.Title
Select Case sIdentifier
Case &quot;com.sun.star.sdb.FormDesign&quot; &apos; Form
.DocumentType = FORMDOCUMENT
Case &quot;com.sun.star.sdb.TextReportDesign&quot; &apos; Report
Case &quot;com.sun.star.text.TextDocument&quot; &apos; Writer
.DocumentType = WRITERDOCUMENT

View file

@ -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

View file

@ -69,6 +69,8 @@ Private _MetaData As Object &apos; com.sun.star.sdbc.XDatabaseMetaData
REM ============================================================ MODULE CONSTANTS
Const cstToken = &quot;//&quot; &apos; Form names accept special characters but not slashes
REM ===================================================== CONSTRUCTOR/DESTRUCTOR
REM -----------------------------------------------------------------------------
@ -401,6 +403,7 @@ Public Function Methods() As Variant
, &quot;DMin&quot; _
, &quot;DSum&quot; _
, &quot;GetRows&quot; _
, &quot;OpenFormDocument&quot; _
, &quot;OpenQuery&quot; _
, &quot;OpenSql&quot; _
, &quot;OpenTable&quot; _
@ -409,6 +412,56 @@ Public Function Methods() As Variant
End Function &apos; SFDatabases.SF_Database.Methods
REM -----------------------------------------------------------------------------
Public Function OpenFormDocument(Optional ByVal FormDocument As Variant) As Object
&apos;&apos;&apos; Open the FormDocument given by its hierarchical name in normal mode
&apos;&apos;&apos; If the form document is already open, the form document is made active
&apos;&apos;&apos; Args:
&apos;&apos;&apos; FormDocument: a valid form document name as a case-sensitive string
&apos;&apos;&apos; When hierarchical, the hierarchy must be rendered with forward slashes (&quot;/&quot;)
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; A FormDocument instance or Nothing
&apos;&apos;&apos; Exceptions:
&apos;&apos;&apos; Form name is invalid
&apos;&apos;&apos; Example:
&apos;&apos;&apos; Set oForm = oDb.OpenFormDocument(&quot;Folder1/myFormDocument&quot;)
Dim oOpen As Object &apos; Return value
Dim oFormDocuments As Variant &apos; com.sun.star.comp.dba.ODocumentContainer
Dim vFormNames As Variant &apos; Array of all document form names present in the document
Dim vOpenArgs As Variant &apos; Array of property values
Dim oNewForm As Object &apos; Output of loadComponent()
Const cstThisSub = &quot;SFDatabases.Database.OpenFormDocument&quot;
Const cstSubArgs = &quot;FormDocument&quot;
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oOpen = Nothing
Check:
&apos; 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, &quot;FormDocument&quot;, V_STRING, vFormNames) Then GoTo Finally
End If
Try:
vOpenArgs = Array(SF_Utils._MakePropertyValue(&quot;ActiveConnection&quot;, _Connection) _
, SF_Utils._MakePropertyValue(&quot;OpenMode&quot;, &quot;open&quot;) _
)
Set oNewForm = oFormDocuments.loadComponentFromURL(FormDocument, &quot;&quot;, 0, vOpenArgs)
Set oOpen = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.FormDocument&quot;, oNewForm)
Finally:
Set OpenFormDocument = oOpen
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
Catch:
GoTo Finally
End Function &apos; SF_Databases.SF_Database.OpenFormDocument
REM -----------------------------------------------------------------------------
Public Function OpenQuery(Optional ByVal QueryName As Variant) As Object
&apos;&apos;&apos; Open the query given by its name
@ -632,6 +685,44 @@ End Function &apos; SFDatabases.SF_Database.SetProperty
REM =========================================================== PRIVATE FUNCTIONS
REM -----------------------------------------------------------------------------
Private Function _CollectFormDocuments(ByRef poContainer As Object) As String
&apos;&apos;&apos; Returns a token-separated string of all hierarchical formdocument names
&apos;&apos;&apos; depending on the formdocuments container in argument
&apos;&apos;&apos; The function traverses recursively the whole tree below the container
&apos;&apos;&apos; The initial call starts from the container _Component.getFormDocuments
&apos;&apos;&apos; The list contains closed and open forms
Dim sCollectNames As String &apos; Return value
Dim oSubItem As Object &apos; com.sun.star.container.XNameAccess (folder) or com.sun.star.ucb.XContent (form)
Dim i As Long
Const cstFormType = &quot;application/vnd.oasis.opendocument.text&quot;
&apos; Identifies forms. Folders have a zero-length content type
On Local Error GoTo Finally
Try:
sCollectNames = &quot;&quot;
With poContainer
For i = 0 To .Count - 1
Set oSubItem = .getByIndex(i)
If oSubItem.ContentType = cstFormType Then &apos; Add the form to the list
sCollectNames = sCollectNames &amp; cstToken &amp; oSubItem.HierarchicalName
Else
sCollectNames = sCollectNames &amp; cstToken &amp; _CollectFormDocuments(oSubItem)
End If
Next i
End With
Finally:
If Len(sCollectNames) &gt; 0 Then
_CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) &apos; Skip the initial token
Else
_CollectFormDocuments = &quot;&quot;
End If
Exit Function
End Function &apos; SFDocuments.SF_Base._CollectFormDocuments
REM -----------------------------------------------------------------------------------------------------------------------
Private Function _DFunction(ByVal psFunction As String _
, Optional ByVal pvExpression As Variant _

View file

@ -145,6 +145,7 @@ Public Function CloseFormDocument(Optional ByVal FormDocument As Variant) As Boo
&apos;&apos;&apos; True if closure is successful
&apos;&apos;&apos; Example:
&apos;&apos;&apos; oDoc.CloseFormDocument(&quot;Folder1/myFormDocument&quot;)
&apos;&apos;&apos; DEPRECATED - Use preferably the CloseDocument() method of the FormDocument service
Dim bClose As Boolean &apos; Return value
Dim oMainForm As Object &apos; com.sun.star.comp.sdb.Content
@ -235,6 +236,7 @@ Public Function Forms(Optional ByVal FormDocument As Variant _
&apos;&apos;&apos; Dim myForm As Object, myList As Variant
&apos;&apos;&apos; myList = oDoc.Forms(&quot;Folder1/myFormDocument&quot;)
&apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;Folder1/myFormDocument&quot;, 0)
&apos;&apos;&apos; DEPRECATED - Use preferably the Forms() method of the FormDocument service
Dim oForm As Object &apos; The new Form class instance
Dim oFormDocument As Object &apos; 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 &apos; SFDocuments.SF_Base.Methods
REM -----------------------------------------------------------------------------
Public Function OpenFormDocument(Optional ByVal FormDocument As Variant _
, Optional ByVal DesignMode As Variant _
) As Boolean
) As Object
&apos;&apos;&apos; Open the FormDocument given by its hierarchical name either in normal or in design mode
&apos;&apos;&apos; If the form document is already open, the form document is made active without changing its mode
&apos;&apos;&apos; Args:
&apos;&apos;&apos; FormDocument: a valid form document name as a case-sensitive string
&apos;&apos;&apos; When hierarchical, the hierarchy must be rendered with forward slashes (&quot;/&quot;)
&apos;&apos;&apos; DesignMode: when True the form document is opened in design mode (Default = False)
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; True if the form document could be opened, otherwise False
&apos;&apos;&apos; A FormDocument instance or Nothing
&apos;&apos;&apos; Exceptions:
&apos;&apos;&apos; Form name is invalid
&apos;&apos;&apos; Example:
&apos;&apos;&apos; oDoc.OpenFormDocument(&quot;Folder1/myFormDocument&quot;)
&apos;&apos;&apos; Set oForm = oDoc.OpenFormDocument(&quot;Folbder1/myFormDocument&quot;)
Dim bOpen As Boolean &apos; Return value
Dim oOpen As Object &apos; Return value
Dim vFormNames As Variant &apos; Array of all document form names present in the document
Dim oContainer As Object &apos; com.sun.star.awt.XWindow
Dim oNewForm As Object &apos; Output of loadComponent()
Const cstThisSub = &quot;SFDocuments.Base.OpenFormDocument&quot;
Const cstSubArgs = &quot;FormDocument, [DesignMode=False]&quot;
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() &lt;&gt; DesignMode Then .setFormDesignMode(DesignMode)
End With
End With
bOpen = True
Set oOpen = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.FormDocument&quot;, 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 _
&apos;&apos;&apos; True when successful
&apos;&apos;&apos; Examples:
&apos;&apos;&apos; oDoc.PrintOut(&quot;myForm&quot;, &quot;1-4;10;15-18&quot;, Copies := 2)
&apos;&apos;&apos; DEPRECATED - Use preferably the PrintOut() method of the FormDocument service
Dim bPrint As Boolean &apos; Return value
Dim vFormNames As Variant &apos; Array of all document form names present in the document
@ -681,6 +686,7 @@ Public Function Properties() As Variant
, &quot;IsBase&quot; _
, &quot;IsCalc&quot; _
, &quot;IsDraw &quot; _
, &quot;IsFormDocument&quot; _
, &quot;IsImpress&quot; _
, &quot;IsMath&quot; _
, &quot;IsWriter&quot; _
@ -708,6 +714,7 @@ Public Function SetPrinter(Optional ByVal FormDocument As Variant _
&apos;&apos;&apos; True when successful
&apos;&apos;&apos; Examples:
&apos;&apos;&apos; oDoc.SetPrinter(&quot;myForm&quot;, Orientation := &quot;PORTRAIT&quot;)
&apos;&apos;&apos; DEPRECATED - Use preferably the SetPrinter() method of the FormDocument service
Dim bPrinter As Boolean &apos; Return value
Dim vFormDocuments As Variant &apos; Array of form documents
@ -829,6 +836,11 @@ Property Get IsDraw() As Boolean
IsDraw = [_Super].GetProperty(&quot;IsDraw&quot;)
End Property &apos; SFDocuments.SF_Base.IsDraw
REM -----------------------------------------------------------------------------
Property Get IsFormDocument() As Boolean
IsFormDocument = [_Super].GetProperty(&quot;IsFormDocument&quot;)
End Property &apos; SFDocuments.SF_Writer.IsFormDocument
REM -----------------------------------------------------------------------------
Property Get IsImpress() As Boolean
IsImpress = [_Super].GetProperty(&quot;IsImpress&quot;)
@ -968,7 +980,11 @@ Try:
End With
Finally:
_CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) &apos; Skip the initial token
If Len(sCollectNames) &gt; 0 Then
_CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) &apos; Skip the initial token
Else
_CollectFormDocuments = &quot;&quot;
End If
Exit Function
End Function &apos; SFDocuments.SF_Base._CollectFormDocuments

View file

@ -2556,6 +2556,7 @@ Public Function Properties() As Variant
, &quot;IsBase&quot; _
, &quot;IsCalc&quot; _
, &quot;IsDraw&quot; _
, &quot;IsFormDocument&quot; _
, &quot;IsImpress&quot; _
, &quot;IsMath&quot; _
, &quot;IsWriter&quot; _
@ -3482,6 +3483,11 @@ Property Get IsDraw() As Boolean
IsDraw = [_Super].GetProperty(&quot;IsDraw&quot;)
End Property &apos; SFDocuments.SF_Calc.IsDraw
REM -----------------------------------------------------------------------------
Property Get IsFormDocument() As Boolean
IsFormDocument = [_Super].GetProperty(&quot;IsFormDocument&quot;)
End Property &apos; SFDocuments.SF_Writer.IsFormDocument
REM -----------------------------------------------------------------------------
Property Get IsImpress() As Boolean
IsImpress = [_Super].GetProperty(&quot;IsImpress&quot;)

View file

@ -268,6 +268,11 @@ Property Get IsDraw() As Boolean
IsDraw = _PropertyGet(&quot;IsDraw&quot;)
End Property &apos; SFDocuments.SF_Document.IsDraw
REM -----------------------------------------------------------------------------
Property Get IsFormDocument() As Boolean
IsFormDocument = _PropertyGet(&quot;IsFormDocument&quot;)
End Property &apos; SFDocuments.SF_Document.IsFormDocument
REM -----------------------------------------------------------------------------
Property Get IsImpress() As Boolean
IsImpress = _PropertyGet(&quot;IsImpress&quot;)
@ -459,7 +464,7 @@ Try:
If SaveAsk And _Component.IsModified Then &apos; Execute closure with the File/Close menu command
Activate()
RunCommand(&quot;CloseDoc&quot;)
bClosed = _IsStillAlive(, False) &apos; Do not raise error
bClosed = Not _IsStillAlive(, False) &apos; 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 &apos; SFDocuments.SF_Document.CloseDocument
@ -592,7 +598,10 @@ Check:
Try:
&apos; Setup arguments
sFilter = LCase(_DocumentType) &amp; &quot;_pdf_Export&quot;
Select Case _DocumentType &apos; Disguise form documents as a Writer document
Case &quot;FormDocument&quot; : sFilter = &quot;Writer_pdf_Export&quot;
Case Else : sFilter = LCase(_DocumentType) &amp; &quot;_pdf_Export&quot;
End Select
&apos; FilterData parameters are added only if they are meaningful
vFilterData = Array()
If Len(Pages) &gt; 0 Then
@ -751,6 +760,7 @@ Public Function Properties() As Variant
, &quot;IsBase&quot; _
, &quot;IsCalc&quot; _
, &quot;IsDraw&quot; _
, &quot;IsFormDocument&quot; _
, &quot;IsImpress&quot; _
, &quot;IsMath&quot; _
, &quot;IsWriter&quot; _
@ -1471,7 +1481,7 @@ Const cstSubArgs = &quot;&quot;
_PropertyGet = _GetFilterNames(True)
Case &quot;ImportFilters&quot;
_PropertyGet = _GetFilterNames(False)
Case &quot;IsBase&quot;, &quot;IsCalc&quot;, &quot;IsDraw&quot;, &quot;IsImpress&quot;, &quot;IsMath&quot;, &quot;IsWriter&quot;
Case &quot;IsBase&quot;, &quot;IsCalc&quot;, &quot;IsDraw&quot;, &quot;IsFormDocument&quot;, &quot;IsImpress&quot;, &quot;IsMath&quot;, &quot;IsWriter&quot;
_PropertyGet = ( Mid(psProperty, 3) = _DocumentType )
Case &quot;Keywords&quot;
_PropertyGet = Join(_Component.DocumentProperties.Keywords, &quot;, &quot;)

View file

@ -23,8 +23,8 @@ Option Explicit
&apos;&apos;&apos;
&apos;&apos;&apos; Definitions:
&apos;&apos;&apos;
&apos;&apos;&apos; FormDocument:
&apos;&apos;&apos; For usual documents, there is only 1 form document. It is in fact the document itself.
&apos;&apos;&apos; FormDocument: BASE DOCUMENTS ONLY
&apos;&apos;&apos; For usual documents, there is only 1 forms cpntainer. It is either the document itself or one of its sheets (Calc)
&apos;&apos;&apos; A Base document may contain an unlimited number of form documents.
&apos;&apos;&apos; In the Base terminology they are called &quot;forms&quot; or &quot;Base forms&quot;. This could create some confusion.
&apos;&apos;&apos; They can be organized in folders. Their name is then always the full path of folders + form
@ -34,29 +34,36 @@ Option Explicit
&apos;&apos;&apos; the user experience significantly
&apos;&apos;&apos;
&apos;&apos;&apos; Form: WHERE IT IS ABOUT IN THE CURRENT &quot;Form&quot; SERVICE
&apos;&apos;&apos; Is an abstract set of Controls in an OPEN FormDocument
&apos;&apos;&apos; Is an abstract set of Controls in an OPEN Document or FormDocument
&apos;&apos;&apos; Each form is usually linked to one single dataset (table, query or Select statement),
&apos;&apos;&apos; located in any database (provided the user may access it)
&apos;&apos;&apos; A usual document may contain several forms. Each of which may have its own data source (database + dataset)
&apos;&apos;&apos; A Base form document may contain several forms. Each of which may address its own dataset. The database however is unique
&apos;&apos;&apos; A form is defined by its owning FormDocument and its FormName or FormIndex
&apos;&apos;&apos; A form is defined by its owning Document or FormDocument and its FormName or FormIndex
&apos;&apos;&apos;
&apos;&apos;&apos; Service invocations:
&apos;&apos;&apos;
&apos;&apos;&apos; REM the form is stored in a not-Base document (Calc, Writer)
&apos;&apos;&apos; REM the form is stored in a Writer document
&apos;&apos;&apos; Dim oDoc As Object, myForm As Object
&apos;&apos;&apos; Set oDoc = CreateScriptService(&quot;SFDocuments.Document&quot;, ThisComponent)
&apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;Form1&quot;)
&apos;&apos;&apos; &apos; or, alternatively, when there is only 1 form
&apos;&apos;&apos; Set myForm = oDoc.Forms(0)
&apos;&apos;&apos;
&apos;&apos;&apos; REM the form is stored in one of the FormDocuments of a Base document
&apos;&apos;&apos; Dim oDoc As Object, myForm As Object, mySubForm As Object
&apos;&apos;&apos; Set oDoc = CreateScriptService(&quot;SFDocuments.Document&quot;, ThisDatabaseDocument)
&apos;&apos;&apos; oDoc.OpenFormDocument(&quot;thisFormDocument&quot;)
&apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;thisFormDocument&quot;, &quot;MainForm&quot;)
&apos;&apos;&apos; REM the form is stored in a Calc document
&apos;&apos;&apos; Dim oCalc As Object, myForm As Object
&apos;&apos;&apos; Set oCalc = CreateScriptService(&quot;SFDocuments.Document&quot;, ThisComponent)
&apos;&apos;&apos; Set myForm = oCalc.Forms(&quot;Sheet1&quot;, &quot;Form1&quot;)
&apos;&apos;&apos; &apos; or, alternatively, when there is only 1 form
&apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;thisFormDocument&quot;, 0)
&apos;&apos;&apos; Set myForm = oCalc.Forms(&quot;Sheet1&quot;, 0)
&apos;&apos;&apos;
&apos;&apos;&apos; REM the form is stored in one of the FormDocuments of a Base document
&apos;&apos;&apos; Dim oBase As Object, myFormDoc As Object, myForm As Object, mySubForm As Object
&apos;&apos;&apos; Set oBase = CreateScriptService(&quot;SFDocuments.Document&quot;, ThisDatabaseDocument)
&apos;&apos;&apos; Set oFormDoc = oBase.OpenFormDocument(&quot;thisFormDocument&quot;)
&apos;&apos;&apos; Set myForm = oFormDoc.Forms(&quot;MainForm&quot;)
&apos;&apos;&apos; &apos; or, alternatively, when there is only 1 form
&apos;&apos;&apos; Set myForm = oFormDoc.Forms(0)
&apos;&apos;&apos; &apos; To access a subform: myForm and mySubForm become distinct instances of the current class
&apos;&apos;&apos; Set mySubForm = myForm.SubForms(&quot;mySubForm&quot;)
&apos;&apos;&apos;
@ -87,9 +94,10 @@ Private _Name As String &apos; Internal name of the form
Private _FormType As Integer &apos; One of the ISxxxFORM constants
Private _SheetName As String &apos; Name as the sheet containing the form (Calc only)
Private _FormDocumentName As String &apos; The hierarchical name of the containing form document (Base only)
Private _FormDocument As Object &apos; com.sun.star.comp.sdb.Content - the containing form document
&apos; The form topmost container
Private _Component As Object &apos; com.sun.star.lang.XComponent or com.sun.star.comp.dba.ODatabaseDocument
Private _FormDocument As Object &apos; com.sun.star.comp.sdb.Content - the form document container
&apos; The form topmost containers
Private _Component As Object &apos; com.sun.star.lang.XComponent
Private _BaseComponent As Object &apos; com.sun.star.comp.dba.ODatabaseDocument
&apos; Events management
Private _CacheIndex As Long &apos; Index in central cache storage
@ -98,9 +106,9 @@ Private _CacheIndex As Long &apos; Index in central cache storage
&apos; The entry to the interactions with the form. Validity checked by the _IsStillAlive() method
&apos; Each method or property requiring that the form is opened should first invoke that method
Private _Form As Object &apos; com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
Private _Database As Object &apos; Database class instance
&apos; Form attributes
Private _Database As Object &apos; Database class instance
&apos; Cache storage for controls
Private _ControlNames As Variant &apos; Array of control names
@ -110,7 +118,7 @@ REM ============================================================ MODULE CONSTANT
Const ISDOCFORM = 1 &apos; Form is stored in a Writer document
Const ISCALCFORM = 2 &apos; Form is stored in a Calc document
Const ISBASEFORM = 3 &apos; Form is stored in a Base document
Const ISBASEFORM = 3 &apos; Form is stored in a Base form document
Const ISSUBFORM = 4 &apos; Form is a subform of a form or of another subform
Const ISUNDEFINED = -1 &apos; Undefined form type
@ -126,6 +134,8 @@ Private Sub Class_Initialize()
_SheetName = &quot;&quot;
_FormDocumentName = &quot;&quot;
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 = &quot;&quot;
If IsMissing(Password) Or IsEmpty(Password) Then Password = &quot;&quot;
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, &quot;User&quot;, V_STRING) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Password, &quot;Password&quot;, V_STRING) Then GoTo Finally
End If
@ -691,7 +704,7 @@ Try:
&apos; Connect to database, avoiding multiple requests
If IsNull(_Database) Then &apos; 1st connection request from the current form instance
If _FormType = ISBASEFORM Then
If _FormType = ISBASEFORM And Not IsNull(_BaseComponent) Then
&apos; 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 &apos; Successive bottom-up parents
Dim sType As String &apos; UNO object type
Dim sPersistentName As String &apos; The Obj... name of a Base form
Dim iLevel As Integer &apos; When = 1 =&gt; first parent
Dim oBase As Object &apos; Empty Base instance
Dim oSession As Object : Set oSession = ScriptForge.SF_Session
On Local Error GoTo Finally &apos; Being probably called from events, this method should avoid failures
@ -1243,12 +1257,15 @@ Try:
Case &quot;com.sun.star.form.OFormsCollection&quot; &apos; The collection of forms inside a drawpage
Case &quot;SwXTextDocument&quot; &apos; The parent document: a Writer document or a Base form document
If oParent.Identifier = &quot;com.sun.star.sdb.FormDesign&quot; Then
sPersistentName = ScriptForge._GetPropertyValue(oParent.Args, &quot;HierarchicalDocumentName&quot;)
_FormType = ISBASEFORM
&apos; Make a new SF_FormDocument instance
Set [_Parent] = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.FormDocument&quot;, oParent)
Set _FormDocument = [_Parent]._FormDocument
ElseIf oParent.Identifier = &quot;com.sun.star.text.TextDocument&quot; Then
_FormType = ISDOCFORM
Set [_Parent] = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.Document&quot;, oParent)
Set _Component = [_Parent]._Component
End If
Set _Component = oParent
Case &quot;ScModelObj&quot; &apos; The parent document: a Calc document
_FormType = ISCALCFORM
Set [_Parent] = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.Document&quot;, oParent)
@ -1256,12 +1273,6 @@ Try:
&apos; The triggered form event is presumed to be located in the (drawpage of the) active sheet
_SheetName = [_Parent].XSpreadsheet(&quot;~&quot;)
Case &quot;com.sun.star.comp.dba.ODatabaseDocument&quot; &apos; The Base document
_FormType = ISBASEFORM
Set [_Parent] = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.Document&quot;, 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, &quot;Parent&quot;) Then Set oParent = oParent.Parent Else Set oParent = Nothing

View file

@ -13,7 +13,8 @@ Option Explicit
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
&apos;&apos;&apos; SF_FormControl
&apos;&apos;&apos; ================
&apos;&apos;&apos; ==============
&apos;&apos;&apos;
&apos;&apos;&apos; Manage the controls belonging to a form or subform stored in a document
&apos;&apos;&apos; Each instance of the current class represents a single control within a form, a subform or a tablecontrol
&apos;&apos;&apos; A prerequisite is that all controls within the same form, subform or tablecontrol must have
@ -1131,7 +1132,7 @@ Try:
End With
&apos; Store the SF_FormControl object in the parent cache
Set _Parent._ControlCache(_IndexOfNames) = [Me]
Set [_Parent]._ControlCache(_IndexOfNames) = [Me]
Finally:
Exit Sub

View file

@ -0,0 +1,642 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_FormDocument" script:language="StarBasic" script:moduleType="normal">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
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
&apos;&apos;&apos; SF_FormDocument
&apos;&apos;&apos; ===============
&apos;&apos;&apos;
&apos;&apos;&apos; The SFDocuments library gathers a number of methods and properties making easy
&apos;&apos;&apos; managing and manipulating LibreOffice documents
&apos;&apos;&apos;
&apos;&apos;&apos; Some methods are generic for all types of documents: they are combined in the SF_Document module.
&apos;&apos;&apos; Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Writer, SF_Base, ...
&apos;&apos;&apos;
&apos;&apos;&apos; To workaround the absence of class inheritance in LibreOffice Basic, some redundancy is necessary
&apos;&apos;&apos; Each subclass MUST implement also the generic methods and properties, even if they only call
&apos;&apos;&apos; the parent methods and properties.
&apos;&apos;&apos; They should also duplicate some generic private members as a subset of their own set of members
&apos;&apos;&apos;
&apos;&apos;&apos; The SF_FormDocument module is focused on :
&apos;&apos;&apos; The orchestration of Base form documents (aka Base Forms, but this is confusing)
&apos;&apos;&apos; and the identification of and the access to their controls.
&apos;&apos;&apos; Form documents are always contained in a Base document.
&apos;&apos;&apos; They should not be confused with Writer documents containing forms,
&apos;&apos;&apos; even if it is easy to convert the former to the latter.
&apos;&apos;&apos;
&apos;&apos;&apos; The current module is closely related to
&apos;&apos;&apos; the &quot;Base&quot; service of the current library
&apos;&apos;&apos; the &quot;Database&quot; service of the SFDatabases library
&apos;&apos;&apos;
&apos;&apos;&apos; A form document may be opened either:
&apos;&apos;&apos; via code or user interface from the Base file welcome page
&apos;&apos;&apos; via code only, without having its Base container opened first
&apos;&apos;&apos; The Base document remains hidden but the user might be prompted about the macro execution mode
&apos;&apos;&apos; In any mode, a form document can be opened only in 1 single copy
&apos;&apos;&apos;
&apos;&apos;&apos; Service invocation examples:
&apos;&apos;&apos; 1) From the Base service
&apos;&apos;&apos; Dim oBase As Object, oFormDoc As Object
&apos;&apos;&apos; &apos; oBase is presumed to represent an open Base document
&apos;&apos;&apos; Set oFormDoc = oBade.OpenFormDocument(&quot;Folder1/Form1&quot;)
&apos;&apos;&apos; 2) Directly without making the Base document visible
&apos;&apos;&apos; Dim oDatabase As Object, oFormDoc As Object
&apos;&apos;&apos; Set oDatabase = CreateScriptService(&quot;SFDatabases.Database&quot;, &quot;.../myFile.odb&quot;, ReadOnly := False)
&apos;&apos;&apos; &apos; The substring &quot;SFDatabases.&quot; in the service name is optional
&apos;&apos;&apos; Set oFormDoc = oDatabase.OpenFormDocument(&quot;Folder1/Form1&quot;)
&apos;&apos;&apos;
&apos;&apos;&apos; Definitions:
&apos;&apos;&apos; None
&apos;&apos;&apos;
&apos;&apos;&apos; Detailed user documentation:
&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_formdocument.html?DbPAR=BASIC
&apos;&apos;&apos;
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
REM ================================================================== EXCEPTIONS
Private Const BASEFORMNOTFOUNDERROR = &quot;BASEFORMNOTFOUNDERROR&quot;
REM ============================================================= PRIVATE MEMBERS
Private [Me] As Object
Private [_Parent] As Object &apos; Unused
Private [_Super] As Object &apos; Document superclass, which the current instance is a subclass of
Private ObjectType As String &apos; Must be FormDocument
Private ServiceName As String
&apos; Components
Private _Component As Object &apos; com.sun.star.lang.XComponent
Private _BaseComponent As Object &apos; com.sun.star.comp.dba.ODatabaseDocument
Private _FormDocument As Object &apos; com.sun.star.comp.sdb.Content
&apos; Form document description
Private _PersistentName As String &apos; Typically Objxx
Private _HierarchicalName As String
Private _DataSource As Object &apos; com.sun.star.sdbc.XDataSource
Private _User As String &apos; Credentials
Private _Password As String
REM ============================================================ MODULE CONSTANTS
Const ISBASEFORM = 3 &apos; 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 = &quot;FormDocument&quot;
ServiceName = &quot;SFDocuments.FormDocument&quot;
Set _Component = Nothing
Set _BaseComponent = Nothing
Set _FormDocument = Nothing
Set _DataSource = Nothing
Set _Database = Nothing
_PersistentName = &quot;&quot;
_HierarchicalName = &quot;&quot;
End Sub &apos; SFDocuments.SF_FormDocument Constructor
REM -----------------------------------------------------------------------------
Private Sub Class_Terminate()
Call Class_Initialize()
End Sub &apos; 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 &apos; SFDocuments.SF_FormDocument Explicit Destructor
REM ================================================================== PROPERTIES
REM ===================================================================== METHODS
REM -----------------------------------------------------------------------------
Public Function CloseDocument() As Boolean
&apos;&apos;&apos; Close the form document and dispose the actual instance
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; True if closure is successful
&apos;&apos;&apos; Example:
&apos;&apos;&apos; myFormDoc.CloseDocument()
Dim bClose As Boolean &apos; Return value
Dim oContainer As Object &apos; com.sun.star.awt.XWindow
Const cstThisSub = &quot;SFDocuments.FormDocument.CloseDocument&quot;
Const cstSubArgs = &quot;&quot;
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 &apos; SFDocuments.SF_FormDocument.CloseDocument
REM -----------------------------------------------------------------------------
Public Function Forms(Optional ByVal Form As Variant) As Variant
&apos;&apos;&apos; Return either
&apos;&apos;&apos; - the list of the Forms contained in the form document
&apos;&apos;&apos; - a SFDocuments.Form object based on its name or its index
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Form: a form stored in the document given by its name or its index
&apos;&apos;&apos; When absent, the list of available forms is returned
&apos;&apos;&apos; To get the first (unique ?) form stored in the form document, set Form = 0
&apos;&apos;&apos; Exceptions:
&apos;&apos;&apos; BASEFORMNOTFOUNDERROR Form not found
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; A zero-based array of strings if Form is absent
&apos;&apos;&apos; An instance of the SF_Form class if Form exists
&apos;&apos;&apos; Example:
&apos;&apos;&apos; Dim myForm As Object, myList As Variant
&apos;&apos;&apos; myList = oDoc.Forms()
&apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;myForm&quot;)
Dim oForm As Object &apos; The new Form class instance
Dim oMainForm As Object &apos; com.sun.star.comp.sdb.Content
Dim oXForm As Object &apos; com.sun.star.form.XForm
Dim vFormNames As Variant &apos; Array of form names
Dim oForms As Object &apos; Forms collection
Const cstDrawPage = 0 &apos; Only 1 drawpage in a FormDocument document
Const cstThisSub = &quot;SFDocuments.FormDocument.Forms&quot;
Const cstSubArgs = &quot;[Form=&quot;&quot;&quot;&quot;]&quot;
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Check:
If IsMissing(Form) Or IsEmpty(Form) Then Form = &quot;&quot;
If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
If Not _IsStillAlive() Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Form, &quot;Form&quot;, Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally
End If
Try:
&apos; Start from the document component and go down to forms
Set oForms = _Component.DrawPages(cstDrawPage).Forms
vFormNames = oForms.getElementNames()
If Len(Form) = 0 Then &apos; Return the list of valid form names
Forms = vFormNames
Else
If VarType(Form) = V_STRING Then &apos; Find the form by name
If Not ScriptForge.SF_Array.Contains(vFormNames, Form, CaseSensitive := True) Then GoTo CatchNotFound
Set oXForm = oForms.getByName(Form)
Else &apos; Find the form by index
If Form &lt; 0 Or Form &gt;= oForms.Count Then GoTo CatchNotFound
Set oXForm = oForms.getByIndex(Form)
End If
&apos; 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 &apos; SFDocuments.SF_FormDocument.Forms
REM -----------------------------------------------------------------------------
Public Function GetDatabase(Optional ByVal User As Variant _
, Optional ByVal Password As Variant _
) As Object
&apos;&apos;&apos; Returns a Database instance (service = SFDatabases.Database) giving access
&apos;&apos;&apos; to the execution of SQL commands on the database defined and/or stored in
&apos;&apos;&apos; the actual form document
&apos;&apos;&apos; Args:
&apos;&apos;&apos; User, Password: the login parameters as strings. Defaults = &quot;&quot;
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; A SFDatabases.Database instance or Nothing
&apos;&apos;&apos; Example:
&apos;&apos;&apos; Dim myDb As Object
&apos;&apos;&apos; Set myDb = oFormDoc.GetDatabase()
Dim oDatabase As Object &apos; Return value
Const cstThisSub = &quot;SFDocuments.FormDocument.GetDatabase&quot;
Const cstSubArgs = &quot;[User=&quot;&quot;&quot;&quot;], [Password=&quot;&quot;&quot;&quot;]&quot;
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Set oDatabase = Nothing
Check:
If IsMissing(User) Or IsEmpty(User) Then User = &quot;&quot;
If IsMissing(Password) Or IsEmpty(Password) Then Password = &quot;&quot;
If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
If Not _IsStillAlive(False) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(User, &quot;User&quot;, V_STRING) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Password, &quot;Password&quot;, V_STRING) Then GoTo Finally
End If
Try:
If IsNull(_DataSource) Then GoTo CatchConnect
Set oDatabase = ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.DatabaseFromDocument&quot; _
, _DataSource, Iif(User = &quot;&quot;, _User, User), Iif(Password = &quot;&quot;, _Password, &quot;&quot;))
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, &quot;User&quot;, User, &quot;Password&quot;, Password, [_Super]._FileIdent())
GoTo Finally
End Function &apos; SFDocuments.SF_FormDocument.GetDatabase
REM -----------------------------------------------------------------------------
Public Function GetProperty(Optional ByVal PropertyName As Variant _
, Optional ObjectName As Variant _
) As Variant
&apos;&apos;&apos; Return the actual value of the given property
&apos;&apos;&apos; Args:
&apos;&apos;&apos; PropertyName: the name of the property as a string
&apos;&apos;&apos; ObjectName: a sheet or range name
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; The actual value of the property
&apos;&apos;&apos; Exceptions:
&apos;&apos;&apos; ARGUMENTERROR The property does not exist
Const cstThisSub = &quot;SFDocuments.FormDocument.GetProperty&quot;
Const cstSubArgs = &quot;&quot;
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
GetProperty = Null
Check:
If IsMissing(ObjectName) Or IsEmpty(ObjectName) Then ObjectName = &quot;&quot;
If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
If Not ScriptForge.SF_Utils._Validate(ObjectName, &quot;ObjectName&quot;, V_STRING) Then GoTo Catch
End If
Try:
&apos; 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 &apos; SFDocuments.SF_FormDocument.GetProperty
REM -----------------------------------------------------------------------------
Public Function Methods() As Variant
&apos;&apos;&apos; Return the list of public methods of the FormDocument service as an array
Methods = Array( _
&quot;CloseDocument&quot; _
, &quot;Forms&quot; _
, &quot;PrintOut&quot; _
)
End Function &apos; 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
&apos;&apos;&apos; Send the content of the document to the printer.
&apos;&apos;&apos; The printer might be defined previously by default, by the user or by the SetPrinter() method
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Pages: the pages to print as a string, like in the user interface. Example: &quot;1-4;10;15-18&quot;. Default = all pages
&apos;&apos;&apos; Copies: the number of copies
&apos;&apos;&apos; PrintBackground: print the background image when True (default)
&apos;&apos;&apos; PrintBlankPages: when False (default), omit empty pages
&apos;&apos;&apos; PrintEvenPages: print the left pages when True (default)
&apos;&apos;&apos; PrintOddPages: print the right pages when True (default)
&apos;&apos;&apos; PrintImages: print the graphic objects when True (default)
&apos;&apos;&apos; Returns:
&apos;&apos;&apos; True when successful
&apos;&apos;&apos; Examples:
&apos;&apos;&apos; oDoc.PrintOut(&quot;1-4;10;15-18&quot;, Copies := 2, PrintImages := False)
Dim bPrint As Boolean &apos; Return value
Dim vPrintOptions As Variant &apos; com.sun.star.text.DocumentSettings
Const cstThisSub = &quot;SFDocuments.FormDocument.PrintOut&quot;
Const cstSubArgs = &quot;[Pages=&quot;&quot;&quot;&quot;], [Copies=1], [PrintBackground=True], [PrintBlankPages=False], [PrintEvenPages=True]&quot; _
&amp; &quot;, [PrintOddPages=True], [PrintImages=True]&quot;
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
bPrint = False
Check:
If IsMissing(Pages) Or IsEmpty(Pages) Then Pages = &quot;&quot;
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, &quot;Pages&quot;, V_STRING) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(Copies, &quot;Copies&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(PrintBackground, &quot;PrintBackground&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(PrintBlankPages, &quot;PrintBlankPages&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(PrintEvenPages, &quot;PrintEvenPages&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(PrintOddPages, &quot;PrintOddPages&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(PrintImages, &quot;PrintImages&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
End If
Try:
vPrintOptions = _Component.createInstance(&quot;com.sun.star.text.DocumentSettings&quot;)
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 &apos; SFDocuments.SF_FormDocument.PrintOut
REM -----------------------------------------------------------------------------
Public Function Properties() As Variant
&apos;&apos;&apos; Return the list or properties of the FormDocument class as an array
Properties = Array( _
&quot;DocumentType&quot; _
, &quot;IsBase&quot; _
, &quot;IsCalc&quot; _
, &quot;IsDraw&quot; _
, &quot;IsFormDocument&quot; _
, &quot;IsImpress&quot; _
, &quot;IsMath&quot; _
, &quot;Readonly&quot; _
, &quot;XComponent&quot; _
)
End Function &apos; SFDocuments.SF_FormDocument.Properties
REM ======================================================= SUPERCLASS PROPERTIES
REM -----------------------------------------------------------------------------
Property Get IsBase() As Boolean
IsBase = [_Super].GetProperty(&quot;IsBase&quot;)
End Property &apos; SFDocuments.SF_FormDocument.IsBase
REM -----------------------------------------------------------------------------
Property Get IsCalc() As Boolean
IsCalc = [_Super].GetProperty(&quot;IsCalc&quot;)
End Property &apos; SFDocuments.SF_FormDocument.IsCalc
REM -----------------------------------------------------------------------------
Property Get IsDraw() As Boolean
IsDraw = [_Super].GetProperty(&quot;IsDraw&quot;)
End Property &apos; SFDocuments.SF_FormDocument.IsDraw
REM -----------------------------------------------------------------------------
Property Get IsFormDocument() As Boolean
IsFormDocument = [_Super].GetProperty(&quot;IsFormDocument&quot;)
End Property &apos; SFDocuments.SF_Writer.IsFormDocument
REM -----------------------------------------------------------------------------
Property Get IsImpress() As Boolean
IsImpress = [_Super].GetProperty(&quot;IsImpress&quot;)
End Property &apos; SFDocuments.SF_FormDocument.IsImpress
REM -----------------------------------------------------------------------------
Property Get IsMath() As Boolean
IsMath = [_Super].GetProperty(&quot;IsMath&quot;)
End Property &apos; SFDocuments.SF_FormDocument.IsMath
REM -----------------------------------------------------------------------------
Property Get Readonly() As Variant
Readonly = [_Super].GetProperty(&quot;Readonly&quot;)
End Property &apos; SFDocuments.SF_FormDocument.Readonly
REM -----------------------------------------------------------------------------
Property Get XComponent() As Variant
XComponent = [_Super].GetProperty(&quot;XComponent&quot;)
End Property &apos; SFDocuments.SF_FormDocument.XComponent
REM ========================================================== SUPERCLASS METHODS
REM -----------------------------------------------------------------------------
Public Function Activate() As Boolean
Activate = [_Super].Activate()
End Function &apos; 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 &apos; 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 &apos; SFDocuments.SF_FormDocument.ExportAsPDF
REM -----------------------------------------------------------------------------
Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
RemoveMenu = [_Super].RemoveMenu(MenuHeader)
End Function &apos; SFDocuments.SF_FormDocument.RemoveMenu
REM -----------------------------------------------------------------------------
Public Sub RunCommand(Optional ByVal Command As Variant _
, ParamArray Args As Variant _
)
[_Super].RunCommand(Command, Args)
End Sub &apos; 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 &apos; 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 &apos; SFDocuments.SF_FormDocument.SetPrinter
REM =========================================================== PRIVATE FUNCTIONS
REM -----------------------------------------------------------------------------
Private Function _FileIdent() As String
&apos;&apos;&apos; Returns a file identification from the information that is currently available
&apos;&apos;&apos; Useful e.g. for display in error messages
_FileIdent = [_Super]._FileIdent()
End Function &apos; SFDocuments.SF_FormDocument._FileIdent
REM -----------------------------------------------------------------------------
Public Sub _Initialize()
&apos;&apos;&apos; Achieve the creation of a SF_Form instance
&apos;&apos;&apos; - the database file
&apos;&apos;&apos; - the database connection
&apos;&apos;&apos; the internal and external names
Dim oBase As Object &apos; A temporary Base instance
On Local Error GoTo Catch
Try:
&apos; Base file where form document is stored
Set _BaseComponent = _Component.Parent
&apos; Connection arguments
Set _DataSource = _BaseComponent.DataSource
With _DataSource
_User = .User
_Password = .Password
End With
&apos; External and internal names
_PersistentName = ScriptForge.SF_Utils._GetPropertyValue(_Component.Args, &quot;HierarchicalDocumentName&quot;)
Set oBase = New SF_Base &apos; 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 &apos; SFDocuments.SF_FormDocument._Initialize
REM -----------------------------------------------------------------------------
Private Function _IsStillAlive(Optional ByVal pbForUpdate As Boolean _
, Optional ByVal pbError As Boolean _
) As Boolean
&apos;&apos;&apos; Returns True if the document has not been closed manually or incidentally since the last use
&apos;&apos;&apos; If dead the actual instance is disposed. The execution is cancelled when pbError = True (default)
&apos;&apos;&apos; Args:
&apos;&apos;&apos; pbForUpdate: if True (default = False), check additionally if document is open for editing
&apos;&apos;&apos; pbError: if True (default), raise a fatal error
Dim bAlive As Boolean &apos; 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 &apos; SFDocuments.SF_FormDocument._IsStillAlive
REM -----------------------------------------------------------------------------
Private Function _PropertyGet(Optional ByVal psProperty As String _
, Optional ByVal pvArg As Variant _
) As Variant
&apos;&apos;&apos; Return the value of the named property
&apos;&apos;&apos; Args:
&apos;&apos;&apos; psProperty: the name of the property
Dim cstThisSub As String
Const cstSubArgs = &quot;&quot;
_PropertyGet = False
cstThisSub = &quot;SFDocuments.FormDocument.get&quot; &amp; 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 &apos; SFDocuments.SF_FormDocument._PropertyGet
REM -----------------------------------------------------------------------------
Private Function _Repr() As String
&apos;&apos;&apos; Convert the SF_FormDocument instance to a readable string, typically for debugging purposes (DebugPrint ...)
&apos;&apos;&apos; Args:
&apos;&apos;&apos; Return:
&apos;&apos;&apos; &quot;[DOCUMENT]: Type/File&quot;
_Repr = &quot;[FormDocument]: &quot; &amp; [_Super]._FileIdent()
End Function &apos; SFDocuments.SF_FormDocument._Repr
REM ============================================ END OF SFDOCUMENTS.SF_FORMDOCUMENT
</script:module>

View file

@ -69,6 +69,7 @@ Public Sub RegisterScriptServices() As Variant
.RegisterService(&quot;Base&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
.RegisterService(&quot;Calc&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
.RegisterService(&quot;Writer&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
.RegisterService(&quot;FormDocument&quot;, &quot;SFDocuments.SF_Register._NewDocument&quot;) &apos; Same reference, distinction is made inside the function
.RegisterEventManager(&quot;DocumentEvent&quot;, &quot;SFDocuments.SF_Register._EventManager&quot;) &apos; Reference to the events manager
.RegisterEventManager(&quot;FormEvent&quot;, &quot;SFDocuments.SF_Register._FormEventManager&quot;)&apos; Reference to the form and controls events manager
End With
@ -408,6 +409,11 @@ Try:
Set oSuperDocument = New SF_Document
Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
Set oSuperDocument.[_SubClass] = oDocument
Case &quot;FormDocument&quot;
Set oDocument = New SF_FormDocument
Set oSuperDocument = New SF_Document
Set oDocument.[_Super] = oSuperDocument &apos; Now both super and subclass are twinned
Set oSuperDocument.[_SubClass] = oDocument
Case &quot;Writer&quot;
Set oDocument = New SF_Writer
Set oSuperDocument = New SF_Document
@ -424,6 +430,8 @@ Try:
Select Case vWindow.DocumentType
Case &quot;Base&quot;
Set ._DataSource = ._Component.DataSource
Case &quot;FormDocument&quot;
._Initialize()
Case Else
End Select
End With

View file

@ -47,7 +47,7 @@ Option Explicit
&apos;&apos;&apos; TBD
&apos;&apos;&apos;
&apos;&apos;&apos; Detailed user documentation:
&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/SF_Writer.html?DbPAR=BASIC
&apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_writer.html?DbPAR=BASIC
&apos;&apos;&apos;
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
@ -68,6 +68,8 @@ Private _Component As Object &apos; com.sun.star.lang.XComponent
REM ============================================================ MODULE CONSTANTS
Const ISDOCFORM = 1 &apos; Form is stored in a Writer document
REM ====================================================== CONSTRUCTOR/DESTRUCTOR
REM -----------------------------------------------------------------------------
@ -312,6 +314,7 @@ Public Function Properties() As Variant
, &quot;IsBase&quot; _
, &quot;IsCalc&quot; _
, &quot;IsDraw&quot; _
, &quot;IsFormDocument&quot; _
, &quot;IsImpress&quot; _
, &quot;IsMath&quot; _
, &quot;IsWriter&quot; _
@ -429,6 +432,11 @@ Property Get IsDraw() As Boolean
IsDraw = [_Super].GetProperty(&quot;IsDraw&quot;)
End Property &apos; SFDocuments.SF_Writer.IsDraw
REM -----------------------------------------------------------------------------
Property Get IsFormDocument() As Boolean
IsFormDocument = [_Super].GetProperty(&quot;IsFormDocument&quot;)
End Property &apos; SFDocuments.SF_Writer.IsFormDocument
REM -----------------------------------------------------------------------------
Property Get IsImpress() As Boolean
IsImpress = [_Super].GetProperty(&quot;IsImpress&quot;)

View file

@ -11,4 +11,5 @@
<library:element library:name="SF_Writer"/>
<library:element library:name="SF_Chart"/>
<library:element library:name="SF_DocumentListener"/>
<library:element library:name="SF_FormDocument"/>
</library:library>

View file

@ -88,7 +88,10 @@ Try:
End With
If Len(sCommand) &gt; 0 Then
Set oFrame = StarDesktop.ActiveFrame &apos; A menu has been clicked necessarily in the current window
&apos; 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 &gt; 0 Then Set oFrame = oFrame.getActiveFrame()
&apos; Command or script ?
If Left(sCommand, Len(cstUnoPrefix)) = cstUnoPrefix Then
&apos; Execute uno command
Set oDispatcher = ScriptForge.SF_Utils._GetUNOService(&quot;DispatchHelper&quot;)
@ -124,5 +127,5 @@ Sub _SFMENU_disposing(Optional poEvent As Object) &apos; com.sun.star.awt.Menu
Exit Sub
End Sub &apos; SFWidgets.SF_MenuListener._SFMENU_disposing
REM ============================================ END OF SFDIALOGS.SF_DIALOGLISTENER
REM ============================================ END OF SFWIDGETS.SF_MENULISTENER
</script:module>