Я получил задание написать скрипт 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
Я уже несколько дней искал в Интернете, но безрезультатно.
При записи генерируется код диспетчера, который обычно бесполезен. Но пример StarBasic выглядит хорошо. Взгляните на Переход с Basic на Python и руководство, а затем попытайтесь переписать InsertFieldIntoDocument
на python-uno. Если у вас все получится, опубликуйте ответ. В противном случае отредактируйте вопрос, чтобы показать свой код и возникшие проблемы.
Возможно, также стоит взглянуть на мой перевод на C++ по адресу stackoverflow.com/questions/62509424/….
Это не ответ, но вот код, который я написал некоторое время назад, и который может оказаться полезным для решения проблемы.
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)
Я редко делаю это, но хочу поздравить с написанием кода для сообщества открытого исходного кода. У тебя хорошая работа. Вопрос проголосован.