Работа с документами формата OpenDocument Text (ODT) из среды 1С часто вызывает затруднения у разработчиков, привыкших к объектной модели MS Word. Одной из типовых задач является определение количества страниц в готовом договоре или отчете, а также динамическое добавление элементов оформления, таких как штрихкоды, в колонтитулы документа. Разберем по шагам, как решить эти задачи с помощью COM-соединения с LibreOffice/OpenOffice и методом прямого редактирования XML-структуры файла.
Для взаимодействия с LibreOffice из 1С мы используем COMОбъект("com.sun.star.ServiceManager"). Основная сложность при получении количества страниц заключается в том, что текстовый процессор Writer вычисляет страницы динамически в процессе отрисовки (layout) документа. Рассмотрим, как правильно обратиться к этим данным.
Многие разработчики пытаются использовать методы типа GetSheets(), однако это методы табличного процессора Calc. Для текстового документа Writer необходимо обращаться к текущему контроллеру представления. Проанализируем пример кода:
// Инициализация сервисов LibreOffice
ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
// Настройка параметров открытия (открываем скрыто)
Параметры = НайтиПараметрыОткрытия(ServiceManager); // Массив PropertyValue
ООДокумент = Desktop.loadComponentFromURL(ПреобразоватьВURL(ИмяФайла), "_blank", 0, Параметры);
// Попытка получить количество страниц напрямую
КоличествоСтраниц = ООДокумент.getCurrentController().PageCount;
Важный нюанс: Если вы открываете документ в скрытом режиме (параметр Hidden = True), свойство PageCount может вернуть 0 или неактуальное значение. Это происходит потому, что фоновая верстка еще не завершена. Чтобы гарантированно получить верное число, рассмотрим более надежный метод с использованием «видимого курсора» (ViewCursor):
// Создаем курсор, привязанный к экрану (контроллеру)
ViewCursor = ООДокумент.getCurrentController().getViewCursor();
// Перемещаем курсор в самый конец документа
ViewCursor.jumpToLastPage();
// Теперь свойство getPage() вернет номер последней страницы
КоличествоСтраниц = ViewCursor.getPage();
Этот метод заставляет LibreOffice выполнить расчет геометрии документа до конца, что дает нам точный результат.
Если нам нужно только прочитать количество страниц, не запуская тяжелое приложение LibreOffice, мы можем рассмотреть ODT-файл как обычный ZIP-архив. Внутри него находится файл meta.xml, содержащий статистику документа.
Рассмотрим алгоритм действий:
meta.xml.<meta:document-statistic> и его атрибут meta:page-count.Внимание: Этот метод имеет ограничение. Значение в meta.xml обновляется только в момент сохранения файла в самом редакторе. Если вы программно меняли содержимое текста через XML и не пересохраняли его в интерфейсе Writer, данные в статистике могут оказаться устаревшими.
Ситуация усложняется, когда на каждую страницу документа нужно добавить штрихкод. Рассмотрим ситуацию: у вас есть готовый ODT-файл, и нужно вставить изображение штрихкода в нижний колонтитул (footer). Если штрихкод одинаковый для всех страниц, проще всего вставить его в описание Стиля страницы.
Выясним причину, почему работа через XML здесь эффективнее. При работе через COM-объект позиционирование картинки в колонтитуле требует сложных манипуляций с объектами TextGraphicObject и TextFrame. Через XML мы можем действовать прямолинейно.
Разберем структуру колонтитулов в ODT:
styles.xml (реже в content.xml).<style:master-page> в блоках <style:header> или <style:footer>.Pictures/ внутри архива.Посмотрим на пример описания картинки в XML для колонтитула:
<style:footer>
<text:p text:style-name="Footer">
<draw:frame draw:name="BarcodeImage" svg:width="4cm" svg:height="1.5cm">
<draw:image xlink:href="Pictures/barcode.png" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/>
</draw:frame>
</text:p>
</style:footer>
Критически важный шаг: Если вы добавляете новый файл изображения в архив, вы ОБЯЗАНЫ зарегистрировать его в файле META-INF/manifest.xml. Без этого при открытии документа LibreOffice выдаст ошибку о повреждении файла. Добавьте в манифест следующую строку:
<manifest:file-entry manifest:full-path="Pictures/barcode.png" manifest:media-type="image/png"/>
Проанализируем ситуацию: что делать, если в исходном документе вообще нет колонтитула? В этом случае нам нужно программно создать блок <style:footer> внутри <style:master-page>. Мастер-страница по умолчанию обычно называется "Standard".
Алгоритм автоматизации из 1С выглядит так:
ЗаписьZipФайла и ЧтениеZipФайла, работаем с ODT как с архивом.Pictures.styles.xml, вставляя блок <draw:frame> с ссылкой на нашу картинку.manifest.xml.Такой подход позволяет обрабатывать документы массово и с высокой скоростью, так как нам не требуется визуальное открытие окна редактора на сервере или клиенте. Если же ваша задача требует сложной переверстки, лучше использовать первый способ с COM-объектом, вызывая метод ООДокумент.store() после всех манипуляций.
Таким образом, мы рассмотрели основные методы управления страницами и содержимым ODT. Выбор метода зависит от ваших требований к производительности и необходимости визуального контроля процесса.