<?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_Writer" 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
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''' SF_Writer
''' =========
'''
''' 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_Writer module is focused on selecting, reading, inserting, modifying texts and values
''' on well-identified and predefined places in the document.
''' Usually such customization of the document starts from a predefined template.
''' Multiple customizations are also known as mail merging.
'''
''' As a consequence, focus is not on text formatting, except by the application of styles
''' onto the targeted text fragments.
'''
''' The positions in the text where customization can take place easily are:
''' - the start and end positions of the text body
''' - the start and end positions of text frames
''' - bookmarks
''' - text fields
''' - the start and end positions of document sections
''' - writer tables and table cells
''' - the area currently selected by the user, i.e. the "visible" selection
'''
''' The current module is closely related to the "UI" service of the ScriptForge library
'''
''' Service invocation examples:
''' 1) From the UI service
''' Dim ui As Object, oDoc As Object
''' Set ui = CreateScriptService("UI")
''' Set oDoc = ui.CreateDocument("Writer", ...)
''' ' or Set oDoc = ui.OpenDocument("C:\Me\MyFile.odt")
''' 2) Directly if the document is already opened
''' Dim oDoc As Object
''' Set oDoc = CreateScriptService("SFDocuments.Writer", ThisComponent) ' Default = ActiveWindow
''' ' or Set oDoc = CreateScriptService("SFDocuments.Writer", "Untitled 1") ' Untitled 1 is presumed a Writer document
''' ' The substring "SFDocuments." in the service name is optional
'''
''' Definitions:
''' Many methods require a "TextRange" as argument.
''' A textrange is a string describing the scope on which to apply the method.
''' Such a textrange corresponds either with a single insertion point or with a (text) interval between 2 insertion points.
''' Multiple textranges are not supported in this context.
'''
''' TextRange: a string containing one of next variants :
''' (names may be surrounded with single or double quotes)
''' "~" or "SELECTION" or "SEL" = current selection (if multiple selections, its 1st component)
''' "BODY" = the main text of the actual document instance
''' "FRAME!name" = the text contained in a text frame
''' "BOOKMARK!name" = the given bookmark, may be zero or more characters long
''' "FIELD!name" = a user text field
''' "SECTION!name" = the text contained in a section
''' "TABLE!name!" = the whole cellrange of a table
''' "TABLE!name!cellrange" = a cell (cellrange = "B3") or a range of cells ("A2:B3")
''' "WORD+3" = 3 words after the current selection
''' "SENTENCE-1" = the sentence before the current selection
''' "PARAGRAPH" or "§" = the paragraph containing the current selection (0 is the default)
''' optionally combined with next control character:
''' "|": start or end of string
''' "|~" = the point immediately before the current visible selection (starting point)
''' "~|" = the point immediately after the current visible selection (ending point)
''' "~", "|~|" = the full visible selection
'''
'''
''' Detailed user documentation:
''' https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_writer.html?DbPAR=BASIC
'''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
REM ================================================================== EXCEPTIONS
Private Const WRITERFORMNOTFOUNDERROR = "WRITERFORMNOTFOUNDERROR"
Private Const WRITERRANGEERROR = "WRITERRANGEERROR"
REM ============================================================= PRIVATE MEMBERS
Private [Me] As Object
Private [_Parent] As Object
Private [_Super] As Object ' Document superclass, which the current instance is a subclass of
Private ObjectType As String ' Must be WRITER
Private ServiceName As String
' Window component
Private _Component As Object ' com.sun.star.lang.XComponent
' Text Range
Type _TextRange
RangeString As String ' The input string
Target As String ' Selection or Body or Frame or ...
TargetName As String ' Name of Frame or Table or ...
TargetCell As String ' Cell
TargetObject As Object ' Field, TableCell, Section, ... object
Offset As Long ' Number of items to right (+) or to left (-)
StartPoint As Boolean ' When True, vertical bar before target
EndPoint As Boolean ' When True, vertical bar after target
Anchor As Object ' com.sun.star.text.XTextRange
Text As Object ' com.sun.star.text.XText
Cursor As Object ' com.sun.star.text.XTextCursor
Location As String ' BODY or FOOTNOTE or HEADER/FOOTER ...
End Type
REM ============================================================ MODULE CONSTANTS
Const ISDOCFORM = 1 ' Form is stored in a Writer document
REM ====================================================== CONSTRUCTOR/DESTRUCTOR
REM -----------------------------------------------------------------------------
Private Sub Class_Initialize()
Set [Me] = Nothing
Set [_Parent] = Nothing
Set [_Super] = Nothing
ObjectType = "WRITER"
ServiceName = "SFDocuments.Writer"
Set _Component = Nothing
End Sub ' SFDocuments.SF_Writer Constructor
REM -----------------------------------------------------------------------------
Private Sub Class_Terminate()
Call Class_Initialize()
End Sub ' SFDocuments.SF_Writer 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_Writer Explicit Destructor
REM ================================================================== PROPERTIES
REM -----------------------------------------------------------------------------
Property Get Bookmarks() As Variant
''' Return the list of currently available bookmarks as a zero-based array
Bookmarks = _PropertyGet("Bookmarks")
End Property ' SFDocuments.SF_Writer.Bookmarks (get)
REM -----------------------------------------------------------------------------
Property Get CurrentSelection() As Variant
''' Return the list of currently available CurrentSelection as a zero-based array
CurrentSelection = _PropertyGet("CurrentSelection")
End Property ' SFDocuments.SF_Writer.CurrentSelection (get)
REM -----------------------------------------------------------------------------
Property Let CurrentSelection(Optional ByVal pvSelection As Variant)
''' Set the selection to a single or a multiple range
''' The argument can be:
''' - a string (a textrange)
''' - a com.sun.star.text.XTextRange object
''' - a collection of com.sun.star.text.XTextRange objects
Dim vSelection As Variant ' Alias of pvSelection
Dim oSelection As Object ' com.sun.star.text.XTextRange
Dim sType As String ' session.UnoObjectType()
Dim oSess As Object : Set oSess = ScriptForge.SF_Session
Dim i As Long
Const cstThisSub = "SFDocuments.Writer.setCurrentSelection"
Const cstSubArgs = "Selection"
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
Check:
If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
If Not _IsStillAlive(True) Then GoTo Finally
If Not ScriptForge.SF_Utils._Validate(pvSelection, "Selection", Array(V_STRING, ScriptForge.V_Object)) Then GoTo Finally
End If
Try:
vSelection = pvSelection ' Necessary to avoid the "Object variable not set" error
With _Component.CurrentController
If VarType(vSelection) = V_STRING Then
Set oSelection = _ParseRange(vSelection).Cursor
If Not IsNull(oSelection) Then .select(oSelection)
Else
sType = oSess.UnoObjectType(vSelection)
Select Case sType
Case "SwXTextRanges" ' Argument is a multiple selection
For i = 0 To vSelection.Count - 1
If oSess.UnoObjectType(vSelection.getByIndex(i)) <> "SwXTextRange" Then GoTo Catch ' Do nothing
Next i
.select(vSelection)
Case "SwXTextRange", "SwXTextCursor", "SwXTextTableCursor" ' Argument is a simple selection (anchor/cursor)
.select(vSelection)
Case Else
End Select
End If
End With
Finally:
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Property
Catch:
GoTo Finally
End Property ' SFDocuments.SF_Writer.CurrentSelection (let)
REM -----------------------------------------------------------------------------
Property Get Fields() As Variant
''' Return the list of currently available fields as a zero-based array
''' Are considered only next field-types:
''' - user fields: com.sun.star.text.textfield.User
''' - variable fields: com.sun.star.text.textfield.SetExpression
Fields = _PropertyGet("Fields")
End Property ' SFDocuments.SF_Writer.Fields (get)
REM -----------------------------------------------------------------------------
Property Get Frames() As Variant
''' Return the list of currently available frames as a zero-based array
Frames = _PropertyGet("Frames")
End Property ' SFDocuments.SF_Writer.Frames (get)
REM ===================================================================== METHODS
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:
''' WRITERFORMNOTFOUNDERROR 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 Writer document
Const cstThisSub = "SFDocuments.Writer.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 = ISDOCFORM
Set ._Component = _Component
._Initialize()
End With
Set Forms = oForm
End If
Finally:
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
Catch:
GoTo Finally
CatchNotFound:
ScriptForge.SF_Exception.RaiseFatal(WRITERFORMNOTFOUNDERROR, Form, _FileIdent())
End Function ' SFDocuments.SF_Writer.Forms
REM -----------------------------------------------------------------------------
Public Function GetProperty(Optional ByVal PropertyName As Variant _
) As Variant
''' Return the actual value of the given property
''' Args:
''' PropertyName: the name of the property as a string
''' Returns:
''' The actual value of the property
''' Exceptions:
''' ARGUMENTERROR The property does not exist
Const cstThisSub = "SFDocuments.Writer.GetProperty"
Const cstSubArgs = ""
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
GetProperty = Null
Check:
If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
If Not ScriptForge.SF_Utils._Validate(PropertyName, "PropertyName", V_STRING, Properties()) Then GoTo Catch
End If
Try:
' Superclass or subclass property ?
If ScriptForge.SF_Array.Contains([_Super].Properties(), PropertyName) Then
GetProperty = [_Super].GetProperty(PropertyName)
Else
GetProperty = _PropertyGet(PropertyName)
End If
Finally:
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
Catch:
GoTo Finally
End Function ' SFDocuments.SF_Writer.GetProperty
REM -----------------------------------------------------------------------------
Public Function Methods() As Variant
''' Return the list of public methods of the Writer service as an array
Methods = Array( _
"Forms" _
, "PrintOut" _
)
End Function ' SFDocuments.SF_Writer.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.Writer.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_Writer.PrintOut
REM -----------------------------------------------------------------------------
Public Function Properties() As Variant
''' Return the list or properties of the Writer class as an array
Properties = Array( _
"Bookmarks" _
, "CurrentSelection" _
, "CustomProperties" _
, "Description" _
, "DocumentProperties" _
, "DocumentType" _
, "ExportFilters" _
, "Fields" _
, "FileSystem" _
, "Frames" _
, "ImportFilters" _
, "IsAlive" _
, "IsBase" _
, "IsCalc" _
, "IsDraw" _
, "IsFormDocument" _
, "IsImpress" _
, "IsMath" _
, "IsWriter" _
, "Keywords" _
, "Readonly" _
, "StyleFamilies" _
, "Subject" _
, "Title" _
, "XComponent" _
, "XDocumentSettings" _
)
End Function ' SFDocuments.SF_Writer.Properties
REM -----------------------------------------------------------------------------
Private Function SetProperty(Optional ByVal psProperty As String _
, Optional ByVal pvValue As Variant _
) As Boolean
''' Set the new value of the named property
''' Args:
''' psProperty: the name of the property
''' pvValue: the new value of the given property
''' Returns:
''' True if successful
Dim bSet As Boolean ' Return value
Static oSession As Object ' Alias of SF_Session
Dim cstThisSub As String
Const cstSubArgs = "Value"
If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
bSet = False
cstThisSub = "SFDocuments.Writer.set" & psProperty
If IsMissing(pvValue) Then pvValue = Empty
'ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) ' Validation done in Property Lets
If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService("Session")
bSet = True
Select Case UCase(psProperty)
Case UCase("CustomProperties")
CustomProperties = pvValue
Case UCase("Description")
Description = pvValue
Case UCase("Keywords")
Keywords = pvValue
Case UCase("Subject")
Subject = pvValue
Case UCase("Title")
Title = pvValue
Case Else
bSet = False
End Select
Finally:
SetProperty = bSet
'ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
Catch:
GoTo Finally
End Function ' SFDocuments.SF_Writer.SetProperty
REM ======================================================= SUPERCLASS PROPERTIES
REM -----------------------------------------------------------------------------
Property Get CustomProperties() As Variant
CustomProperties = [_Super].GetProperty("CustomProperties")
End Property ' SFDocuments.SF_Writer.CustomProperties
REM -----------------------------------------------------------------------------
Property Let CustomProperties(Optional ByVal pvCustomProperties As Variant)
[_Super].CustomProperties = pvCustomProperties
End Property ' SFDocuments.SF_Writer.CustomProperties
REM -----------------------------------------------------------------------------
Property Get Description() As Variant
Description = [_Super].GetProperty("Description")
End Property ' SFDocuments.SF_Writer.Description
REM -----------------------------------------------------------------------------
Property Let Description(Optional ByVal pvDescription As Variant)
[_Super].Description = pvDescription
End Property ' SFDocuments.SF_Writer.Description
REM -----------------------------------------------------------------------------
Property Get DocumentProperties() As Variant
DocumentProperties = [_Super].GetProperty("DocumentProperties")
End Property ' SFDocuments.SF_Writer.DocumentProperties
REM -----------------------------------------------------------------------------
Property Get DocumentType() As String
DocumentType = [_Super].GetProperty("DocumentType")
End Property ' SFDocuments.SF_Writer.DocumentType
REM -----------------------------------------------------------------------------
Property Get ExportFilters() As Variant
ExportFilters = [_Super].GetProperty("ExportFilters")
End Property ' SFDocuments.SF_Writer.ExportFilters
REM -----------------------------------------------------------------------------
Property Get FileSystem() As String
FileSystem = [_Super].GetProperty("FileSystem")
End Property ' SFDocuments.SF_Writer.FileSystem
REM -----------------------------------------------------------------------------
Property Get ImportFilters() As Variant
ImportFilters = [_Super].GetProperty("ImportFilters")
End Property ' SFDocuments.SF_Writer.ImportFilters
REM -----------------------------------------------------------------------------
Property Get IsAlive() As Boolean
IsAlive = [_Super].GetProperty("IsAlive")
End Property ' SFDocuments.SF_Writer.IsAlive
REM -----------------------------------------------------------------------------
Property Get IsBase() As Boolean
IsBase = [_Super].GetProperty("IsBase")
End Property ' SFDocuments.SF_Writer.IsBase
REM -----------------------------------------------------------------------------
Property Get IsCalc() As Boolean
IsCalc = [_Super].GetProperty("IsCalc")
End Property ' SFDocuments.SF_Writer.IsCalc
REM -----------------------------------------------------------------------------
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")
End Property ' SFDocuments.SF_Writer.IsImpress
REM -----------------------------------------------------------------------------
Property Get IsMath() As Boolean
IsMath = [_Super].GetProperty("IsMath")
End Property ' SFDocuments.SF_Writer.IsMath
REM -----------------------------------------------------------------------------
Property Get IsWriter() As Boolean
IsWriter = [_Super].GetProperty("IsWriter")
End Property ' SFDocuments.SF_Writer.IsWriter
REM -----------------------------------------------------------------------------
Property Get Keywords() As Variant
Keywords = [_Super].GetProperty("Keywords")
End Property ' SFDocuments.SF_Writer.Keywords
REM -----------------------------------------------------------------------------
Property Let Keywords(Optional ByVal pvKeywords As Variant)
[_Super].Keywords = pvKeywords
End Property ' SFDocuments.SF_Writer.Keywords
REM -----------------------------------------------------------------------------
Property Get Readonly() As Variant
Readonly = [_Super].GetProperty("Readonly")
End Property ' SFDocuments.SF_Writer.Readonly
REM -----------------------------------------------------------------------------
Property Get StyleFamilies() As Variant
StyleFamilies = [_Super].GetProperty("StyleFamilies")
End Property ' SFDocuments.SF_Writer.StyleFamilies
REM -----------------------------------------------------------------------------
Property Get Subject() As Variant
Subject = [_Super].GetProperty("Subject")
End Property ' SFDocuments.SF_Writer.Subject
REM -----------------------------------------------------------------------------
Property Let Subject(Optional ByVal pvSubject As Variant)
[_Super].Subject = pvSubject
End Property ' SFDocuments.SF_Writer.Subject
REM -----------------------------------------------------------------------------
Property Get Title() As Variant
Title = [_Super].GetProperty("Title")
End Property ' SFDocuments.SF_Writer.Title
REM -----------------------------------------------------------------------------
Property Let Title(Optional ByVal pvTitle As Variant)
[_Super].Title = pvTitle
End Property ' SFDocuments.SF_Writer.Title
REM -----------------------------------------------------------------------------
Property Get XComponent() As Variant
XComponent = [_Super].GetProperty("XComponent")
End Property ' SFDocuments.SF_Writer.XComponent
REM -----------------------------------------------------------------------------
Property Get XDocumentSettings() As Variant
XDocumentSettings = [_Super].GetProperty("XDocumentSettings")
End Property ' SFDocuments.SF_Writer.XDocumentSettings
REM ========================================================== SUPERCLASS METHODS
REM -----------------------------------------------------------------------------
Public Function Activate() As Boolean
Activate = [_Super].Activate()
End Function ' SFDocuments.SF_Writer.Activate
REM -----------------------------------------------------------------------------
Public Function CloseDocument(Optional ByVal SaveAsk As Variant) As Boolean
CloseDocument = [_Super].CloseDocument(SaveAsk)
End Function ' SFDocuments.SF_Writer.CloseDocument
REM -----------------------------------------------------------------------------
Public Function ContextMenus(Optional ByVal ContextMenuName As Variant _
, Optional ByVal SubmenuChar As Variant _
) As Variant
ContextMenus = [_Super].ContextMenus(ContextMenuName, SubmenuChar)
End Function ' SFDocuments.SF_Writer.ContextMenus
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_Writer.CreateMenu
REM -----------------------------------------------------------------------------
Public Sub DeleteStyles(Optional ByVal Family As Variant _
, Optional ByRef StylesList As Variant _
)
[_Super].DeleteStyles(Family, StylesList)
End Sub ' SFDocuments.SF_Writer.DeleteStyles
REM -----------------------------------------------------------------------------
Public Sub Echo(Optional ByVal EchoOn As Variant _
, Optional ByVal Hourglass As Variant _
)
[_Super].Echo(EchoOn, Hourglass)
End Sub ' SFDocuments.SF_Writer.Echo
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_Writer.ExportAsPDF
REM -----------------------------------------------------------------------------
Public Sub ImportStylesFromFile(Optional FileName As Variant _
, Optional ByRef Families As Variant _
, Optional ByVal Overwrite As variant _
) As Variant
[_Super]._ImportStylesFromFile(FileName, Families, Overwrite)
End Sub ' SFDocuments.SF_Writer.ImportStylesFromFile
REM -----------------------------------------------------------------------------
Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
RemoveMenu = [_Super].RemoveMenu(MenuHeader)
End Function ' SFDocuments.SF_Writer.RemoveMenu
REM -----------------------------------------------------------------------------
Public Sub RunCommand(Optional ByVal Command As Variant _
, ParamArray Args As Variant _
)
[_Super].RunCommand(Command, Args)
End Sub ' SFDocuments.SF_Writer.RunCommand
REM -----------------------------------------------------------------------------
Public Function Save() As Boolean
Save = [_Super].Save()
End Function ' SFDocuments.SF_Writer.Save
REM -----------------------------------------------------------------------------
Public Function SaveAs(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
SaveAs = [_Super].SaveAs(FileName, Overwrite, Password, FilterName, FilterOptions)
End Function ' SFDocuments.SF_Writer.SaveAs
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_Writer.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_Writer.SetPrinter
REM -----------------------------------------------------------------------------
Public Function Styles(Optional ByVal Family As Variant _
, Optional ByVal NamePattern As variant _
, Optional ByVal Used As variant _
, Optional ByVal UserDefined As Variant _
, Optional ByVal ParentStyle As Variant _
, Optional ByVal Category As Variant _
) As Variant
Styles = [_Super].Styles(Family, NamePattern, Used, UserDefined, ParentStyle, Category)
End Function ' SFDocuments.SF_Writer.Styles
REM -----------------------------------------------------------------------------
Public Function Toolbars(Optional ByVal ToolbarName As Variant) As Variant
Toolbars = [_Super].Toolbars(ToolbarName)
End Function ' SFDocuments.SF_Writer.Toolbars
REM -----------------------------------------------------------------------------
Public Function XStyle(Optional ByVal Family As Variant _
, Optional ByVal StyleName As variant _
) As Object
Set XStyle = [_Super].XStyle(Family, StyleName)
End Function ' SFDocuments.SF_Writer.XStyle
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_Writer._FileIdent
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_Writer._IsStillAlive
REM -----------------------------------------------------------------------------
Private Function _ParseRange(psTextRange As String) As Object
''' Parse and validate a text range passed as a string
''' Syntax to parse:
''' [|]~ or "SELECTION" or "SEL"[|]
''' [|]BODY[|]
''' [|]FRAME!name[|]
''' BOOKMARK!name
''' FIELD!name
''' [|]SECTION!name[|]
''' TABLE!name!cell
''' [|]WORD±n[|]
''' [|]SENTENCE±n[|]
''' [|]PARAGRAPH±n or §±n[|]
''' A name must be surrounded with single or double quotes when it contains a space or a not alphanumeric character
''' Returns:
''' An object of type _TextRange
''' Exceptions:
''' WRITERRANGEERROR ' Text range could not be parsed to a valid location
Dim oTextRange As Object ' Return value
Dim bParsing As Boolean ' When True, parsing could identify the target
Dim lSelects As Long ' Number of items in the current selection
Dim sTarget As String ' Alias of _TextRange.Target
Dim sString As String ' Work variable
Dim sLeft1 As String ' The 1st character of sString
Dim sSign As String ' + or -
Dim oColl As Object ' Collection of TargetObjects (bookmarks or frames or ...)
Dim oItem As Object ' An item in the oColl collection
Dim vNames As Variant ' Array of the available object names within a collection
Dim oStr As Object : Set oStr = ScriptForge.SF_String
Dim bMove As Boolean ' Return value of a cursor move
Dim i As Long
' Reinitialize a new _TextRange object
Set oTextRange = New _TextRange
With oTextRange
Set .TargetObject = Nothing
.RangeString = "" : .Target = "" : .TargetName = "" : .TargetCell = ""
.Offset = 0 : .StartPoint = False : .EndPoint = False
Set .Anchor = Nothing : Set .Text = Nothing : Set .Cursor = Nothing
.Location = ""
End With
' Identify the type of range with adequate regular expressions
With oTextRange
.RangeString = psTextRange
.StartPoint = ( Left(psTextRange, 1) = "|" )
.EndPoint = ( Right(psTextRange, 1) = "|" )
Select Case True
' Parsing is done with regular expressions because names may really contain any character, including "ç"
' Selection
Case oStr.IsRegex(psTextRange, "\|?\s*(~|SEL|SELECTION)\s*\|?")
.Target = "Selection"
If _Component.CurrentSelection.ImplementationName = "SwXTextRanges" Then
lSelects = _Component.CurrentSelection.Count
If lSelects > 0 Then
Set .Anchor = _Component.CurrentSelection.getByIndex(lSelects - 1)
If .StartPoint And Not .EndPoint Then
Set .Anchor = .Anchor.Start
ElseIf Not .StartPoint And .EndPoint Then
Set .Anchor = .Anchor.End
End If
Set .Text = .Anchor.Text
Set .Cursor = .Text.createTextCursorByRange(.Anchor)
End If
End If
If IsNull(.Cursor) Then .Location = _Component.CurrentSelection.ImplementationName
' WORD, SENTENCE, PARAGRAPH
Case oStr.IsRegex(psTextRange, "\|?\s*(PARAGRAPH|§|SENTENCE|WORD)\s*([+-][0-9]+)?\s*\|?")
If InStr(psTextRange, "+") > 0 Then
sSign = "+"
ElseIf InStr(psTextRange, "-") > 0 Then
sSign= "-"
End If
If Len(sSign) > 0 Then sTarget = Split(psTextRange, sSign)(0) Else sTarget = psTextRange
If InStr(Iif(.StartPoint, 2, 1), sTarget, "PARAGRAPH", 1) > 0 Or InStr(Iif(.StartPoint, 2, 1), sTarget, "§", 1) > 0 Then
.Target = "Paragraph"
ElseIf InStr(Iif(.StartPoint, 2, 1), sTarget, "SENTENCE", 1) > 0 Then
.Target = "Sentence"
ElseIf InStr(Iif(.StartPoint, 2, 1), sTarget, "WORD", 1) > 0 Then
.Target = "Word"
End If
' Identify the offset
If Len(sSign) = 0 Then
.Offset = 0
Else
sString = Split(psTextRange, sSign)(1)
If .EndPoint Then sString = Left(sString, Len(sString) - 1)
.Offset = CLng(sString) * Iif(sSign = "+", 1, -1)
End If
' Build the cursor pointing at the current selection
If _Component.CurrentSelection.ImplementationName = "SwXTextRanges" Then
lSelects = _Component.CurrentSelection.Count
If lSelects > 0 Then
Set .Anchor = _Component.CurrentSelection.getByIndex(lSelects - 1)
Set .Text = .Anchor.Text
Set .Cursor = .Text.createTextCursorByRange(.Anchor)
End If
End If
If IsNull(.Cursor) Then
.Location = _Component.CurrentSelection.ImplementationName
Else
' Move the cursor to the requested area
With .Cursor
Select Case oTextRange.Target
Case "Word"
bMove = .gotoStartOfWord(False)
If bMove Then
For i = 1 To Abs(oTextRange.Offset)
If sSign = "+" Then bMove = .gotoNextWord(False) Else bMove = .gotoPreviousWord(False)
If sSign = "+" Then
If Not bMove Then Exit For
If .isEndOfSentence() Then i = i - 1 ' Loop to do once more
Else
bMove = .goLeft(1, False) ' Additional trial to bypass some locks (tabs, list items, ... ?)
If Not bMove Then Exit For
End If
Next i
End If
' Cursor is always at the start of a word, move it when necessary
If Not oTextRange.StartPoint And oTextRange.EndPoint Then
.gotoEndOfWord(False)
ElseIf oTextRange.StartPoint = oTextRange.EndPoint Then
.gotoEndOfWord(True)
End If
Case "Sentence"
bMove = .gotoStartOfSentence(False)
If bMove Then
For i = 1 To Abs(oTextRange.Offset)
If sSign = "+" Then bMove = .gotoNextSentence(False) Else bMove = .gotoPreviousSentence(False)
If sSign = "+" Then
If .isEndOfParagraph() Then bMove = .goRight(1, False)
Else
bMove = .goLeft(1, False) ' Additional trial to bypass some locks (tabs, list items, ... ?)
If .isStartOfParagraph() Then bMove = .goLeft(1, False)
End If
If Not bMove Then Exit For
Next i
End If
' Cursor is always at the start of a sentence, move it when necessary
If Not oTextRange.StartPoint And oTextRange.EndPoint Then
.gotoEndOfSentence(False)
ElseIf oTextRange.StartPoint = oTextRange.EndPoint Then
.gotoEndOfSentence(True)
End If
Case "Paragraph"
bMove = .gotoStartOfParagraph(False)
If bMove Then
For i = 1 To Abs(oTextRange.Offset)
If sSign = "+" Then bMove = .gotoNextParagraph(False) Else bMove = .gotoPreviousParagraph(False)
If sSign = "+" Then
If .isEndOfParagraph() Then bMove = .goRight(1, False)
Else
bMove = .goLeft(1, False) ' Additional trial to bypass some locks (tabs, list items, ... ?)
If .isStartOfParagraph() Then bMove = .goLeft(1, False)
End If
If Not bMove Then Exit For
Next i
End If
' Cursor is always at the start of a Paragraph, move it when necessary
If Not oTextRange.StartPoint And oTextRange.EndPoint Then
.gotoEndOfParagraph(False)
ElseIf oTextRange.StartPoint = oTextRange.EndPoint Then
.gotoEndOfParagraph(True)
End If
End Select
End With
End If
' Bookmarks, Fields, Frames, Sections
Case oStr.IsRegex(psTextRange, "\|?\s*(BOOKMARK|FIELD|FRAME|SECTION)!([\w\s]+|'[^']+'|""[^""]+"")\|?")
sTarget = Split(psTextRange, "!")(0)
If InStr(Iif(.StartPoint, 2, 1), sTarget, "BOOKMARK", 1) > 0 Then
.Target = "Bookmark"
ElseIf InStr(Iif(.StartPoint, 2, 1), sTarget, "FIELD", 1) > 0 Then
.Target = "Field"
ElseIf InStr(Iif(.StartPoint, 2, 1), sTarget, "FRAME", 1) > 0 Then
.Target = "Frame"
ElseIf InStr(Iif(.StartPoint, 2, 1), sTarget, "SECTION", 1) > 0 Then
.Target = "Section"
End If
' Identify section or frame or bookmark or field by its name
sString = Split(psTextRange, "!")(1)
If .EndPoint Then sString = Left(sString, Len(sString) - 1)
sLeft1 = Left(sString, 1)
If (sLeft1 = """" Or sLeft1 = "'") And Len(sString) > 2 Then .TargetName = Trim(Mid(sString, 2, Len(sString) - 2)) Else .TargetName = Trim(sString)
Select Case .Target
Case "Bookmark" : Set oColl = _Component.getBookmarks()
Case "Field" : Set oColl = _Component.getTextFieldMasters()
.TargetName = "com.sun.star.text.fieldmaster.User." & .TargetName
If Not oColl.hasByName(.TargetName) Then .TargetName = Replace(.TargetName, ".User.", ".SetExpression.")
Case "Frame" : Set oColl = _Component.getTextFrames()
Case "Section" : Set oColl = _Component.getTextSections()
End Select
If .Target = "Field" Then vNames = Fields() Else vNames = oColl.getElementNames()
If Not ScriptForge.SF_Utils._Validate(.TargetName, .Target, V_STRING, vNames, True) Then GoTo Finally
Set .TargetObject = oColl.getByName(.TargetName)
' Set text, anchor and cursor: order varies depending on target
Select Case .Target
Case "Bookmark", "Field", "Section"
If .Target = "Field" Then Set .Anchor = .TargetObject.DependentTextFields(0).Anchor Else Set .Anchor = .TargetObject.Anchor
If .StartPoint And Not .EndPoint Then
Set .Anchor = .Anchor.Start
ElseIf Not .StartPoint And .EndPoint Then
Set .Anchor = .Anchor.End
End If
Set .Text = .Anchor.Text
Set .Cursor = .Text.createTextCursorByRange(.Anchor)
Case "Frame"
Set .Text = .TargetObject.Start.Text
Set .Anchor = .Text.Anchor
Set .Cursor = .Text.createTextCursor()
If .StartPoint And Not .EndPoint Then
.Cursor.gotoStart(False)
ElseIf Not .StartPoint And .EndPoint Then
.Cursor.gotoEnd(False)
Else
.Cursor.gotoStart(False)
.Cursor.gotoEnd(True)
End If
Case Else
End Select
' Body
Case oStr.IsRegex(psTextRange, "\|0\s*?BODY\s*\|?")
Set .Text = _Component.Text
Set .Anchor = .Text.Start
Set .Cursor = .Text.createTextCursor()
If .StartPoint And Not .EndPoint Then
.Cursor.gotoStart(False)
ElseIf Not .StartPoint And .EndPoint Then
Set .Anchor = .Text.End
.Cursor.gotoEnd(False)
Else
.Cursor.gotoStart(False)
.Cursor.gotoEnd(True)
End If
' Table cell
Case oStr.IsRegex(psTextRange, "\|?\s*TABLE!([\w\s]+|'[^']+'|""[^""]+"")![\s]*[A-Za-z]+[1-9][0-9]*\s*\|?")
.Target = "TableCell"
' Identify table by its name
sString = Split(psTextRange, "!")(1)
sLeft1 = Left(sString, 1)
If (sLeft1 = """" Or sLeft1 = "'") And Len(sString) > 2 Then .TargetName = Trim(Mid(sString, 2, Len(sString) - 2)) Else .TargetName = Trim(sString)
Set oColl = _Component.getTextTables()
vNames = oColl.getElementNames()
If Not ScriptForge.SF_Utils._Validate(.TargetName, .Target, V_STRING, vNames, True) Then GoTo Finally
Set oItem = oColl.getByName(.TargetName)
.TargetCell = Split(psTextRange, "!")(2)
' Set text, anchor and cursor
Set .TargetObject = oItem.getCellByName(.TargetCell)
If IsNull(.TargetObject) Then GoTo CatchRange ' The given range is out of the scope of the table
Set .Text = .TargetObject.Text
Set .Anchor = .Text.Start
Set .Cursor = .Text.createTextCursor()
If .StartPoint And Not .EndPoint Then
.Cursor.gotoStart(False)
ElseIf Not .StartPoint And .EndPoint Then
Set .Anchor = .Text.End
.Cursor.gotoEnd(False)
Else
.Cursor.gotoStart(False)
.Cursor.gotoEnd(True)
End If
Case Else
GoTo CatchRange
End Select
' Determine Location if not yet done
If .Location = "" And Not IsNull(.Text) Then
Select Case .Text.ImplementationName
Case "SwXBodyText" : .Location = "Body"
Case "SwXTextFrame" : .Location = "Frame"
Case "SwXCell" : .Location = "Cell"
Case "SwXHeadFootText" : .Location = "Header/Footer"
Case "SwXFootnote" : .Location = "Footnote/Endnote"
Case "SwXShape" : .Location = "Shape"
Case Else : .Location = .Text.ImplementationName
End Select
End If
End With
Finally:
Set _ParseRange = oTextRange
Exit Function
CatchError:
ScriptForge.SF_Exception.Clear()
CatchRange:
ScriptForge.SF_Exception.RaiseFatal(WRITERRANGEERROR, "TextRange", psTextRange _
, "Document", [_Super]._FileIdent())
GoTo Finally
End Function ' SFDocuments.SF_Writer._ParseRange
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 oFieldMasters As Object ' SwXTextFieldMasters
Dim vMasters As Variant ' Array of SwXTextFieldMasters
Dim oMaster As Object ' A single SwXTextFieldMasters
Dim sField As String ' A text field full name
Dim vFieldNames As Variant ' Array of field names as strings
Dim cstThisSub As String
Const cstSubArgs = ""
_PropertyGet = False
cstThisSub = "SFDocuments.Writer.get" & psProperty
ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
If Not _IsStillAlive() Then GoTo Finally
Select Case UCase(psProperty)
Case UCase("Bookmarks")
_PropertyGet = _Component.getBookmarks().getElementNames()
Case UCase("CurrentSelection")
_PropertyGet = _Component.CurrentSelection
Case UCase("Fields")
vFieldNames = Array()
Set oFieldMasters = _Component.getTextFieldMasters()
vMasters = oFieldMasters.getElementNames()
For Each sField In vMasters
If ScriptForge.SF_String.StartsWith(sField, "com.sun.star.text.fieldmaster.User") Then
Set oMaster = oFieldMasters.getByName(sField)
vFieldNames = ScriptForge.SF_Array.InsertSorted(vFieldNames, oMaster.Name, CaseSensitive := True)
ElseIf ScriptForge.SF_String.StartsWith(sField, "com.sun.star.text.fieldmaster.SetExpression") Then
Set oMaster = oFieldMasters.getByName(sField)
If oMaster.SubType = com.sun.star.text.SetVariableType.VAR Then
vFieldNames = ScriptForge.SF_Array.InsertSorted(vFieldNames, oMaster.Name, CaseSensitive := True)
End If
End If
Next sField
_PropertyGet = vFieldNames
Case UCase("Frames")
_PropertyGet = _Component.getTextFrames().getElementNames()
Case Else
_PropertyGet = Null
End Select
Finally:
ScriptForge.SF_Utils._ExitFunction(cstThisSub)
Exit Function
End Function ' SFDocuments.SF_Writer._PropertyGet
REM -----------------------------------------------------------------------------
Private Function _Repr() As String
''' Convert the SF_Writer instance to a readable string, typically for debugging purposes (DebugPrint ...)
''' Args:
''' Return:
''' "[DOCUMENT]: Type/File"
_Repr = "[Writer]: " & [_Super]._FileIdent()
End Function ' SFDocuments.SF_Writer._Repr
REM ============================================ END OF SFDOCUMENTS.SF_WRITER
</script:module>