Вставьте UserField в LibreOffice, используя API/макрос

Я получил задание написать скрипт Python для LibreOffice (точнее, для Collabora Online), который вставляет поле пользователя в документ. Я записал макросы в LibreOffice с необходимыми действиями.

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

Переписал этот код на Python, и он не сработал.

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

Я нашел здесь скрипт (вероятно, Starbasic) с тем же функционалом, но понятия не имею, как использовать его для своих целей в 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

Я уже несколько дней искал в Интернете, но безрезультатно.

Я редко делаю это, но хочу поздравить с написанием кода для сообщества открытого исходного кода. У тебя хорошая работа. Вопрос проголосован.

darren 23.04.2024 15:16

При записи генерируется код диспетчера, который обычно бесполезен. Но пример StarBasic выглядит хорошо. Взгляните на Переход с Basic на Python и руководство, а затем попытайтесь переписать InsertFieldIntoDocument на python-uno. Если у вас все получится, опубликуйте ответ. В противном случае отредактируйте вопрос, чтобы показать свой код и возникшие проблемы.

Jim K 23.04.2024 15:16

Возможно, также стоит взглянуть на мой перевод на C++ по адресу stackoverflow.com/questions/62509424/….

Jim K 23.04.2024 15:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это не ответ, но вот код, который я написал некоторое время назад, и который может оказаться полезным для решения проблемы.

oDoc = XSCRIPTCONTEXT.getDocument()
xTextFieldsSupplier = oDoc
if not xTextFieldsSupplier:
    raise Exception("No xTextFieldsSupplier")
xTextFieldsInfo = xTextFieldsSupplier.getTextFieldMasters()
if not xTextFieldsInfo:
    raise Exception("No xTextFieldsInfo")
xTextFieldsNames = xTextFieldsInfo.getElementNames()
oVC = oDoc.getCurrentController().getViewCursor()
oVC.getText().insertString(oVC, "Hello!\n", False)
for field in xTextFieldsNames:
    xField = xTextFieldsInfo.getByName(field)
    oVC.getText().insertString(oVC, "{}\n".format(xField.Name), False)

Кроме того, в этом коде, написанном в 2010 году, я использовал диспетчер. Но если ваш проект не имеет такого же дизайна, предпочтительнее использовать код API.

"""
...the .uno:InsertField call seems
to fail when called within a dialog event handler.

...there does not seem to be a way to create
a "Number Range" master field or text field with the API,
only SetExpression items which are not as flexible.
"""
uno_args = (
    util.createProp("Type", 23),
    util.createProp("SubType", 127),
    util.createProp("Name", "AutoNr"),
    util.createProp("Content", ""),
    util.createProp("Format", 4),
    util.createProp("Separator", " ")
)
self.unoObjs.dispatcher.executeDispatch(
    self.unoObjs.frame, ".uno:InsertField", "", 0, uno_args)
Ответ принят как подходящий

Сделал это.

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)

Другие вопросы по теме