Начала программирования в OpenOffice.org

37
OpenOffice.org Developer Guide – Ch.2 First Steps. перевод kitovras – 2007г. Начала программирования в OpenOffice.org Программирование в UNO Основной технологией OpenOffice.org выступает UNO (Universal Network Objects – Универсальные Сетевые Объекты). Эта технология позволяет использовать и создавать компоненты, работающие независимо от языка программирования, компонентной технологии, компьютерной платформы и типа используемой сети. В настоящее время варианты UNO доступны для Linux, Solaris, Power PC, Windows, FreeBSD и Mac OS X, поддерживаются языки Java, C++ и OpenOffice.org Basic. Другие порты – на стадии разработки. Через компонентную технология MS COM UNO доступно для многих других языков, в OpenOffice.org есть привязка к Python. Возможно программирование для OpenOffice.org UNO с использованием .NET языков, при помощи CLI (Common Language Infrastructure – Общая Инфраструктура Языков), и с применением сценарных языков, таких, как JavaScript, Beanshell или Jython. Для доступа к OpenOffice.org UNO использует API (Application Programming Interface – Интерфейс Прикладного Программирования) OpenOffice.org. Области приложения UNO При помощи UNO можно соединиться с локальным или удаленным экземпляром OpenOffice.org при помощи C++, Java, COM/DCOM C++ и Java десктоп-приложений, сервлетов Java, Java Server Pages, JScript, VBScript и языков наподобие Delphi, Visual Basic и многих других. На C++ или Java можно разработать компоненты UNO, экземпляры которых будут создаваться OpenOffice.org и добавлять к офисным приложениям новые возможности. Например, можно написать Add-in-ы для Chart, Calc, лингвистические расширения, файловые фильтры, драйверы баз данных. Можно создавать и завершенные, полно- функциональные приложения, в том числе и для групповой работы. Компоненты UNO (как и, к примеру, Java Beans) объединяются с Java IDE, что облегчает доступ к OpenOffice.org .В настоящее время разрабатывается набор таких компонентов, которые позволят редактировать документы OpenOffice.org в приложениях Java. OpenOffice.org Basic связан с UNO так, что программы UNO могут быть написаны непосредственно в OpenOffice.org . Используя этот способ, можно создавать собственные офисные решения и мастера, основанные на событийно-управляемой диалоговой парадигме. Ядро управления базами данных, встроенное в OpenOffice.org и связанные с базами данных компоненты открыва- ют область решений, управляемых базами данных. С чего начать Для работы с OpenOffice.org API следует установить некоторые пакеты. Требующиеся файлы Прежде всего, очевидно, надо установить экземпляр OpenOffice.org . Его можно скачать с сайта www.openoffice.org . Справочная информация по OpenOffice.org API является частью пакета разработчика OpenOffice.org SDK (Software Development KIT – Набор для Разработки Программного обеспечения). Справочник по OpenOffice.org API можно загрузить с api.openoffice.org . Установочные пакеты Для разработки приложений OpenOffice.org на Java следует установить: Java Development Kit – Набор для Разработки на Java версии 1.3.1 или более новый. JDK доступен на сайте java.sun.com. Для использования всех возможностей OpenOffice.org нужна версия Java не старше 1.4.1_01. Java IDE, такая, как NetBeans или подобная. OpenOffice.org SDK, который можно загрузить с www.openoffice.org . 1

Transcript of Начала программирования в OpenOffice.org

Page 1: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Начала программирования в OpenOffice.org

Программирование в UNOОсновной технологией OpenOffice.org выступает UNO (Universal Network Objects – Универсальные Сетевые Объекты). Эта технология позволяет использовать и создавать компоненты, работающие независимо от языка программирования, компонентной технологии, компьютерной платформы и типа используемой сети. В настоящее время варианты UNO доступны для Linux, Solaris, Power PC, Windows, FreeBSD и Mac OS X, поддерживаются языки Java, C++ и OpenOffice.org Basic. Другие порты – на стадии разработки. Через компонентную технология MS COM UNO доступно для многих других языков, в OpenOffice.org есть привязка к Python.Возможно программирование для OpenOffice.org UNO с использованием .NET языков, при помощи CLI (Common Language Infrastructure – Общая Инфраструктура Языков), и с применением сценарных языков, таких, как JavaScript, Beanshell или Jython.Для доступа к OpenOffice.org UNO использует API (Application Programming Interface – Интерфейс Прикладного Программирования) OpenOffice.org.

Области приложения UNOПри помощи UNO можно соединиться с локальным или удаленным экземпляром OpenOffice.org при помощи C++, Java, COM/DCOM C++ и Java десктоп-приложений, сервлетов Java, Java Server Pages, JScript, VBScript и языков наподобие Delphi, Visual Basic и многих других.На C++ или Java можно разработать компоненты UNO, экземпляры которых будут создаваться OpenOffice.org и добавлять к офисным приложениям новые возможности. Например, можно написать Add-in-ы для Chart, Calc, лингвистические расширения, файловые фильтры, драйверы баз данных. Можно создавать и завершенные, полно-функциональные приложения, в том числе и для групповой работы.Компоненты UNO (как и, к примеру, Java Beans) объединяются с Java IDE, что облегчает доступ к OpenOffice.org .В настоящее время разрабатывается набор таких компонентов, которые позволят редактировать документы OpenOffice.org в приложениях Java.OpenOffice.org Basic связан с UNO так, что программы UNO могут быть написаны непосредственно в OpenOffice.org . Используя этот способ, можно создавать собственные офисные решения и мастера, основанные на событийно-управляемой диалоговой парадигме.Ядро управления базами данных, встроенное в OpenOffice.org и связанные с базами данных компоненты открыва-ют область решений, управляемых базами данных.

С чего начатьДля работы с OpenOffice.org API следует установить некоторые пакеты.

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

www.openoffice.org. Справочная информация по OpenOffice.org API является частью пакета разработчика OpenOffice.org SDK

(Software Development KIT – Набор для Разработки Программного обеспечения). Справочник по OpenOffice.org API можно загрузить с api.openoffice.org.

Установочные пакетыДля разработки приложений OpenOffice.org на Java следует установить:

Java Development Kit – Набор для Разработки на Java версии 1.3.1 или более новый. JDK доступен на сайте java.sun.com. Для использования всех возможностей OpenOffice.org нужна версия Java не старше 1.4.1_01.

Java IDE, такая, как NetBeans или подобная. OpenOffice.org SDK, который можно загрузить с www.openoffice.org.

1

Page 2: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Конфигурация

Подключение Java к OpenOffice.orgДля создания экземпляров компонентов, написанных на Java, OpenOffice.org использует Java Virtual Machine. На-чиная с версии OpenOffice.org 2.0 Java запускается автоматически при запуске офисного приложения – или позднее, при необходимости. Если требуется заранее выбрать JDK или JRE из имеющихся на компьютере, или если Java не установлена – можно произвести конфигурирование Java, используя диалоговое окно, доступное из меню Сервис->Параметры, в секции OpenOffice.org->Java. В более ранних версиях OpenOffice.org сле-дует использовать утилиту jvmsetup, после чего перезапустить OpenOffice.org.

Использование файлов классов Java UNOРасположение классов OpenOffice.org должно быть сообщено Java IDE. А именно, к проекту Java следует подклю-чить пакеты jurt.jar, unoil.jar, ridl.jar и juh.jar, которые находятся в каталоге <путь_к_OpenOffice.org>/program/classes. Кроме того, следует добавить папки <путь_к_Open-Office.org_SDK>/docs/common/ref и <путь_к_OpenOffice.org_SDK>/docs/java/ref к пути по-иска документации Javadoc – конкретные шаги зависят от используемой IDE. Это позволит легко использовать справочник OpenOffice.org API при работе.

Первый контакт

НачинаемНачиная с версии OpenOffice.org 2.0 стало просто получить рабочее окружение для прозрачного использования функциональности UNO и самого OpenOffice.org .В данном примере показано, как написать маленькую програм-му, инициализирующую UNO. Эта программа соединяется с экземпляром офиса или запускает экземпляр – если офис не был запущен, и сообщает о возможности получить контекст экземпляра офиса, обеспечиваемый объектом офисного менеджера сервисов.

• Создайте файл FirstUnoContact.java и внесите код примера.Не забудьте добавить к проекту jar-файлы, как описано выше.• Для упрощения компиляции можно добавить к проекту ant-файлКонечно же, переменные OFFICE_HOME, OOO_SDK_HOME и OUTDIR в ant-файле придется изменить соответ-ственно тому, что имеется на вашей машине.

Теперь разберем, что происходит при выполнении кода.

Менеджеры сервисовUNO вводит концепцию менеджеров сервисов, которые являются объектами-"фабриками", создающими сер-висы. Сервис, в свою очередь, – объект UNO, выполняющий те или иные задачи (подробнее – позднее).Например, очень часто применяются следующие сервисы:com.sun.star.frame.Desktop обслуживает загруженные документы, используется

для загрузки документа, получения текущего доку-мента и доступа ко всем загруженным документам.

com.sun.star.configuration.Confi-gurationProvider

обеспечивает доступ к настройкам OpenOffice.org , например, к диалоговому окну Сервис->Пара-метры.

com.sun.star.sdb.DatabaseContext работает с базами данных, зарегистрированными в OpenOffice.org.

com.sun.star.system.SystemShellExecu-te

выполняет системные команды или документы, заре-гистрированные для приложения на текущей плат-форме.

com.sun.star.text.GlobalSettings управляет глобальными параметрами настройки вида

2

Page 3: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

и печати текстовых документов.

Сервис всегда существует в компонентном контексте, включающем менеджер сервисов, который создает сервис, и другие данные, используемые сервисом.В приведенном примере экземпляр класса FirstUnoContact – клиент процесса OpenOffice.org, сам же OpenOffice.org – сервер. Сервер имеет собственные компонентный контекст и менеджер сервисов, к которым мо-жет обратиться клиент, чтобы воспользоваться функциональностью офиса.Клиентская программа инициализирует UNO и получает компонентный контекст от процесса OpenOffice.org.Говоря подробнее, инициализирующий процесс создает локальный менеджер сервисов, устанавливает канальное подключение с выполняющимся процессом OpenOffice.org, при необходимости создавая новый процесс, и возвра-щает удаленный компонентный контекст.Метод com.sun.star.comp.helper.Bootstrap.bootstrap() инициализирует UNO и возвращает уда-ленный компонентный контекст выполняющегося процесса OpenOffice.org.После этого можно использовать метод getServiceManager() компонентного контекста для получения уда-ленного менеджера сервисов от процесса OpenOffice.org, что позволяет работать с функциональностью офиса, до-ступной через API.

Нарушение подключенияИногда удаленное подключение может не установиться, либо утратиться в процессе работы.

Клиент должен быть способен обнаружить ошибки. Например, иногда мост может быть недоступен. Простые клиенты, соединяющиеся с офисом, выполняющие некоторую задачу и прекращающие работу, должны выполнить остановку и сообщить пользователю об ошибке соединения.

Клиенты, предполагающие длительную работу, не должны предполагать, что ссылка на начальный объект будет существовать все время работы. Клиент должен возобновлять подключение при разрыве и продол-жать работу. Когда подключение прерывается, длительно работающий клиент должен приостановить те-кущую задачу, сообщить пользователю о том, что подключение не доступно и высвободить ссылку на уда-ленный процесс. Если пользователь пытается повторить последнее действие, клиент должен попытаться восстановить подключение. Не следует строить программу так, чтобы ее надо было перезапускать только потому, что подключение было временно недоступно.

При попытке обращения к мосту, в настоящее время недоступному, возникает исключение com.sum.star.lang.DisposedException. Всегда, когда в программе производится обращение к удален-ные ссылкам, следует отлавливать это исключение, при возникновении его обнулять удаленные ссылки и опове-щать пользователя. Если клиент работает в течение некоторого времени, следует получать новые удаленные ссыл-ки всякий раз, когда они оказываются обнулены.Более сложный способ поддерживать утраченные подключения – регистрация слушателя объекта моста.

3

ServiceManager

Service

Service

Service

«создает »

«создает »

«создает »

Page 4: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Как получить объекты OpenOffice.orgОбъект – это программный артефакт, имеющий методы, которые можно вызывать. Объекты делают что-то с OpenOffice.org. Рассмотрим способы их получения.

Новые объектыВообще новые объекты – или объекты, нужные для начального доступа, – создаются менеджерами серви-сов OpenOffice.org. В примере FirstLoadComponent (он будет рассмотрен ниже) удаленный менеджер сер-висов создает удаленный объект Desktop, управляющий окнами приложений и загружающий документы в OpenOffice.org.

Object desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop",xRemoteContext);

Объекты документовОбъекты документов представлены файлами, открытыми в OpenOffice.org. Они создаются объектом Desktop, использующим для этого метод loadComponentFromURL().

Объекты, предоставляющие другие объектыОбъекты могут предоставлять другие объекты двумя основными способами.

Атрибуты, спроектированные как неотъемлемая часть другого объекта, могут быть получены get-методами. Например, метод getSheets() необходим для каждого документа Calc, getText() для каждого документа Writer и т.д. После загрузки документа эти методы могут использоваться для получения листов (Sheets) и текста (Text) соответствующих документов. Объекто-специфи-ческие get-методы – важная техника получения объектов.

Атрибуты, не являющиеся неотъемлемой частью архитектуры других объектов, доступны через набор стандартных методов. В OpenOffice.org API эти атрибуты называются свойствами, для об-ращения к ним используются общие методы, такие, как getPropertyValue(String propertyName), Иногда такие не-неотъемлемые атрибуты представляются как объекты и, таким образом, метод getPropertyValue() может быть еще одним источником объектов. Например, стили страниц (для электронных таблиц) имеют свойства RightPageHeaderContent и LeftPageHeaderContent, содержащие объекты колонтитулов страниц.

Наборы объектовОбъекты могут быть членами набора однообразных объектов. Чтобы обратиться к объекту-члену набора, следует знать, как производится доступ к элементу набора. OpenOffice.org API предостав-ляет четыре способы получения элемента из набора. Первые три – объекты с методами обращения к элементу по имени, индексу или перечислению. Четвертый путь – последовательность элемен-тов, не имеющая методов доступа, а используемая как массив.Выбор способа получения элемента определяется проектировщиком применительно к данной кон-кретной ситуации.

Работа с объектами

Объекты, интерфейсы и сервисы

ОбъектыВ UNO объект – программный артефакт, имеющий методы, которые можно вызывать и атрибуты, которые можно получать и устанавливать. Конкретный набор методов и атрибутов, предоставляемых объектом, определя-ется интерфейсами, реализуемыми объектом.

ИнтерфейсыИнтерфейс описывает набор атрибутов и методов, которые вместе определяют некоторый единичный аспект объекта. Например, интерфейс com.sun.star.resource.XResourceBundle:

4

Page 5: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

module com { module sun { module star { module resource {interface XResourceBundle: com::sun::star::container::XNameAccess {[attribute] XResourceBundle Parent;com::sun::star::lang::Locale getLocale();any getDirectElement([in] string key);};}; }; }; };определяет атрибут Parent и методы getLocale() и getDirectElement().Для обеспечения многократного использования подобных интерфейсных спецификаций, интерфейс может насле-довать один или более других интерфейсов (например, XResourceBundle наследует все атрибуты и методы ин-терфейса com.sun.star.container.XNameAccess). Множественное наследование интерфейсов – новая возможность OpenOffice.org 2.0.Строго говоря, интерфейсные атрибуты не необходимы в UNO. Каждый атрибут может быть представлен сочета-нием get-метода для получения значения атрибута и set-метода для установки значения (или одного из этих ме-тодов). Но с использованием атрибутов возможно лучше выразить нюансы особенностей объекта. Атрибуты мо-гут использоваться для не неотъемлемых особенностей объекта, а методы доступа резервируются для манипуля-ции с необходимыми аспектами объектов.Исторически типичный объект UNO поддерживал набор из нескольких независимых интерфейсов, соответствую-щих различным ракурсам объекта. С множественным наследованием ситуация изменилась, объект может поддер-живать один интерфейс, наследующий все остальные.

СервисыИзначально используемый в UNO термин "сервис" был не вполне ясен. Начиная с версии OpenOffice.org 2.0 ситу-ация прояснилась, но до сих пор остаются разночтения для термина "сервис". В дальнейшем будет использовать-ся термин в новом значении, соответствующем разъясненной концепции OpenOffice.org 2.0. Словосочетание "сер-вис старого стиля" будет применяться для обозначения объекта, соответствующего старой, неопределенной кон-цепции. Затрудняет ситуацию и то, что слово "сервис" применяется и помимо UNO в самых разных значениях.Хотя сейчас нет надобности в сервисах старого стиля, OpenOffice.org API продолжает поддерживать их для сохра-нения обратной совместимости.Сервис "нового стиля" выглядит так:module com { module sun { module star { module bridge {service UnoUrlResolver: XUnoUrlResolver;}; }; }; };Это определяет, что объекты, поддерживающие некоторый интерфейс (например, здесь com.sun.s-tar.bridge.XUnoUrlResolver) будут доступны под некоторым именем сервиса – здесь com.sun.s-tar.bridge.UnoUrlResolver, – в компонентном контексте менеджера сервисов. Иначе сервисы "нового сти-ля" еще называют сервисами, основанными на одиночном интерфейсе.Сервис старого стиля – иначе называемый накопительным сервисом, – выглядит так:module com { module sun { module star { module frame {service Desktop {service Frame;interface XDesktop;interface XComponentLoader;interface com::sun::star::document::XEventBroadcaster;};}; }; }; };В общем, если объект определен как поддерживающий какой-то сервис старого стиля, то следует ожидать, что этот объект будет поддерживать все интерфейсы, экспортируемые этим сервисом – и всеми унаследованными сер-висами.Например, метод com.sun.star.frame.XFrames.queryFrames() вернет последовательность объектов, все они будут поддерживать сервис старого стиля com.sun.star.frame.Frame, и, следовательно, все интер-фейсы, экспортируемые Frame.Сервис старого стиля может содержать одно (или более) свойств:

5

Page 6: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

module com { module sun { module star { module frame {service Frame {interface com::sun::star::frame::XFrame;interface com::sun::star::frame::XDispatchProvider;// ...[property] string Title;[property, optional] XDispatchRecorderSupplier RecorderSupplier;// ...};}; }; }; };Свойства (подробнее рассматриваемые ниже) подобны интерфейсным атрибутам, и описывают некоторые допол-нительные особенности объекта. Основное отличие от атрибутов – обращение к атрибутам производится непо-средственно, тогда как к свойствам сервисы старого стиля обращаются при помощи родовых интерфейсов, таких, как com.sun.star.beans.XPropertySet. Интерфейсные атрибуты чаще применяются для представления неотъемлемых особенностей объектов, тогда как свойства определяют дополнительные, более изменчивые аспек-ты.Некоторые сервисы старого стиля подразумевают доступность в компонентном контексте менеджера сервисов. Например, экземпляр сервиса com.sun.star.frame.Desktop может быть создан в компонентном контексте менеджера сервисов под собственным именем "com.sun.star.frame.Desktop". Но нельзя определить, предназначен ли какой-то сервис старого стиля для подобного использования, тогда как применение сервиса "но-вого стиля" делает намерение подобного использования более прозрачным.Другие сервисы старого стиля проектируются как родовые "супер-сервисы", предназначенные для наследования другими сервисами. Например, сервис com.sun.star.document.OfficeDocument служит родовой осно-вой для многих конкретных сервисов документа, таких, как com.sun.star.text.TextDocument, или com.sun.star.drawing.DrawingDocument. Для определения подобных базовых родовых сервисов пред-почтителен механизм множественного наследования.Другие сервисы старого стиля лишь перечисляют свойства, не экспортируя каких-либо интерфейсов. Подобные сервисы используются для описания набора связанных между собою свойств. Например, сервис com.sun.star.document.MediaDescriptor перечисляет все свойства, которые могут быть переданы ме-тоду интерфейса com.sun.star.frame.XComponentLoader.loadComponentFromURL.Свойства определяют такие аспекты объекта, которые не являются его неотъемлемой или структурной частью, и поэтому обрабатываются при помощи родовых методов getPropertyValue() и setPropertyValue() вме-сто специализированных методов, наподобие getPrinter(). Сервисами старого стиля предлагается специаль-ный синтаксис для перечисления свойств объекта. Объект, содержащий свойства, должен поддерживать интер-фейс com.sun.star.beans.XPropertySet, что дает возможность работать со всеми разновидностями свойств. Например – свойства, содержащие какие-то параметры форматирования символа или абзаца. При помо-щи свойств можно определить несколько параметров одним вызовом метода setPropertyValues(), что весь-ма повышает производительность при удаленной работе. К примеру, объекты-абзацы поддерживают метод setPropertyValues() благодаря реализуемому ими интерфейсу com.sun.star.beans.XMulti-PropertySet.

Использование сервисовПричины появления концепций интерфейсов и сервисов.

Интерфейсы и сервисы отделяют спецификацию от реализации.Спецификация интерфейса или сервиса абстрактна, то есть не определяет, как объект, обеспечивающий некую функциональность, делает это. Благодаря этому можно менять реализацию компонентов, не изме-няя другие части программы.

Сервисы позволяют создавать экземпляры по имени спецификации – не по имени класса.В языках Java или C++ для создания экземпляра класса используется оператор new. При таком подходе получаемый класс жестко предопределен, нельзя создать экземпляр другого класса без изменения кода. Применение сервисов решает эту проблему. Глобальный менеджер сервисов (центральную "фабрику" объектов OpenOffice.org) клиенты запрашивают создать объект для какой-то цели – без какого-то указания на внутреннюю реализацию запрашиваемого объекта. Это возможно потому, что создание сервиса запра-шивается согласно имени сервиса, и уже менеджер сервисов ("фабрика" объектов) будет решать, какую именно реализацию сервиса создавать. Для клиента нет разницы, какую реализацию он получил, если по-

6

Page 7: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

лученный объект поддерживает нужные интерфейсы. Множественное наследование облегчает управление малоразмерными интерфейсами.

Абстрактные интерфейсы проще повторно использовать, если они малоразмерны – то есть если они малы по размерам и описывают только какую-то один аспект объекта. В таком случае требуется много подоб-ных интерфейсов для описания большого объекта. Множественное наследование упрощает задачу мани-пулирования большим количеством малоразмерных интерфейсов.

Рассмотрим сервис старого стиля com.sun.star.text.TextDocument в нотации UML.Как видно, здесь схематически изображены сервисы com.sun.star.text.TextDocument и com.sun.-star.document.OfficeDocument.

Также видно, какие интерфейсы экспортирует каждый из этих сервисов. В OpenOffice.org API принято начинать имя интерфейса с буквы X.Каждый объект TextDocument должен поддерживать интерфейсы XTextDocument, XSearchable и XRefreshable. Так как TextDocument наследует OfficeDocument, он также поддерживает XPrintable, XStorable, XModel и XModifiable. Методы этих интерфейсов обеспечивают различные аспекты поведения объекта, как видно из названия: печать, сохранение, модификацию, управление моделью и др.Не следует забывать, что на схеме отображены лишь основные интерфейсы. Реальное устройство объектов на-много сложнее.

Использование интерфейсовОбращение к объектам UNO через его интерфейсы накладывает особенность при кодировании на Java или C++. В этих языках компилятор нуждается в правильном типе ссылки для того, чтобы можно было вызывать методы объекта, и обычно перед обращением к интерфейсу следует произвести приведение типа. При работе с объектами UNO дело обстоит иначе. Следует запросить UNO о соответствующей ссылке каждый раз, когда производится об-ращение к методам интерфейса, поддерживаемого объектом.Для этого существует метод UNO queryInterface(). Это выглядит довольно усложненно, но позволяет без-опасное (в том числе межпроцессное) приведение типов. В примере FirstloadComponent создается новый объект Desktop, и метод queryInterface() используется для получения ссылки на интерфейс XComponentLoader.Object desktop = xRemoteServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", xRemoteContext);XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);Здесь делается запрос методу менеджера сервисов (объект xRemoteServiceManager) createInstance-WithContext() для создания экземпляра com.sun.star.frame.Desktop. Этот метод возвращает Java-тип

7

«сервис »com.sun.star.document.OfficeDocument

«сервис »com.sun.star.document.TextDocument

com.sun.star.view.XPrintablecom.sun.star.frame.XStorable

com.sun.star.frame.XModel

com.sun.star.text.XTextDocumentcom.sun.star.util.XSearchable

com.sun.star.util.XRefreshable

com.sun.star.util.XModifiable

Page 8: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Object, на самом же деле этот объект типа com.sun. star. frame. Desktop.Вот спецификация этого метода:java.lang.Object createInstanceWithContext(String serviceName, XComponentContext context)Далее создается ссылка на интерфейс XComponentLoader объекта desktop. Хотя мы и знаем, что этот объект экспортирует требуемый интерфейс, компилятор не имеет информации об этом. Поэтому делается запрос мето-дом UNO queryInterface() чтобы получить ссылку требуемого типа. При этом для компилятора нет разни-цы, локальный или удаленный объект используется.В языке Java есть два вида спецификации этого метода:java.lang.Object UnoRuntime.queryInterface(java.lang.Class targetInterface, Object sourceObject)java.lang.Object UnoRuntime.queryInterface(com.sun.star.uno.Type targetInterface, Object sourceObject)Так как метод queryInterface() возвращает значение типа java.lang.Object, следует все же принуди-тельно привести тип. Однако (в отличие от метода createInstanceWithContext()) здесь можно безопасно приводить тип, и ссылка будет работать – даже с объектом другого процесса.Еще раз подробно разберем запрос интерфейса.XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);XComponentLoader – тип интерфейса, который мы хотим использовать, для чего создаем переменную по име-ни xComponentLoader. В ней будет храниться результат запроса к queryInterface().Аргументы здесь – требуемый интерфейс XComponentLoader.class и объект desktop, у которого этот ин-терфейс запрашивается.Перед присвоением значения происходит приведение типа результата к типу XComponentLoader.Если объект не поддерживает запрашиваемый интерфейс, метод вернет null.В Java подобный запрос делается каждый раз, когда нужна ссылка на объект, поддерживающий нужный интер-фейс. Можно сделать запрос интерфейса не только от объекта, но и от другой интерфейсной ссылки:// загружаем пустой документ, полученный при помощи интерфейса XComponent:XComponent xComponent = xComponentLoader.loadComponentFromURL("private:factory/scalc", "_blank", 0, loadProps);//а теперь запрашиваем ссылку на XSpreadsheetDocument:XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)UnoRuntime.queryInterface(XSpreadsheetDocument.class, xComponent);Если метод определен так, что сразу возвращает интерфейсный тип – нет нужды в запросе интерфейса, можно сразу использовать его методы.В приведенном выше отрывке метод loadComponentFromURL() определен так, что возвращает интерфейсный тип com.sun.star.lang.XComponent – и можно сразу вызывать методы addEventListener() и removeEventListener(), используя переменную xComponent – если нужно получать уведомление о закры-тии документа.Вот так это делается в C++://получаем экземпляр сервиса от менеждера сервисовReference< XInterface > rInstance =rServiceManager->createInstanceWithContext(OUString::createFromAscii("com.sun.star.frame.Desktop" ),rComponentContext );//запрос интерфейса XComponentLoaderReference< XComponentLoader > rComponentLoader( rInstance, UNO_QUERY );В OpenOffice.org Basic нет необходимости в запросе интерфейсов, Basic делает это самостоятельно.С увеличением числа множественно-унаследованных интерфейсов уменьшается число запросов интерфейсов в Java и C++.Предположим, есть интерфейсы:

8

Page 9: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

interface XBase1 {void fun1();};interface XBase2 {void fun2();};interface XBoth { // наследует оба интерфейса: XBase1 и XBase2interface XBase1;interface XBase2;};interface XFactory {XBoth getBoth();};Используя интерфейс, полученный при помощи XFactory.getBoth(), поддерживает методы fun1() и fun2() одновременно, нет надобности создавать ссылки на интерфейсы XBase1 и XBase2.

Использование свойствОбъект предлагает клиенту свойства при помощи интерфейсов, которые позволяют работать со свойствами. Основной интерфейс, используемый для этого – com.sun.star.beans.XPropertySet. Есть и другие интер-фейсы, такие, как com.sun.star.beans.XMultiPropertySet, работающий с несколькими свойствами пу-тем одиночного вызова метода. XPropertySet поддерживается всегда, если у сервиса есть свойства.Два метода XPropertySet осуществляют доступ к свойству. Определение методов в Java таково:void setPropertyValue(String propertyName, Object propertyValue)Object getPropertyValue(String propertyName)

Пример: работа с электронной таблицейВ примере FirstLoadComponent интерфейс XPropertySet используется для установки свойства CellStyle объекта ячейки Объект ячейки – экземпляр com.sun.star.sheet.SheetCell, и поэтому поддерживает сер-вис com.sun.star.table.CellProperties, который имеет свойство CellStyle.//запрос к интерфейсу XPropertySet объекта ячейкиXPropertySet xCellProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xCell);//установка значения свойства CellStylexCellProps.setPropertyValue("CellStyle", "Result");В примере FirstLoadComponent мы делаем запрос удаленному менеджеру сервисов для получения удаленного объекта Desktop и используем метод loadComponentFromURL() для создания нового документа-электрон-ной таблицы. В этом документе мы получаем контейнер листов таблицы и осуществляем доступ к новому листу по имени. В новом листе мы вводим значения в ячейки A1 и A2, суммируя их в ячейке A3. Ячейка-результат полу-чает стиль Result – подчеркнутый полужирный курсив. Наконец, этот лист делается активным – чтобы с ним мог работать пользователь.

Общие типыДо сих пор литеральные и общие типы для параметров методов и возвращаемых значений использовались нами так, будто бы OpenOffice.org API написан специально для Java. Однако следует помнить, что UNO задуман как не-зависимый язык и имеет собственный набор типов, которые следует как-то соотносить с типами используемого языка.

Основные типыОсновные типы UNO обычно выступают типами членов структур, параметров и возвращаемых значений методов. Вот сводная таблица основных типов OpenOffice.org UNO:

UNO Описание типа Java C++ Basicvoid пустой тип, используется как тип

для возвращаемого значения и как тип any

void void нет

9

Page 10: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

UNO Описание типа Java C++ Basicboolean Булевский тип, значения true (ис-

тина) и false (ложь)boolean sal_Bool Boolean

byte 8-битный целый тип со знаком byte sal_Int8 Integershort 16-битный целый тип со знаком short sal_Int16 Integer

unsigned short 16-битный целый тип без знака (устарел)

нет sal_uInt16 нет

long 32-битный целый тип со знаком int sal_Int32 Longunsigned long 32-битный целый тип без знака

(устарел)нет sal_uInt32 нет

hyper 64-битный целый тип со знаком long sal_Int64 нетunsigned hyper 64-битный целый тип без знака

(устарел)нет sal_uInt64 нет

float числовой тип с плавающей точкой (стандарт IEC 60559)

float float Single

double числовой тип с плавающей точкой двойной точности (стандарт IEC 60559)

double double Double

char 16-битный символьный тип Unicode char sal_Unicode нет

СтрокиUNO считает строки простыми типами, но в некоторых языках они обрабатываются особым образом.

UNO Описание Java C++ Basicstring строковый тип Unicode (вернее,

строки скалярных значений Unicode)

java.lang.String rtl::OUString String

Java обрабатывает строки как объекты java.lang.String.В C++ символьные строки должны быть преобразованы в UNO-строки Unicode с помощью функций преобразова-ния, обычно – функции createFromAscii() в объект класса rtl::OUString://C++static OUString createFromAscii(const sal_Char * value) throw();OpenOffice.org Basic работает со строками без дополнительных преобразований.

Перечисления и группы константВ OpenOffice.org API используются типы перечисления (enum) и группы констант. Перечисления исполь-зуются для создания списков допустимых в данном контексте именованных значений. Группы констант определя-ют допустимые значения для свойств, параметров, возвращаемых значений и членов структур.Например, перечисление com.sun.star.table.CellVertJustify описывает допустимые значения верти-кального выравнивания содержимого ячейки таблицы. За вертикальное выравнивание ячейки таблицы отвечает свойство com.sun.star.table.CellProperties.VertJustify. Допустимые значения этого свойства, согласно перечислению CellVertJustify – STANDARD, TOP, CENTER и BOTTOM.//выравнивание содержимого ячейки по верхней границе ячейки.////сервис com.sun.star.table.Cell включает в себя сервис com.sun.star.table.CellProperties//и имеет свойство VertJustify, управляющее вертикальным выравниванием.//для установки свойства используем интерфейс XPropertySetxCellProps.setPropertyValue("VertJustify", com.sun.star.table.CellVertJustify.TOP);OpenOffice.org Basic может использовать перечисления и группы констант напрямую:oCellProps.VertJustify = com.sun.star.table.CellVertJustify.TOP

10

Page 11: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

В C++ эти типы используются так:rCellProps->setPropertyValue(OUString::createFromAscii( "VertJustify" ),::com::sun::star::table::CellVertJustify.TOP);

СтруктурыСтруктуры в OpenOffice.org API используются для создания составных типов из уже существующих. Структуры OpenOffice.org соответствуют структурам C++ или Java-классам, содержащим только публичные члены.Структуры не инкапсулируют данные, они упрощаю передачу данных "целиком", вместо выстраивания ряда запросов get/set. Это дает преимущества, к примеру, при связи с удаленными компонентами.Доступ к членам структур производится оператором-точкой ".", например:aProperty.Name = "ReadOnly";В Java, C++ и Basic при создании экземпляра структуры используется слово new. Применяя автоматизацию OLE (ActiveX), для получения экземпляра структуры следует использовать com.sun.star.-reflection.CoreReflection. Для создания структур не следует применять менеджер сервисов. Например://В Java:com.sun.star.beans.PropertyValue aProperty = new com.sun.star.beans.PropertyValue();'В BasicDim aProperty As New com.sun.star.beans.PropertyValue

Тип anyВ OpenOffice.org API часто используется тип any, соответствующий типу Variant, широко известному благода-ря некоторым средам разработки...Тип any может содержать один (произвольный) тип UNO. Особенно часто тип any используется в родовых ин-терфейсах UNO.

Интерфейс возврат типа any получение типа anyXPropertySet any

getPropertyValue(string propertyName)

void setPropertyValue(any value)

XNameContainer any getByName(string name)

void replaceByName(string name, any element)void insertByName(string name, any element)

XIndexContainer any getByIndex(long index)

void replaceByIndex(long index, any element)void insertByIndex(long index, any element)

XEnumeration any nextElement()Тип any входит в структуру com.sun.star.beans.PropertyValue:

Эта структура имеет два члена: Name и Value, которые в паре описывают свойство по имени и значению. Для ра-боты с такими структурами следует назначать тип any – и быть в состоянии интерпретировать полученный тип any.В Java тип any соответствует java.lang.Object, однако есть и специальный класс com.sun.star.-uno.Any, используемый тогда, когда применение обычного Object было бы неоднозначно. Когда предполагает-ся передача значения типа any, всегда передается java.lang.Object или объект UNO.

11

+Name : string+Value : any

«struct»com.sun.star.beans.PropertyValue

Page 12: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Например, если используется метод setPropertyValue() для установки значения неинтерфейсного типа, сле-дует передавать java.lang.Object. Если значение имеет примитивный тип Java, используется соответствую-щий ему объектный тип:xCellProps.setPropertyValue("CharWeight", new Double(200.0));Или так:com.sun.star.beans.PropertyValue aProperty = new com.sun.star.beans.PropertyValue();aProperty.Name = "ReadOnly";aProperty.Value = Boolean.TRUE;При получении значения типа any следует использовать com.sun.star.uno.AnyConverter.Например, если нужно получить значение свойства, которое имеет примитивный тип Java, следует иметь в виду, что метод getPropertyValue() вернет java.lang.Object, содержащий примитивный тип, "обернутый" в тип any.com.sun.star.uno.AnyConverter служит преобразователем для таких объектов.Вот список его функций:static java.lang.Object toArray(java.lang.Object object)static boolean toBoolean(java.lang.Object object)static byte toByte(java.lang.Object object)static char toChar(java.lang.Object object)static double toDouble(java.lang.Object object)static float toFloat(java.lang.Object object)static int toInt(java.lang.Object object)static long toLong(java.lang.Object object)static java.lang.Object toObject(Class clazz, java.lang.Object object)static java.lang.Object toObject(Type type, java.lang.Object object)static short toShort(java.lang.Object object)static java.lang.String toString(java.lang.Object object)static Type toType(java.lang.Object object)static int toUnsignedInt(java.lang.Object object)static long toUnsignedLong(java.lang.Object object)static short toUnsignedShort(java.lang.Object object)При этом использовать его следует явно, например:import com.sun.star.uno.AnyConverter;long cellColor = AnyConverter.toLong(xCellProps.getPropertyValue("CharColor"));Для интерфейсных типов можно сразу использовать UnoRuntime.queryInterface без предварительного вы-зова AnyConverter.getObject():import com.sun.star.uno.AnyConverter;import com.sun.star.uno.UnoRuntime;Object ranges = xSpreadsheet.getPropertyValue("NamedRanges");XNamedRanges ranges1 = (XNamedRanges) UnoRuntime.queryInterface(XNamedRanges.class, AnyConverter.toObject(XNamedRanges.class, r));XNamedRanges ranges2 = (XNamedRanges) UnoRuntime.queryInterface(XNamedRanges.class, r);В OpenOffice.org Basic тип any соответствует типу Variant:'OpenOffice.org BasicDim cellColor As VariantcellColor = oCellProps.CharColorВ C++ используем специальный оператор://C++ имеет специальные операторы >>= и <<= для типа Any (угловые скобки всегда располагаются слева)sal_Int32 cellColor;Any any;any = rCellProps->getPropertyValue(OUString::createFromAscii( "CharColor" ));// извлекаем значение из anyany >>= cellColor;

ПоследовательностьПоследовательность – однородный набор значений одного и того же типа UNO, который может содержать различное число элементов. В других распространенных языках подобные сущности называются массивами (имеются в виду одномерные массивы-векторы). Хотя подобные наборы иногда реализуются как объекты с мето-

12

Page 13: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

дами доступа, принятыми в UNO (например, при помощи интерфейса com.sun.star.container.XEnumeration), они также выступают как последовательности, которые могут использоваться в целях повышения удаленной производительности. Последовательности изображаются с угловы-ми скобками.//последовательность строкsequence< string > aStringSequence;В Java последовательности обрабатываются как массивы (не следует использовать null для пустых последова-тельностей, надо создавать массив при помощи слова new и определять ему нулевую длину). Следует также по-мнить, что при создании массива объектов Java будет создан массив ссылок, а не экземпляров объектов. Поэтому после создания массива надо будет создавать каждый объект в отдельности и присваивать его члену массива (в цикле).Пустая последовательность структур PropertyValue чаще всего применяется с loadComponentFromURL.// создаем пустой массив структур PropertyValue для loadComponentFromURLPropertyValue[] emptyProps = new PropertyValue[0];Последовательность структур PropertyValue нужна для использования загрузки параметров с loadComponentFromURL(). Допустимые значения параметров для loadComponentFromURL() и для ин-терфейса com.sun.star.frame.XStorage можно найти в сервисе com.sun.star.document.-MediaDescriptor.//создаем массив с одной структурой PropertyValue для loadComponentFromURL, он содержит ссылкуPropertyValue[] loadProps = new PropertyValue[1];//создаем экземпляр структуры PropertyValue и инициализируем поляPropertyValue asTemplate = new PropertyValue();asTemplate.Name = "AsTemplate";asTemplate.Value = Boolean.TRUE;//присваиваем полученную структуру PropertyValue первому элементу массиваloadProps[0] = asTemplate;//загружаем файл Calc как шаблонXComponent xSpreadsheetComponent = xComponentLoader.loadComponentFromURL("file:///X:/share/samples/english/spreadsheets/OfficeSharingAssoc.sxc","_blank", 0, loadProps);В OpenOffice.org Basic пустой массив создается просто:Dim loadProps() 'пустой массивПоследовательность структур создается с использованием new:Dim loadProps(0) As New com.sun.star.beans.PropertyValue 'одна структура PropertyValueВ C++ есть шаблон класса для последовательностей. Пустая последовательность создается без указания числа элементов:Sequence< ::com::sun::star::beans::PropertyValue > loadProperties; //пустая последовательностьЕсли передается число элементов, создается массив элементов нужной длины:Sequence< ::com::sun::star::beans::PropertyValue > loadProps( 1 );//структура создается с конструктором по умолчаниюloadProps[0].Name = OUString::createFromAscii( "AsTemplate" );loadProps[0].Handle <<= true;Reference< XComponent > rComponent = rComponentLoader->loadComponentFromURL(OUString::createFromAscii("private:factory/swriter"),OUString::createFromAscii("_blank"),0,loadProps);

Доступ к элементу набораНаборы объектов должны быть обеспечены методами доступа к элементам. Есть три основных метода доступа: посредством интерфейсов com.sun.star.container.XNameContainer, com.sun.star.-container.XIndexContainer и com.sun.star.container.XEnumeration.Три интерфейса доступа к элементу – пример того, как малоразмерные интерфейсы OpenOffice.org API позволяют создать связный дизайн объекта.Все три интерфейса наследуют от XElementAccess, то есть включают методыtype getElementType()boolean hasElements()

13

Page 14: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

для получения основной информации о наборе элементов. Метод hasElements() определяет, содержит ли на-бор элементы вообще, и какого типа. В Java и C++ можно получить информацию о типе UNO при помощи com.sun.star.uno.Type.Интерфейсы com.sun.star.container.XIndexContainer и com.sun.star.container.XName-Container имеют сходный дизайн.

Интерфейсы XIndexAccess/XNameAccess предназначены для получения элемента по индексу и по имени со-ответственно, XIndexReplace/XNameReplace позволяют заменять существующие элементы без изменения числа элементов в наборе, и, наконец, XIndexContainer/XNameContainer предоставляют возможность вставлять и удалять элементы, изменяя их число в наборе.Некоторые именованные или индексированные наборы не полностью поддерживают эту иерархию наследования XIndex(Name)Container – потому что возможности подклассов не всегда применимы для элементов набора.Например, интерфейс XEnumerationAccess работает по-другому, нежели именованные и индексированные контейнеры-наследники XElementAcces. Интерфейс XEnumerationAccess не позволяет работу с единич-ными элементами наподобие XIndex(Name)Access, но создает перечисление объектов, имеющее методы для перехода на следующий элемент набора – если указатель находится не на последнем элементе (то есть для пере-бора элементов набора). Вот схема:

14

-type getElementType()-boolean hasElements()

«interface»com.sun.star.container.XElementAccess

-any getByIndex(long index)-long getCount()

«interface»com.sun.star.container.XIndexAccess

-void replaceByIndex(long index, any element)

«interface»com.sub.star.container.XIndexReplace

-void insertByIndex(long index, any element)-void removeByIndex(long index)

«interface»com.sun.star.container.XIndexContainer

-any getByName(string name)-sequence <string> getElementNames()-boolean hasByName(string name)

«interface»com.sun.star.container.XNameAccess

-void replaceByName(string name, any element)

«interface»com.sun.star.container.XNameReplace

-void insertByName(string name, any element)-void removeByName(string name)

«interface»com.sun.star.container.XNameContainer

Page 15: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Наборы объектов могут поддерживать доступ к элементам по имени, индексу или доступ по типу перечисления – в различных сочетаниях. В каждом конкретном случае следует обращаться к справке API.Например, метод getSheets() интерфейса com.sun.star.sheet.XSpreadsheetDocument определен так, чтобы возвращать интерфейс com.sun.star.sheet.XSpreadsheets, унаследованный от XNameContainer. В справке API можно узнать также, что реализующий эти интерфейсы объект также поддер-живает сервис com.sun.star.sheet.Spreadsheets, определяющий дополнительные интерфейсы доступа к элементам, помимо XSpreadsheets.Ниже приведены примеры работы с XNameAccess, XIndexAccess и XEnumerationAccess.

Доступ по имениОсновной интерфейс, предоставляющий доступ к элементу по имени – com.sun.star.container.XNameAccess. Он имеет три метода:any getByName( [in] string name)sequence< string > getElementNames()boolean hasByName( [in] string name)В примере FirstLoadComponent метод getSheets() возвращает интерфейс com.sun.star.sheet.-XSpreadsheets, унаследованный от XNameAccess. Поэтому возможно использовать метод getByName() для получения объекта листа от контейнера XSpreadsheets.XSpreadsheets xSpreadsheets = xSpreadsheetDocument.getSheets();Object sheet = xSpreadsheets.getByName("Новый лист");XSpreadsheet xSpreadsheet = (XSpreadsheet)UnoRuntime.queryInterface(XSpreadsheet.class, sheet);// используется интерфейс XSpreadsheet для получения ячейки A1 в позиции 0,0 и ввода значения 42XCell xCell = xSpreadsheet.getCellByPosition(0, 0);Так как getByName() возвращает тип any, следует использовать AnyConverter.toObject() и(или) UnoRuntime.queryInterface() для возможности обращения к методам объекта листа.

Доступ по индексуИнтерфейс, осуществляющий доступ к элементу набора по индексу – com.sun.star.-container.XIndexAccess. Он имеет два метода:any getByIndex( [in] long index)long getCount()Пример FirstLoadComponent демонстрирует применение этого интерфейса. Из справки API можно узнать, что

15

-type getElementType()-boolean hasElements()

«interface»com.sun.star.container.XElementAccess

-com.sun.star.container.XEnumetation createEnumeration()

«interface»com.sun.star.container.XEnumerationAccess

-boolean hasMoreElements()-any nextElement()

«interface»com.sun.star.container.XEnumeration

createEnumeration()

Page 16: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

сервис, возвращаемый методом getSheets() – com.sun.star.sheet.Spreadsheet, – поддерживает не только интерфейс com.sun.star.sheet.XSpreadsheets, но и XIndexAccess. Поэтому становится воз-можным обращение к листам не только по имени, но и по индексу:XIndexAccess xSheetIndexAccess = (XIndexAccess)UnoRuntime.queryInterface(XIndexAccess.class, xSpreadsheets);Object sheet = XSheetIndexAccess.getByIndex(0);

Доступ к перечислениюИнтерфейс com.sun.star.container.XEnumerationAccess создает перечисления, позволяющие пере-бор набора объектов. У него один метод:com.sun.star.container.XEnumeration createEnumeration()Интерфейс com.sun.star.container.XEnumerationAccess поддерживает интерфейс com.sun.-star.container.XEnumeration. С его помощью можно осуществлять перебор перечисления.XEnumeration имеет методы:boolean hasMoreElements()any nextElement()используемые для построения циклов типа:while (xCells.hasMoreElements()) {Object cell = xCells.nextElement();//что-то делаем с объектом cell}Например, так можно определить, какие ячейки таблицы содержат формулы. Результирующий набор объектов cell рассматривается как XEnumerationAccess.Интерфейс, запрашивающий ячейки с формулами – com.sun.star.sheet.XCellRangesQuery, имеющий, в частности, методXSheetCellRanges queryContentCells(short cellFlags)определяющий тип содержимого ячейки в соответствии с группой констант com.sun.star.sheet.CellFlags. Один из этих флагов – FORMULA.Метод queryContentCells() возвращает объект, поддерживающий интерфейс com.sun.star.sheet.XSheetCellRanges, имеющий три метода:XEnumerationAccess getCells()String getRangeAddressesAsString()sequence< com.sun.star.table.CellRangeAddress > getRangeAddresses()Метод getCells() может использоваться для перечисления всех ячеек с формулами и содержащиеся в них фор-мулы.XCellRangesQuery xCellQuery = (XCellRangesQuery)UnoRuntime.queryInterface(XCellRangesQuery.class, sheet);XSheetCellRanges xFormulaCells = xCellQuery.queryContentCells((short)com.sun.star.sheet.CellFlags.FORMULA);XEnumerationAccess xFormulas = xFormulaCells.getCells();XEnumeration xFormulaEnum = xFormulas.createEnumeration();while (xFormulaEnum.hasMoreElements()) {Object formulaCell = xFormulaEnum.nextElement();// do something with formulaCellxCell = (XCell)UnoRuntime.queryInterface(XCell.class, formulaCell);XCellAddressable xCellAddress = (XCellAddressable)UnoRuntime.queryInterface(XCellAddressable.class, xCell);

System.out.println("Ячейке в строке " + xCellAddress.getCellAddress().Column + ", ряду " + xCellAddress.getCellAddress().Row +" содержит формулу " + xCell.getFormula());

}

Как определить тип полученного объекта?Общая проблема – определить, какие возможности имеет объект после его получения от метода.Методы могут быть определены так, чтобы вернуть один тип интерфейса. Но объект, получаемый от метода (как его возвращаемое значение) зачастую поддерживает гораздо больше интерфейсов, нежели возвращает метод (осо-бенно если дизайн этих интерфейсов предшествовал возможностям множественно-унаследованных интерфейсов

16

Page 17: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

UNO). Кроме того, интерфейс ничего не сообщает о свойствах объекта.В OpenOffice.org Basic можно ознакомиться со свойствами объекта, используя следующие свойства Basic:Sub mainoDocument = ThisComponentMsgBox(oDocument.Dbg_Methods)MsgBox(oDocument.Dbg_Properties)MsgBox(oDocument.Dbg_SupportedInterfaces)End Sub

Пример: работа с текстом, таблицей и фигуройДалее рассмотрим пример общих приемов работы с OpenOffice.org API. Три основные области приложения OpenOffice.org – текст, таблицы и рисунки.

Общие механизмы работыНачнем с общих интерфейсов и свойств, позволяющими манипулировать существующими текстами, таблицами и рисунками. Далее будут рассмотрены другие приемы, предназначенные для создания таких документов.Для работы с существующими текстами, таблицами и рисунками применяются следующие основные интерфей-сы.Для текстовых документов интерфейс com.sun.star.text.XText содержит методы, позволяющие изменять "основной" текст документа и другое текстовое содержимое (таблицы, текстовые поля, графические объекты и т.п., но подобное допустимо не всегда).

Интерфейс com.sun.star.text.XText может устанавливать и возвращать текст как единичную строку и определять начало и конец текста. Также этот интерфейс может вставлять строку в произвольную позицию в тек-сте и создавать текстовые курсоры для выбора и форматирования текста. Кроме того, этот интерфейс может обра-батывать текстовый контент методами insertTextContent и removeTextContent, хотя это и не всегда воз-можно.Форматирование текста обеспечивается свойствами, имеющимися в сервисах com.sun.star.style.ParagraphProperties и com.sun.star.style.CharacterProperties.В последующем примере метод manipulateText() добавляет текст, используя текстовый курсор для выделения и

17

-void setString(string text)-string getString()-com.sun.star.text.XTextRange getStart()-com.sun.star.text.XTextRange getEnd()-com.sun.star.text.XText getText()

«interface»com.sun.star.text.XTextRange

-com.sun.star.text.XTextCursor createTextCursor()-com.sun.star.text.XTextCursor createTextCursorByRange(com.sun.star.text.XTextRange textRange)-void insertString(com.sun.star.text.XTextRange textRange, string text, boolean absorb)-void insertControlCharacter(com.sun.star.text.XTextRange textRange, short controlCharacter, boolean absorb)

«interface»com.sun.star.text.XSimpleText

-void insertTextContent(com.sun.star.text.XTextRange textRange, com.sun.star.text.XTextContent content, boolean absorb)-void removeTextContent(com.sun.star.text.XTextContent content)

«interface»com.sun.star.text.XText

Page 18: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

форматирования некоторых слов и применяя CharacterProperties. Метод manipulateText() содержит лишь основные методы XText, применимые для работы с любыми текстовыми объектами. Например, не применяется метод insertTextContent() – потому, что нет текстового контента, исключая обычный текст, который можно вставить во все текстовые объекты.Изучите функцию manipulateText() в коде примера HelloTextTableShape.В таблицах и ячейках таблиц интерфейс com.sun.star.table.XCellRange позволяет получать отдельные ячейки и поддиапазоны ячеек. С содержимым ячейки можно работать при помощи интерфейса com.sun.star.table.XCell.

Форматирование таблиц отличаются для текстовых таблиц Writer и таблиц Calc. Текстовые таблицы применяют свойства, описанные в com.sun.star.text.TextTable, а таблицы Calc – com.sun.star.table.CellProperties. Также есть объекты-табличные курсоры, позволяющие выбирать и форматировать регионы ячеек и содержащийся в них текст. Но com.sun.star.text.TextTableCursor ра-ботает по-другому, чем com.sun.star.sheet.SheetCellCursor.Изучите функцию manipulateTable() в тексте примера HelloTextTableShape.Для фигур Draw используется интерфейс com.sun.star.drawing.XShape, позволяющий определить пози-цию и размер фигуры.

Все остальное определяется при помощи основанного на свойствах форматирования. Есть много свойств для форматирования фигур. OpenOffice.org имеет одиннадцать фигур, на которых основаны средства для рисования. Шесть из них имеют собственные свойства, отражающие их характеристики: com.sun.star.drawing.EllipseShape круги и эллипсыcom.sun.star.drawing.RectangleShape прямоугольные поляcom.sun.star.drawing.TextShape текстовые поляcom.sun.star.drawing.CaptionShape заголовкиcom.sun.star.drawing.MeasureShape средства измеренияcom.sun.star.drawing.ConnectorShape соединительные линии, "приклеивающиеся" к

18

-com.sun.star.table.XCell getCellByPosition(long nColumn, long nRow)-com.sun.star.table.XCellRange getCellRangeByPosition(long nLeft, long nTop, long nRight, long nBottom)-com.sun.star.table.XCellRange getCellRangeByName(string aRange)

«interface»com.sun.star.table.XCellRange

-string getFormula()-void setFormila(string aFormula)-double getValue()-void setValue(double nValue)-com.sun.star.table.CellContentType getType()-long getError()

«interface»com.sun.star.table.XCell

-string getShapeType()-com.sun.star.awt.Point getPosition()-void setPosition(com.sun.star.awt.Point aPosition)-com.sun.star.awt.Size getSize() invoke-void setSize(com.sun.star.awt.Size aSize)

«interface»com.sun.star.drawing.XShape

Page 19: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

другим фигурамПять фигур не имеют индивидуальных свойств, а используют свойства, определенные в сервисе com.sun.star.drawing.PolyPolygonBezierDescriptor:com.sun.star.drawing.LineShape линии и стрелкиcom.sun.star.drawing.PolyLineShape незамкнутые фигуры, образованные

прямыми линиямиcom.sun.star.drawing.PolyPolygonShape фигуры, образованные одним или

несколькими многоугольникамиcom.sun.star.drawing.ClosedBezierShape замкнутые фигуры, образованные ли-

ниями Безьеcom.sun.star.drawing.PolyPolygonBezierShape комбинации многоугольников и фигур

БезьеВсе эти одиннадцать фигур используют свойства от следующих сервисов:com.sun.star.drawing.Shape описывает основные свойства фигур,

такие, как слой, к которому принадле-жит фигура, защищенность от пере-мещения и изменения размеров, на-звание стиля, 3D-трансформация и имя фигуры

com.sun.star.drawing.LineProperties определяет внешний вид линийcom.sun.star.drawing.Text не имеет собственных свойств, но

включает:com.sun.star.drawing.TextProperties описывает нумерацию, увеличение

фигуры, выравнивание текста в ячей-ке, анимацию текста и направление письма

com.sun.star.style.ParagraphProperties обеспечивает форматирование абзацаcom.sun.star.style.CharacterProperties описывает форматирование символов

com.sun.star.drawing.ShadowProperties определяет тень, отбрасываемую фи-гурой

com.sun.star.drawing.RotationDesriptor устанавливает повороты и отсечения фигуры

com.sun.star.drawing.FillProperties описывает заливку замкнутых фигурcom.sun.star.presentation.Shape добавляет эффекты к фигурам в пре-

зентацияхОбратитесь к функции manipulateShape() в коде примера HelloTextTableShape.

Создание текста, электронной таблицы и рисование фигурТри метода manipulateXXX в примере HelloTextTableShape получают текст, таблицу и фигуру как аргументы и изменяют их.Далее следует рассмотреть, как создавать подобные объекты в документах различного типа.Надо помнить, что все документы имеют собственные "фабрики" для создания вставляемых объектов. Кроме того, методики могут отличаться для разных типов документов.Сначала следует создать новый документ, что делается довольно просто – см. функцию newDocComponent() в тек-сте примера.

19

Page 20: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

Текст, таблицы и фигуры в WriterМетод useWriter создает документ Writer, изменяет его текст, затем использует менеджер сервисов документа для создания текстовой таблицы и фигуры, вставки их в документ и изменения в дальнейшем. Следует изучить функ-цию useWriter() в примере HelloTextTableShape.

Текст, таблицы и фигуры в CalcМетод useCalc нашего примера создает документ Calc, применяет его "фабрику документов" для создания фигуры и изменения текста в ячейках, таблицы и фигуры. Изучите функцию useCalc() подробнее.

Рисование и текст в DrawНаконец, метод useDraw создает документ Draw, добавляя к нему фигуру и изменяя ее. Подробнее – смотрите текст функции useDraw().

20

Page 21: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

ПриложениеFirstUnoContact.java

import com.sun.star.comp.helper.Bootstrap;import com.sun.star.lang.XMultiComponentFactory;import com.sun.star.uno.XComponentContext;

public class FirstUnoContact {

public static void main (String[] args){//всего одна функция//по завершении которой прекращаем работуtry{

//создаем компонентный контекст XComponentContext xContext = Bootstrap.bootstrap();//выводим сообщение

System.out.println("Соединяемся с работающим экземпляром OOffice... ");//создаем основную фабрику объектовXMultiComponentFactory xMCF = xContext.getServiceManager();//проверяем, получилось ли создать?String avaiable = (xMCF != null ? "доступен":"не доступен");//и сообщаем о результатеSystem.out.println("удаленный ServiceManager " + avaiable);

}catch(Exception e){

//при исключении – выводим дамп стекаe.printStackTrace();

}finally{

//выходим без ошибкиSystem.exit(0);

}}

}

21

Page 22: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

build_FirstUnoContact.xml

<?xml version="1.0" encoding="UTF-8"?><project basedir="." default="all" name="FirstUnoContact">

<property name="OFFICE_HOME" value="c:\Program Files\OpenOffice.org 2.1"/> <property name="OO_SDK_HOME" value="c:\Program Files\OpenOffice.org_2.1_SDK"/> <target name="init"> <property name="OUTDIR" value="c:\VB\projects\java\eclipse\UNO_sample_01"/> </target>

<path id="office.class.path"> <filelist dir="${OFFICE_HOME}/program/classes" files="jurt.jar,unoil.jar,ridl.jar,juh.jar"/> </path> <fileset id="bootstrap.glue.code" dir="${OO_SDK_HOME}/classes"> <patternset> <include name="com/sun/star/lib/loader/*.class"/> <include name="win/unowinreg.dll"/> </patternset> </fileset> <target name="compile" depends="init"> <mkdir dir="${OUTDIR}"/> <javac debug="true" deprecation="true" destdir="${OUTDIR}" srcdir="."> <classpath refid="office.class.path"/> </javac> </target>

<target name="jar" depends="init,compile"> <jar basedir="${OUTDIR}" compress="true" jarfile="${OUTDIR}/FirstUnoContact.jar"> <exclude name="**/*.java"/> <exclude name="*.jar"/> <fileset refid="bootstrap.glue.code"/> <manifest> <attribute name="Main-Class" value="com.sun.star.lib.loader.Loader"/> <section name="com/sun/star/lib/loader/Loader.class"> <attribute name="Application-Class" value="FirstUnoContact"/> </section> </manifest> </jar> </target>

<target name="all" description="Build everything." depends="init,compile,jar"> <echo message="Application built. FirstUnoContact!"/> </target>

<target name="run" description="Try running it." depends="init,all"> <java jar="${OUTDIR}/FirstUnoContact.jar" failonerror="true" fork="true"> </java> </target>

<target name="clean" description="Clean all build products." depends="init"> <delete> <fileset dir="${OUTDIR}"> <include name="**/*.class"/> </fileset> </delete> <delete file="${OUTDIR}/FirstUnoContact.jar"/> </target>

</project>

22

Page 23: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

FirstLoadComponent.javaimport com.sun.star.uno.UnoRuntime;import com.sun.star.uno.XComponentContext;import com.sun.star.lang.DisposedException;import com.sun.star.lang.XMultiComponentFactory;import com.sun.star.lang.XComponent;import com.sun.star.beans.XPropertySet;import com.sun.star.beans.PropertyValue;import com.sun.star.sheet.CellFlags;import com.sun.star.sheet.XSpreadsheetDocument;import com.sun.star.sheet.XSpreadsheets;import com.sun.star.sheet.XSpreadsheet;import com.sun.star.sheet.XSpreadsheetView;import com.sun.star.sheet.XCellRangesQuery;import com.sun.star.sheet.XSheetCellRanges;import com.sun.star.sheet.XCellAddressable;import com.sun.star.table.CellVertJustify;import com.sun.star.table.XCell;import com.sun.star.frame.XModel;import com.sun.star.frame.XController;import com.sun.star.frame.XComponentLoader;import com.sun.star.container.XEnumeration;import com.sun.star.container.XEnumerationAccess;

public class FirstLoadComponent {

public FirstLoadComponent(){//пустой конструктор}

//глобальные переменные — компонентный контекстprivate XComponentContext xRemouteContext = null;//и менеджер сервисовprivate XMultiComponentFactory xRemouteServiceManager = null;

public static void main(String[] args){// сначала создаем экземпляр этого приложенияFirstLoadComponent firstLoadComponent1 = new FirstLoadComponent();try{//пытаемся установить соединение

firstLoadComponent1.useConnection();}catch(Exception e){//при неудаче – вывод стека вызовов

System.out.println(e.getMessage());e.printStackTrace();

}finally{//в любом случае – выход без ошибки

System.exit(0);}

}

23

Page 24: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

private void useConnection() throws Exception {//основная процедура приложения, условно разделенноая на две части////первая часть – соединение с офисом,//вторая же выполняет всю работу////почему авторы примера объединили //две совершенно разные процедуры в одну – непонятно,//но оставим как есть////первая часть//вот так пытаемся соединиться с экземпляром офисаtry{

//создаем экземпляр удаленного компонентного контекстаxRemouteContext=com.sun.star.comp.helper.Bootstrap.bootstrap();System.out.println("соединяемся с работающим Office...");

//и получаем от него экземпляр менеджера сервисовxRemouteServiceManager=xRemouteContext.getServiceManager();

}catch(Exception e){

//при неудаче – как обычноe.printStackTrace();System.exit(1);

}

//вторая частьtry{

//создаем экземпляр объекта рабочего стола --//основного объекта офисного приложенияObject

desktop=xRemouteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemouteContext);

//приведением типов получаем объект загрузчика компонентовXComponentLoader

xComponentLoader=(XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);

//объект-набор свойств (одно свойство в наборе)PropertyValue[] loadProps=new PropertyValue[0];//компонент-листXComponent

xSpreadsheetComponent=xComponentLoader.loadComponentFromURL("private:factory/scalc", "_blank", 0, loadProps);

//а это – документ-лист (образуется запросом интерфейса и приведением типа)XSpreadsheetDocument

xSpreadsheetDocument=(XSpreadsheetDocument)UnoRuntime.queryInterface(XSpreadsheetDocument.class, xSpreadsheetComponent);

//мз документа получаем набор листов – пока пустойXSpreadsheets xSpreadsheets=xSpreadsheetDocument.getSheets();//вставка нового листа с заданным именемxSpreadsheets.insertNewByName("Новый лист", (short)0);//получаем тип элемента набора листов

//(т.к. UNO заранее об этом ничего не знает)com.sun.star.uno.Type elemType=xSpreadsheets.getElementType();

//debug-сообщение – вывод имени типаSystem.out.println(elemType.getTypeName());

//наконец получаем объект-лист типа ObjectObject sheet=xSpreadsheets.getByName("Новый лист");//и приводим его к нужному типу

24

Page 25: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

XSpreadsheet xSpreadsheet=(XSpreadsheet)UnoRuntime.queryInterface(XSpreadsheet.class, sheet);

//получаем ячейку листа с координатами 0,0XCell xCell=xSpreadsheet.getCellByPosition(0,0);//пишем в нее значение 21xCell.setValue(21);

//то же для следующей ячейкиxCell=xSpreadsheet.getCellByPosition(0,1);xCell.setValue(21);//а в следующую – пишем формулуxCell=xSpreadsheet.getCellByPosition(0,2);xCell.setFormula("=sum(A1:A2");

//набор свойств ячейки (обратите внимание, что работаем//с последней активной ячейкой – той, в которой формулаXPropertySet

xCellProps=(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xCell);//устанавливаем свойство стиля ячейкиxCellProps.setPropertyValue("CellStyle", "Result");

//объект-модель листа//получаем приведением типа запрошенного от компонента-листа интерфейсаXModel xSpreadsheetModel=(XModel)UnoRuntime.queryInterface(XModel.class,

xSpreadsheetComponent);//объект-контроллер листа//получаем get-методом от объекта-моделиXController

xSpreadsheetController=xSpreadsheetModel.getCurrentController();//объект-вид листа//приводим тип интерфейса объекта-контроллераXSpreadsheetView

xSpreadsheetView=(XSpreadsheetView)UnoRuntime.queryInterface(XSpreadsheetView.class, xSpreadsheetController);

//созданный новый листа делаем активным при помощи//объекта-видаxSpreadsheetView.setActiveSheet(xSpreadsheet);

//установка свойства вертикального выравнивания ячейки//(той, где формула)xCellProps.setPropertyValue("VertJustify", CellVertJustify.TOP);

//пересоздаем набор свойств (два свойства в наборе)loadProps=new PropertyValue[1];//объект-свойствоPropertyValue asTemplate=new PropertyValue();//инициализируем егоasTemplate.Name="AsTemplate";asTemplate.Value=new Boolean(true);//и заносим в набор свойствloadProps[0]=asTemplate;

//получаем от листа объект-диапазон ячеекXCellRangesQuery

xCellQuery=(XCellRangesQuery)UnoRuntime.queryInterface(XCellRangesQuery.class, sheet);//и получаем набор ячеек с формуламиXSheetCellRanges

xFormulaCells=xCellQuery.queryContentCells((short)CellFlags.FORMULA);//ячейки этого набора приводим к виду набора с типом доступа – перечислениеXEnumerationAccess xFormulas=xFormulaCells.getCells();//создаем из полученного набора перечисление

25

Page 26: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

XEnumeration xFormulaEnum=xFormulas.createEnumeration();

//в цикле, пока не закончатся элементы в перечисленииwhile(xFormulaEnum.hasMoreElements()){

//получаем очередной элемент в виде ObjectObject formulaCell=xFormulaEnum.nextElement();//приводим его к типу ячейкиxCell=(XCell)UnoRuntime.queryInterface(XCell.class, formulaCell);//и к типу адресуемой ячейки – чтобы получить ее координатыXCellAddressable

xCellAddress=(XCellAddressable)UnoRuntime.queryInterface(XCellAddressable.class, xCell);//выводим координаты ячейки с формулой и ее содержимоеSystem.out.println("Ячейке в строке "+

xCellAddress.getCellAddress().Column+", ряду "+xCellAddress.getCellAddress().Row+" содержит формулу "+xCell.getFormula());

}}catch(DisposedException e){

//при неудчае – обнуляем удаленный компонентный контекстxRemouteContext=null;//и передаем исключение «родителям»throw e;

}}

}

26

Page 27: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

HelloTextTableShape.java

//import sun.security.action.GetBooleanAction;

import com.sun.star.lang.XComponent;//import com.sun.star.uno.Exception;import com.sun.star.uno.XComponentContext;import com.sun.star.uno.UnoRuntime;//import com.sun.star.uno.AnyConverter;//import com.sun.star.bridge.XUnoUrlResolver;import com.sun.star.frame.XComponentLoader;import com.sun.star.lang.DisposedException;import com.sun.star.lang.XMultiComponentFactory;import com.sun.star.lang.XMultiServiceFactory;import com.sun.star.lang.XServiceInfo;import com.sun.star.beans.XPropertySet;//import com.sun.star.beans.XPropertySetInfo;import com.sun.star.beans.PropertyValue;//import com.sun.star.beans.UnknownPropertyException;//import com.sun.star.beans.PropertyVetoException;import com.sun.star.text.XTextDocument;import com.sun.star.text.XText;import com.sun.star.text.XTextCursor;//import com.sun.star.text.XWordCursor;import com.sun.star.text.XTextContent;//import com.sun.star.text.XTextTable;//import com.sun.star.text.XTextTableCursor;//import com.sun.star.table.XTableRows;import com.sun.star.table.XCellRange;import com.sun.star.table.XCell;//import com.sun.star.table.XCellCursor;import com.sun.star.table.TableBorder;import com.sun.star.table.BorderLine;import com.sun.star.drawing.XShape;import com.sun.star.awt.FontSlant;import com.sun.star.awt.FontWeight;import com.sun.star.awt.Size;import com.sun.star.awt.Point;import com.sun.star.sheet.XSpreadsheetDocument;//import com.sun.star.sheet.XSpreadsheet;//import com.sun.star.sheet.XSheetCellCursor;import com.sun.star.comp.helper.Bootstrap;import com.sun.star.container.XIndexAccess;import com.sun.star.container.XNameAccess;import com.sun.star.drawing.XDrawPagesSupplier;import com.sun.star.drawing.XDrawPageSupplier;import com.sun.star.drawing.XDrawPage;import com.sun.star.text.XTextTablesSupplier;import com.sun.star.container.XNamed;import com.sun.star.text.XBookmarksSupplier;import com.sun.star.text.XTextRange;

27

Page 28: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

public class HelloTextTableShape {//основные объекты://удаленный контекстprivate XComponentContext xRemoteContext = null;//удаленный менеджер сервисовprivate XMultiComponentFactory xRemoteServiceManager = null;

public HelloTextTableShape(){

//конструктор пуст, ничего особенного не делаем}

public static void main (String [] srgs){

//объект текущей программы-примераHelloTextTableShape helloTextTableShape1 = new HelloTextTableShape();

try{

//пытаемся выполнить основную функциюhelloTextTableShape1.useDocuments();

}catch(java.lang.Exception e){

//при ошибке – сообщение об ошибкеSystem.err.println(e.getMessage());//и стек вызовов для отслеживания ошибкиe.printStackTrace();

}finally{

//в любом случае – выход без ошибкиSystem.exit(0);

}}

//////////////////////////////////////////////////////////////////////////////////////////protected void useDocuments() throws java.lang.Exception{

//основная функция программы-примера//последовательная работа с документами ////WriteruseWriter();//CalcuseCalc();//DrawuseDraw();

}//////////////////////////////////////////////////////////////////////////////////////////

28

Page 29: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

protected void useWriter() throws java.lang.Exception{

//работа с документом Writertry{

//создание объекта-экземпляра WriterXComponent xWriterComponent = newDocComponent("swriter");//объект-текстовый документ объекта Writer путем приведения типовXTextDocument xTextDocument =

(XTextDocument)UnoRuntime.queryInterface(XTextDocument.class, xWriterComponent);//доступ к содержащемуся в нем текстуXText xText = xTextDocument.getText();

//функция манипуляции текстомmanipulateText(xText);

//объект-фабрика объектов на основе объекта WriterXMultiServiceFactory

xWriterFactory=(XMultiServiceFactory)UnoRuntime.queryInterface(XMultiServiceFactory.class, xWriterComponent);

//с помощью объекта-фабрики создаем объект-текстовую таблицуObject table =

xWriterFactory.createInstance("com.sun.star.text.TextTable");//и в ней – объект-текстовый контекст таблицыXTextContent xTextContentTable =

(XTextContent)UnoRuntime.queryInterface(XTextContent.class, table);//вставляем его в конец текстаxText.insertTextContent(xText.getEnd(), xTextContentTable, false);

//в таблице – объект-регион ячеекXCellRange xCellRange =

(XCellRange)UnoRuntime.queryInterface(XCellRange.class, table);//в нем – ячейка с указанной позициейXCell xCell = xCellRange.getCellByPosition(0, 1);//в ней – объект-текст как содержимое ячейкиXText xCellText = (XText)UnoRuntime.queryInterface(XText.class, xCell);

//манипуляции с этим текстомmanipulateText(xCellText);//манипуляции с таблицейmanipulateTable(xCellRange);

//создаем объект-фигуру Writer при помощи фабрики объектовObject writerShape =

xWriterFactory.createInstance("com.sun.star.drawing.RectangleShape");//приводим этот объект к нужному интерфейсному типуXShape xWriterShape = (XShape)UnoRuntime.queryInterface(XShape.class,

writerShape);//установка размера фигурыxWriterShape.setSize(new Size(10000, 10000));//объект-текстовый контекст фигурыXTextContent xTextContentShape =

(XTextContent)UnoRuntime.queryInterface(XTextContent.class, writerShape);

//вставка его в конец текста документаxText.insertTextContent(xText.getEnd(), xTextContentShape, false);

//набор свойств фигурыXPropertySet xShapeProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, writerShape);

//установка свойства TextContourFrame в truexShapeProps.setPropertyValue("TextContourFrame", new Boolean(true));

//объект – текст фигуры

29

Page 30: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

XText xShapeText = (XText)UnoRuntime.queryInterface(XText.class, writerShape);

//манипуляции с текстомmanipulateText(xShapeText);//манипуляции с фигуройmanipulateShape(xWriterShape);

//создание объекта-закладки при помощи фабрики объектовObject bookmark =

xWriterFactory.createInstance("com.sun.star.text.Bookmark");//приведение к типу именованной закладкиXNamed xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class, bookmark);//установка имениxNamed.setName("МояУникальнаяЗакладка");

//текстовый контекст закладкиXTextContent xTextContent =

(XTextContent)UnoRuntime.queryInterface(XTextContent.class, bookmark);//вставляем в конец текста документаxText.insertTextContent(xText.getEnd(), xTextContent, false);

//создаем объект-поставщик закладокXBookmarksSupplier xBookmarksSupplier =

(XBookmarksSupplier)UnoRuntime.queryInterface(XBookmarksSupplier.class, xWriterComponent);//обеспечиваем именованный доступXNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();//получаем созданную ранее закладку от набора именованных закладокObject foundBookmark = xNamedBookmarks.getByName("МояУникальнаяЗакладка");//ее текстовый контекстXTextContent xFoundBookmark =

(XTextContent)UnoRuntime.queryInterface(XTextContent.class, foundBookmark);//в ней объект-якорьXTextRange xFound = xFoundBookmark.getAnchor();//и вставляем строкуxFound.setString("Раз, два, три, четыре, пять,"

+ "вышел зайчик погулять...");

//создаем объект-поставщик текстовых таблиц XTextTablesSupplier xTableSupplier =

(XTextTablesSupplier)UnoRuntime.queryInterface(XTextTablesSupplier.class, xWriterComponent);//именованный доступXNameAccess xNamedTables = xTableSupplier.getTextTables();

//и индексированный доступXIndexAccess xIndexedTables =

(XIndexAccess)UnoRuntime.queryInterface(XIndexAccess.class, xNamedTables);

//обнуляем набор свойствXPropertySet xTableProps = null;

//в цикле для каждой таблицыfor(int i=0; i<xIndexedTables.getCount(); i++){

//получаем очередную таблицу из набораtable = xIndexedTables.getByIndex(i);

//для нее создаем объект-набор свойствxTableProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, table);//и устанавливаем цвет фона BackColorxTableProps.setPropertyValue("BackColor", new Integer(0xc8ffb9));

}

}catch(DisposedException e)

30

Page 31: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

{//при исключении – уничтожаем объект-удаленный контекстxRemoteContext = null;//передаем исключение на дальнейшую обработкуthrow e;

}}

protected void useCalc() throws java.lang.Exception{

//работа с Calctry{

//создаем экземпляр приложения CalcXComponent xCalcComponent = newDocComponent("scalc");//объект-документ_таблицаXSpreadsheetDocument xSpreadsheetDocument =

(XSpreadsheetDocument)UnoRuntime.queryInterface(XSpreadsheetDocument.class, xCalcComponent);

//из него – набор листовObject sheets = xSpreadsheetDocument.getSheets();//индексированный доступ к листамXIndexAccess xIndexedSheets =

(XIndexAccess)UnoRuntime.queryInterface(XIndexAccess.class, sheets);//первый в наборе листObject sheet = xIndexedSheets.getByIndex(0);

//набор ячеек таблицыXCellRange xSpreadsheetCells =

(XCellRange)UnoRuntime.queryInterface(XCellRange.class, sheet);//левая верхняя ячейкаXCell xCell = xSpreadsheetCells.getCellByPosition(0,1);//для нее – объект-набор свойствXPropertySet xCellProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xCell);//устанавливаем свойство IsTextWrappedxCellProps.setPropertyValue("IsTextWrapped", new Boolean(true));

//текст ячейкиXText xCellText = (XText)UnoRuntime.queryInterface(XText.class, xCell);

//манипуляция с текстомmanipulateText(xCellText);//манипуляция с таблицейmanipulateTable(xSpreadsheetCells);

//объект-фабрика объектов CalcXMultiServiceFactory xCalcFactory =

(XMultiServiceFactory)UnoRuntime.queryInterface(XMultiServiceFactory.class, xCalcComponent);

//объект-поставщик

31

Page 32: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

фигур CalcXDrawPageSupplier xDrawPageSupplier =

(XDrawPageSupplier)UnoRuntime.queryInterface(XDrawPageSupplier.class, sheet);//объект-"страница" для рисования фигурыXDrawPage xDrawPage = xDrawPageSupplier.getDrawPage();

//объект-фигураObject calcShape =

xCalcFactory.createInstance("com.sun.star.drawing.RectangleShape");//приводим ее к типу фигуры CalcXShape xCalcShape = (XShape)UnoRuntime.queryInterface(XShape.class,

calcShape);//устанавливаем размерxCalcShape.setSize(new Size(10000, 10000));//и позициюxCalcShape.setPosition(new Point(7000, 7000));

//добавляем фигуру на "страницу"xDrawPage.add(xCalcShape);

//объект-набор свойств фигуры CalcXPropertySet xShapeProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, calcShape);//установка свойства TextContourFrame для объекта-фигурыxShapeProps.setPropertyValue("TextContourFrame", new Boolean(true));

//объект-текст в этой фигуреXText xShapeText = (XText)UnoRuntime.queryInterface(XText.class,

calcShape);

//манипуляция текстомmanipulateText(xShapeText);//манипуляция фигуройmanipulateShape(xCalcShape);

}catch(DisposedException e){

//как вышеxRemoteContext = null;throw e;

}}

32

Page 33: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

protected void useDraw() throws java.lang.Exception{

try{

//создание объекта-экземпляра DrawXComponent xDrawComponent = newDocComponent("sdraw");//объект-поставщик "страниц" для рисованияXDrawPagesSupplier xDrawPagesSupplier =

(XDrawPagesSupplier)UnoRuntime.queryInterface(XDrawPagesSupplier.class, xDrawComponent);

//из него – объект-набор страницObject drawPages = xDrawPagesSupplier.getDrawPages();//обеспечиваем индексированный доступ к наборуXIndexAccess xIndexedDrawPages =

(XIndexAccess)UnoRuntime.queryInterface(XIndexAccess.class, drawPages);

//первая страницаObject drawPage = xIndexedDrawPages.getByIndex(0);//приводим к нужному типуXDrawPage xDrawPage = (XDrawPage)UnoRuntime.queryInterface(XDrawPage.class,

drawPage);

//объект-фабрика объектов DrawXMultiServiceFactory xDrawFactory =

(XMultiServiceFactory)UnoRuntime.queryInterface(XMultiServiceFactory.class, xDrawComponent);

//создаем объект-фигуру Draw (прямоугольник)Object drawShape =

xDrawFactory.createInstance("com.sun.star.drawing.RectangleShape");//приводим к нужному типуXShape xDrawShape = (XShape)UnoRuntime.queryInterface(XShape.class,

drawShape);//размерxDrawShape.setSize(new Size(10000, 10000));//позицияxDrawShape.setPosition(new Point(5000, 5000));//добавляем на страницуxDrawPage.add(xDrawShape);

//объект-текст фигурыXText xShapeText = (XText)UnoRuntime.queryInterface(XText.class,

drawShape);//набор свойствXPropertySet xShapeProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, drawShape);

//устанавливаем свойствоxShapeProps.setPropertyValue("TextContourFrame", new Boolean(true));

//манипуляция текстомmanipulateText(xShapeText);//манипуляция фигуройmanipulateShape(xDrawShape);

}catch(DisposedException e){

//как вышеxRemoteContext = null;throw e;

}}

///////////////////////////////////////////////////////////////////////////////////////////

33

Page 34: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

protected void manipulateText(XText xText) throws com.sun.star.uno.Exception{

//функция манипуляции текстом//получает объект, соответствующий тексту, содержащемуся в каком-то объекте

приложения OpenOffice.org////пишем строкуxText.setString("Тут охотник выбегает, "

+ "Прямо в зайчика стреляет!...");

//создаем объект-текстовый курсорXTextCursor xTextCursor = xText.createTextCursor();//набор свойств текстового курсораXPropertySet xCursorProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xTextCursor);

//специфические для объекта особенности-свойства устанавливаются напрямуюxTextCursor.gotoStart(false);xTextCursor.goRight((short)8, true);//а менее специфические – как обычноxCursorProps.setPropertyValue("CharPosture", FontSlant.ITALIC);xCursorProps.setPropertyValue("CharWeight", new Float(FontWeight.BOLD));xTextCursor.gotoEnd(false);xText.insertString(xTextCursor, "\n Пиф-паф, ой-ой-ой...", false);xText.insertString(xTextCursor, "\n \n Помирает зайчик мой!", false);//в результате первые 8 символов текста устанавливаются в "жирный курсив"//и добавляется дополнительный текст

}

protected void manipulateTable(XCellRange xCellRange) throws com.sun.star.uno.Exception{

//функция манипуляции таблицей//получает набор ячеек таблицы////String backColorPropertyName = "";XPropertySet xTableProps = null;

//получаем первую ячейку полученного в аргументе набораXCell xCell = xCellRange.getCellByPosition(0, 0);//приводим к текстовому типу XText xCellText = (XText)UnoRuntime.queryInterface(XText.class, xCell);//пишем строкуxCellText.setString("Заголовок");//ячейка рядом (справа) от предыдущейxCell = xCellRange.getCellByPosition(1, 0);//аналогично – приводим к текстовому типуxCellText = (XText)UnoRuntime.queryInterface(XText.class, xCell);//пишем строкуxCellText.setString("Еще один");//ячейка нижеxCell = xCellRange.getCellByPosition(1, 1);//пишем значение (число, поэтому к текстовому типу можно не приводить)xCell.setValue(1940);//выделяем регионXCellRange xSelectedCells = xCellRange.getCellRangeByName("A1:B1");//его набор свойствXPropertySet xCellProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xSelectedCells);

//интерфейс, предоставляющий информацию о сервисеXServiceInfo xServiceInfo =

(XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, xCellRange);

//проверяем, поддерживает ли родительский объект (регион ячеек) этот интерфейс (в строке записан)

34

Page 35: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

//иначе говоря, если работаем с листом Calcif(xServiceInfo.supportsService("com.sun.star.sheet.Spreadsheet")){

//если да --////строка – имя свойстваbackColorPropertyName = "CellBackColor";//выделяем регион ячеекxSelectedCells = xCellRange.getCellRangeByName("A1:B2");//набор свойств таблицыxTableProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class,

xSelectedCells);}//иначе, если работаем с текстовой таблицейelse if(xServiceInfo.supportsService("com.sun.star.text.TextTable"))

{//имя свойства другоеbackColorPropertyName = "BackColor";//набор свойств таблацыxTableProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xCellRange);}

//и теперь пишем значение свойства (цвет фона ячеек)xCellProps.setPropertyValue(backColorPropertyName, new Integer(0x99ccff));

//объект-контурная линияBorderLine theLine = new BorderLine();//цветtheLine.Color = 0x000099;//толщинаtheLine.OuterLineWidth = 10;

//объект-граница таблицыTableBorder bord = new TableBorder();//всем границам присваиваем объект-контурную линиюbord.VerticalLine = bord.HorizontalLine = bord.LeftLine = bord.RightLine =

bord.TopLine = bord.BottomLine = theLine;

//разрешаем рисовать линии на всех границах таблицыbord.IsVerticalLineValid = bord.IsHorizontalLineValid = bord.IsLeftLineValid =

bord.IsRightLineValid =bord.IsTopLineValid = bord.IsBottomLineValid = true;

//устанавливаем свойство таблицыxTableProps.setPropertyValue("TableBorder", bord);

//получаем значение свойстваbord = (TableBorder)xTableProps.getPropertyValue("TableBorder");//изменяем имеющиеся объектыtheLine = bord.TopLine;//цветint col = theLine.Color;//выводи значениеSystem.out.println(col);

}

35

Page 36: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

protected void manipulateShape(XShape xShape) throws com.sun.star.uno.Exception{

//манипулирование фигурой////вначале получаем набор свойств текущей фигуры (полученной в аргументе)XPropertySet xShapeProps =

(XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xShape);//устанавливаем свойстваxShapeProps.setPropertyValue("FillColor", new Integer(0x99ccff));xShapeProps.setPropertyValue("LineColor", new Integer(0x000099));xShapeProps.setPropertyValue("RotateAngle", new Integer(3000));

xShapeProps.setPropertyValue("TextLeftDistance", new Integer(0));xShapeProps.setPropertyValue("TextRightDistance", new Integer(0));xShapeProps.setPropertyValue("TextUpperDistance", new Integer(0));xShapeProps.setPropertyValue("TextLowerDistance", new Integer(0));////все :)

}

protected XComponent newDocComponent(String docType) throws java.lang.Exception{

//получение документа заданного в аргументе типа////формируем строку-URLString loadUrl = "private:factory/" + docType;//получаем удаленный менеджер сервисов из текущего приложения//(то есть программы, текст который вы читаете)xRemoteServiceManager = this.getRemoteServiceManager();//объект-рабочий стол, основной объект OOoObject desktop = xRemoteServiceManager.createInstanceWithContext(

"com.sun.star.frame.Desktop", xRemoteContext);

//объект-загрузчик компонентовXComponentLoader xComponentLoader =

(XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);//массив значений свойствPropertyValue[] loadProps = new PropertyValue[0];//функция возвращает то, что загрузил объект-загрузчик компонентов//по указанному URLreturn xComponentLoader.loadComponentFromURL(loadUrl, "_blank", 0 ,loadProps);

}

protected XMultiComponentFactory getRemoteServiceManager() throws java.lang.Exception{

//получение удаленного менеджера сервисов////если он еще не получен и не получен удаленный контекст – if(xRemoteContext == null && xRemoteServiceManager == null)

{try //пытаемся{

//получаем удаленный контекстxRemoteContext = Bootstrap.bootstrap();//выводим сообщениеSystem.out.println("Соединение

36

Page 37: Начала программирования в OpenOffice.org

OpenOffice.org Developer Guide – Ch.2 First Steps.перевод kitovras – 2007г.

с работающим офисом... ");

//и получаем удаленный менеджер сервисовxRemoteServiceManager = xRemoteContext.getServiceManager();

}catch(java.lang.Exception e){

//иначе – выводим стек вызововe.printStackTrace();//выходим с ошибкойSystem.exit(1);

}}

//все нормальноreturn xRemoteServiceManager;

}}

37