Вставка UserField в документ из python скрипта

Автор kireev20000, 19 апреля 2024, 16:48

0 Пользователи и 1 гость просматривают эту тему.

kireev20000

Здравствуйте, сегодня на работе дали задание написать скрипт для коллаборы который вставляет UserField из переменных в документ по нажатию кнопки. Метом гугления удалось найти скрипт который вставляет текст в документ (по нажатие кнопки в браузере). Весь день просидев за темой понял что она огромна и с наскока тут не получится. Учитывая что макросс вставки текста есть, по логике мне всего лишь нужно найти способ вставить UserFiled вместо текста который прилетает в функцию, но как это сделать ума не приложу, может кто подскажет где хотя бы это искать.

скрипт который вставляет текст, работает успешно
def insert_user_variable(var_name):
    """Вставляет UserField в текст."""
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()

    # Проверяем, есть ли уже открытый документ.
    if not hasattr(model, "Text"):
        return

    # The context variable is of type XScriptContext and is available to
    # all BeanShell scripts executed by the Script Framework
    xModel = XSCRIPTCONTEXT.getDocument()

    # The writer controller impl supports the css.view.XSelectionSupplier
    # interface.
    xSelectionSupplier = xModel.getCurrentController()

    # See section 7.5.1 of developers' guide
    xIndexAccess = xSelectionSupplier.getSelection()
    count = xIndexAccess.getCount()

    if count >= 1:  # ie we have a selection
        i = 0

   
    while i < count:
        xTextRange = xIndexAccess.getByIndex(i)
        theString = xTextRange.getString()

        if not len(theString):
            # Nothing really selected, just insert.
            xText = xTextRange.getText()
            xWordCursor = xText.createTextCursorByRange(xTextRange)
            xWordCursor.setString(var_name)
            xSelectionSupplier.select(xWordCursor)
        else:
            # Replace the selection.
            xTextRange.setString(var_name)
            xSelectionSupplier.select(xTextRange)

        i += 1

economist

Для StarBasic примеров больше. В ScriptForges искали?

Вставить Поле проще всего Автотекстом, и расширить для всего офиса по сети. И макрос не нужен. Поле м.б. каким угодно, даже Списком (Текст).
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

kireev20000

Цитата: economist от 19 апреля 2024, 17:22Для StarBasic примеров больше. В ScriptForges искали?

Вставить Поле проще всего Автотекстом, и расширить для всего офиса по сети. И макрос не нужен. Поле м.б. каким угодно, даже Списком (Текст).

мне нужно именно через макросс. ScriptForges поискал, но ничего не нашел. (тема для меня в целом новая, буквально первый день, на работе правда ждать не будут пока тут два месяца разбираться буду в скриптинге).

mikekaganski

С уважением,
Михаил Каганский

kireev20000

Цитата: mikekaganski от 19 апреля 2024, 18:11https://ask.libreoffice.org/t/inserting-fields-inside-a-document-from-a-macro/101541/7

да это я тоже находил, но код на бейсике, и как его в моему скрипту прикрутить не очень ясно.

mikekaganski

А есть большая разница? Код показывает, в какой последовательности какие вызовы API нужны. Они одни и те же, независимо от языка, из которого они вызываются.
С уважением,
Михаил Каганский

kireev20000

Всё еще занимаюсь этой задачей, тема просто огромная, а документации кот наплакал.
От безысходности записал в Либреоффисе макрос в нужным действием

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 = "ФИО222"
args1(4).Name = "Format"
args1(4).Value = -1
args1(5).Name = "Separator"
args1(5).Value = " "

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

переписал на питон, вроде тоже самое, но не работает.

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", "ФИО222"),
        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

Над этим примером тоже голову ломал, непонятно как это переписать на питон. Полдня читал книгу OpenOffice.org Macros Explained_4_0.odt, но понятней как то не стало, да и документация по УНО обе ноги слоамешь.
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

economist

Макрорекордер в LO часто даёт код, который ничего не делает. Видимо число методов Диспетчера в разы меньшее API.

Рассмотрите План Б: Шаблоны с полями, Автотекст для вставки, Поля-макросы для вставки Полей пользователя. На Basic примеров много, Python добавляет сложности, особенно тем кто привык к ясности питона.

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

kireev20000

я сделал что хотел  :beer:  в основном благодаря книге OpenOffice.org Macros Explained_4_0.odt

import uno


def insert_user_variable(userfield_name=None):
    """Вставляет UserField в текст."""
    oDoc = XSCRIPTCONTEXT.getDocument()
    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)