python-3.xscriptinglibreoffice

Insert UserField into LibreOffice using API/Macro


i got task to write python script for LibreOffice (for Collabora online to be exact), which inserts userfield into document. I recorded macros in LibreOffice with needed actions

sub Main
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(5) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Type"
args1(0).Value = 20
args1(1).Name = "SubType"
args1(1).Value = 1
args1(2).Name = "Name"
args1(2).Value = "FIO"
args1(3).Name = "Content"
args1(3).Value = "FIO222"
args1(4).Name = "Format"
args1(4).Value = -1
args1(5).Name = "Separator"
args1(5).Value = " "

dispatcher.executeDispatch(document, ".uno:InsertField", "", 0, args1())
End sub

Rewrited this code to python, and it didnt work.

import uno

def InsertLinkedImage():
    ctx = XSCRIPTCONTEXT.getComponentContext()
    smgr = ctx.ServiceManager
    oDisp = smgr.createInstanceWithContext(
        "com.sun.star.frame.DispatchHelper", ctx)
    oDoc = XSCRIPTCONTEXT.getDocument()
    oFrame = oDoc.getCurrentController().getFrame()
    props = (
        createProp("Type", 20),
        createProp("SubType", 1),
        createProp("Name", "FIO"),
        createProp("Content", "FIO222"),
        createProp("Format", -1),
        createProp("Separator", ""),
    )
    oDisp.executeDispatch(oFrame, ".uno:InsertField", "", 0, props)

def createProp(name, value):
    """Creates an UNO property."""
    prop = uno.createUnoStruct("com.sun.star.beans.PropertyValue")
    prop.Name = name
    prop.Value = value
    return prop

I found script (Starbasic probably) here with same functional, but i have no idea how to use it for my purpose in python.

Sub InsertFieldIntoDocument(sFieldName As String, Optional bSection As Boolean, Optional bSectionOpened As Boolean)

    Dim oDoc As Object
    Dim oText As Object
    Dim oViewCursor As Object
    Dim oUserFieldMaster, oUserFieldMasters, oUserField As Object
    Dim bMasterExists As Boolean
    Dim sPrefix As String

    oDoc = ThisComponent
    oText = oDoc.getText()
    oViewCursor = oDoc.getCurrentController().getViewCursor()
   
    ' Handling optional values
    If IsMissing(bSection) Then bSection = False
    If IsMissing(bSectionOpened) Then bSectionOpened = False

    ' Getting the collection of masters of user fields
    oUserFieldMasters = oDoc.getTextFieldMasters()
    bMasterExists = False

    ' Checks is master field already exists
    sCalculatedFieldName = sFieldName
    ' If it's a section, we have to search for a specific field name
    If bSection Then
        If bSectionOpened Then
            sCalculatedFieldName = "SECT_" & sFieldName
        Else
            sCalculatedFieldName = "SECT_END_" & sFieldName
        End If
    End If
    If oUserFieldMasters.hasByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName) Then
        bMasterExists = True
        oUserFieldMaster = oUserFieldMasters.getByName("com.sun.star.text.fieldmaster.User." & sCalculatedFieldName)
    End If

    ' Creates master field if it doesn't exist
    If Not bMasterExists Then
        oUserFieldMaster = oDoc.createInstance("com.sun.star.text.fieldmaster.User")
        oUserFieldMaster.Name = sCalculatedFieldName
        oUserFieldMaster.Content = ""
        Msgbox oUserFieldMaster.Value
    End If

    ' Creates the textfield that uses master
    oUserField = oDoc.createInstance("com.sun.star.text.textfield.User")
    oUserField.attachTextFieldMaster(oUserFieldMaster)

    ' Insert the field in the document
    oText.insertTextContent(oViewCursor, oUserField, False)

End Sub

I searched internet for days already, but to no avail.


Solution

  • Done it.

    import uno
    
    
    def insert_user_variable(userfield_name=None):
        """Вставляет UserField в текст."""
        oDoc = XSCRIPTCONTEXT.getDocument()
        # userfield_name = "FIO"
        sLead = "com.sun.star.text.FieldMaster.User"
        sTotName = sLead + "." + userfield_name
        oText = oDoc.Text
        oMasters = oDoc.getTextFieldMasters()
        oUField = oDoc.createInstance("com.sun.star.text.TextField.User")
        oMasterField = oMasters.getByName(sTotName)
        oUField.attachTextFieldMaster(oMasterField)
        oText.insertTextContent(oText.getEnd(), oUField, False)