MyTetra Share
Делитесь знаниями!
Python как язык макросов для OpenOffice.org
27.12.2017
18:37
Текстовые метки: Python
Раздел: Python - script-coding.com

Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также любые проблемы программирования на различных макроязыках и в скриптовых средах)

Python как язык макросов для OpenOffice.org

Скриптовая оболочка OOo, поставляемая с OOo 2.0, поддерживает макросы на Python. В настоящее время поддержка ограничена, и работают только функции назначения и исполнения макросов через стандартный диалог Tools/Macro, тогда как редактирование и отладка макросов в графическом интерфейсе OpenOffice.org пока не предусмотрены (просто по причине нехватки ресурсов у разработчиков). Для создания и модификации скриптов на языке Питон можно использовать любой текстовый редактор.

Размещение скриптов

Скрипты, предназначенные для исполнения в OpenOffice.org, могут храниться следующим образом:

  • В пользовательском каталоге OpenOffice.org.
  • В общем каталоге OpenOffice.org.
  • Внутри документа OpenOffice.org.
  • Внутри пакетов UNO (uno-packages, в данной статье не рассматриваются).

Пользовательский каталог является стандартным местом хранения для скриптов, написанных на Питоне. При этом скриптовые файлы просто сохраняются в файловой системе. В операционной системе Windows каталог обычно располагается здесь:

%userprofile%\Application Data\OpenOffice.org 2.0\user\Scripts\python 

А в *nix здесь:

~/.openoffice.org.2.0/user/Scripts/python 

Обратите внимание на то, что может возникнуть необходимость в первоначальном создании последнего подкаталога "python". Убедитесь, что слово "python" полностью набрано в нижнем регистре. Вы можете произвольно создавать глубоко вложенные подпапки. Их названия будут отражаться в графическом интерфейсе OOo.

Пример: вы можете поместить py-файл примера, приведенного далее, в обозначенную выше папку. После этого откройте диалог Tools/Macros/Run Macro и осуществите навигацию до нужной позиции. Щелкните по кнопке Run, чтобы выполнить скрипт, в результате чего откроется диалог с кнопкой и надписью (это уже будет работа макроса). Каждый щелчок мышкой по этой кнопке будет увеличивать число на надписи. Диалог можно закрыть при помощи клавиши ESC.

Код примера:

import uno
import unohelper
from com.sun.star.awt import XActionListener

class MyActionListener( unohelper.Base, XActionListener ):
    def __init__(self, labelControl, prefix ):
        self.nCount = 0
        self.labelControl = labelControl
        self.prefix = prefix
        
    def actionPerformed(self, actionEvent):
        # increase click counter 
        self.nCount = self.nCount + 1;
        self.labelControl.setText( self.prefix + str( self.nCount ) )

# 'translated' from the developer's guide chapter 11.6
def createDialog():
    """Opens a dialog with a push button and a label,
    clicking the button increases the label counter."""
    try:
        ctx = uno.getComponentContext()
        smgr = ctx.ServiceManager

        # create the dialog model and set the properties 
        dialogModel = smgr.createInstanceWithContext( 
            "com.sun.star.awt.UnoControlDialogModel", ctx)

        dialogModel.PositionX = 100
        dialogModel.PositionY = 100
        dialogModel.Width = 150 
        dialogModel.Height = 100
        dialogModel.Title = "Runtime Dialog Demo"

        # create the button model and set the properties 
        buttonModel = dialogModel.createInstance( 
            "com.sun.star.awt.UnoControlButtonModel" )

        buttonModel.PositionX = 50
        buttonModel.PositionY  = 30 
        buttonModel.Width = 50; 
        buttonModel.Height = 14; 
        buttonModel.Name = "myButtonName"; 
        buttonModel.TabIndex = 0;         
        buttonModel.Label = "Click Me"; 

        # create the label model and set the properties 
        labelModel = dialogModel.createInstance( 
            "com.sun.star.awt.UnoControlFixedTextModel" ); 

        labelModel.PositionX = 40 
        labelModel.PositionY = 60 
        labelModel.Width  = 100 
        labelModel.Height = 14 
        labelModel.Name = "myLabelName" 
        labelModel.TabIndex = 1
        labelModel.Label = "Clicks "

        # insert the control models into the dialog model 
        dialogModel.insertByName( "myButtonName", buttonModel); 
        dialogModel.insertByName( "myLabelName", labelModel); 

        # create the dialog control and set the model 
        controlContainer = smgr.createInstanceWithContext( 
            "com.sun.star.awt.UnoControlDialog", ctx); 
        controlContainer.setModel(dialogModel); 

        # add the action listener
        controlContainer.getControl("myButtonName").addActionListener(
            MyActionListener( controlContainer.getControl( "myLabelName" ), labelModel.Label ))

        # create a peer 
        toolkit = smgr.createInstanceWithContext( 
            "com.sun.star.awt.ExtToolkit", ctx);       

        controlContainer.setVisible(False);       
        controlContainer.createPeer(toolkit, None);

        # execute it
        controlContainer.execute()

        # dispose the dialog 
        controlContainer.dispose()
    except Exception,e:
        print str(e)

g_exportedScripts = createDialog, 

Скрипты, которые будут использоваться всеми пользователями этой инсталляции OpenOffice.org, можно поместить в общий каталог, в котором находятся все скрипты, по умолчанию поставляемые вместе с OpenOffice.org.

Обычно в операционной системе Windows этот каталог находится здесь:

C:\Program Files\OpenOffice.org 2.0\share\Scripts\python 

А в *nix здесь:

/usr/lib/openoffice/share/Scripts/python 

Документ OpenOffice.org представляет собой zip-файл, содержащий различные файлы и папки. Скрипты, написанные на языке Питон, хранятся внутри документа в подкаталоге Scripts/python.

Если вы хотите разместить написанные вами скрипты внутри документа, то сначала вам необходимо создать их, например, в пользовательском каталоге (о котором упоминалось выше) и только затем при помощи архиватора переместить скрипты в документ. В идеальном случае вам нужно вначале убрать ваши скрипты из каталога, где вы их создавали и отлаживали, а затем провести тест функциональности документа.

При открытии документа OpenOffice.org оповестит вас о том, что внутри документа находятся скрипты. Если оповещения не последовало, значит, вы либо отключили соответствующую опцию, либо сделали что-то неправильно.

Важно: при сохранении документа OpenOffice.org удалит ваши скрипты из документа, если вы не пропишете их заранее внутри документа в файле META-INF/manifest.xml:

<manifest:file-entry manifest:media-type="" manifest:full-path="Scripts/python/my_script.py"/>
<manifest:file-entry manifest:media-type="application/binary" manifest:full-path="Scripts/python/"/>
<manifest:file-entry manifest:media-type="application/binary" manifest:full-path="Scripts/"/> 

Написание скриптов

Макрос для скриптовой оболочки OpenOffice.org представляет собой функцию (введенную ключевым словом def) внутри py-файла. Чтобы можно было исполнить макрос при помощи диалога Tools/Macros/Run macro, список аргументов функции должен быть пуст (примечание: некоторые версии OpenOffice.org - наоборот, требуют наличие у функции единственного аргумента). Для обычных обработчиков событий (event listener), функция должна содержать только один аргумент – событие. В целом, количество аргументов зависит от того, где функция будет использоваться. Важно: в настоящее время .py-файл должен использовать переводы строк в стиле unix, однако в будущем это условие может измениться.

Один .py-файл может содержать произвольное количество определений функций. По умолчанию все определения функций экспортируются (т.е. отображаются внутри диалога OpenOffice.org, предназначенного для выбора макросов). Можно ограничить экспорт меньшим количеством функций, введя для этого глобальную переменную g_exportedScripts, представляющую собой кортеж имён функций.

В настоящее время py-файлам под силу импортировать только модули питона, указанные в PYTHONPATH. Это означает, что py-файлы не могут ссылаться на другие макро-файлы, написанные на питоне. В будущем это ограничение, возможно, будет снято.

Перед исполнением кода модуля в качестве глобальной переменной в модуль импортируется глобальная переменная XSCRIPTCONTEXT (эта переменная также есть в javascript и beanshell, и вставлена в Питон из соображений совместимости). Переменная имеет три составляющие - Document, Desktop и ComponentContext.

Комментарий функции, начинающийся и заканчивающийся тремя двойными кавычками ("), отображаются как описание в диалоге выбора макросов.

Устранение ошибок и отладка

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

В данный момент функция подключения отладчика Питона не поддерживается.

Подключение к OpenOffice.org "извне"

UNO (Universal Network Objects) является интерфейсом, предоставляющим доступ к компонентной модели OpenOffice.org для кроссплафторменного и языконезависимого программирования (это аналог технологии COM для Windows). Python-UNO bridge (PyUNO) позволяет как использовать OpenOffice.org API из языка Python, так и вызывать сценарии Python непосредственно в контексте документа OpenOffice.org (начиная с версии OOo 2.0), что и было описано выше.

Для того, чтобы скрипт успешно импортировал модуль uno, необходимо запускать Python в каталоге, где этот модуль находится, т.е. в каталоге программы OpenOffice.org, который может выглядеть примерно так:

/usr/lib/ooo-2.0/program 

Если скрипт запускается в контексте OpenOffice.org (как макрос), модуль uno будет импортирован успешно в любом случае.

Кроме того, для успешного импортирования модуля uno можно прописать путь к каталогу программы OpenOffice.org в переменную среды PYTHONPATH различными способами. Например, запустить скрипт так:

PYTHONPATH=$PYTHONPATH:/usr/lib/ooo-2.0/program python <путь к скрипту> 

Или установить переменную среды PYTHONPATH непосредственно перед запуском скрипта:

export PYTHONPATH=/usr/lib/ooo-2.0/program
python <путь к скрипту> 

Или прописать установку переменной среды PYTHONPATH в автоматически загружаемом сценарии оболочки, например, в файле ~/.bashrc:

export PYTHONPATH=$PYTHONPATH:/usr/lib/ooo-2.0/program 

Кроме того, можно прописать путь к нужному каталогу прямо в самом скрипте:

import sys
sys.path.append('/usr/lib/ooo-2.0/program')
import uno
... 

Текст скрипта:

import uno

# получаем контекст PyUNO
localContext = uno.getComponentContext()

# создаём UnoUrlResolver
resolver = localContext.ServiceManager.createInstanceWithContext(
    "com.sun.star.bridge.UnoUrlResolver", localContext)

# подключаемся к запущенному офису
ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
smgr = ctx.ServiceManager

# получаем объект рабочего стола
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)

# получаем доступ к текущему документу
model = desktop.getCurrentComponent()

# получаем доступ к свойству документа text
text = model.Text

# создаем курсор
cursor = text.createTextCursor()

# вставляем текст в документ
text.insertString(cursor, "Hello, World!", 0)

# В случае, если последний вызов является асинхронным (в нашем случае это insertString),
# нужно синхронизировать remote-bridge кэш перед тем, как питон завершит процесс.
# Иначе достижение результата асинхронным вызовом не гарантировано.
# Делаем это посредством "бесполезного" чтения свойства ServiceManager,
# что является синхронным вызовом, который приводит к автоматической синхронизации кэша.
ctx.ServiceManager 

Чтобы вышеприведённый скрипт сработал, OOo должен быть запущен в "слушающем" режиме с помощью примерно такой команды:

soffice "-accept=socket,host=localhost,port=2002;urp;" 

Кроме того, должен быть открыт текстовый документ Writer (можно добавить параметр -writer в командную строку).

Скрипт вставит в начало документа текст "Hello, World!".


Источники информации (англ.):

Людоговский Александр

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.

 
MyTetra Share v.0.52
Яндекс индекс цитирования