Переход с операционной системы Windows на Linux (например, Astra Linux) ставит перед разработчиком 1С серьезную проблему: привычный механизм COMОбъект, который годами использовался для взаимодействия с Microsoft Office, в среде Linux не существует. Если в вашей базе на Windows печатные формы формировались через Word.Application, то при переносе на Linux код перестанет работать, выдавая ошибку инициализации объекта. В рамках построения защищенной IT инфраструктуры на базе Astra Linux такие задачи требуют принципиально иного подхода.
В данной статье мы подробно разберем, как решить эту задачу с минимальными затратами, сохранив возможность формирования качественных документов в формате DOCX. Мы проанализируем несколько подходов: от низкоуровневой работы с XML до использования внешних микросервисов.
Проанализируем структуру файла .docx. На самом деле это обычный ZIP-архив, внутри которого находятся XML-файлы с текстом и описанием стилей. Библиотека стандартных подсистем (БСП) уже давно отказалась от COM в пользу этого метода. Разберем этот процесс по шагам.
Основная идея заключается в том, чтобы не "управлять" приложением Word, а напрямую изменять содержимое файла. Для реализации манипуляций с архивами можно использовать встроенные средства или изучить инструменты для распаковки и запаковки файлов, работающие на чистом языке 1С. Рассмотрим алгоритм реализации:
ЧтениеZipФайла.word/document.xml — именно в нем хранится основной текст документа.ЧтениеXML. Если требуется сложная трансформация данных, можно задействовать модуль для конвертации JSON/XML/CSV.[ФИО]) на реальные данные из информационной базы..docx, используя ЗаписьZipФайла.Посмотрим на пример кода, реализующего базовую логику замены текста:
// Пример упрощенной замены текста в XML
ПутьКДокументу = "word/document.xml";
ТекстДокумента = ЧтениеТекста.Прочитать();
// Важно помнить, что Word может разбивать одну метку на несколько тегов XML
// Например, "[ФИО]" может превратиться в "[", "ФИ", "О]" в разных тегах <w:t>
ТекстДокумента = СтрЗаменить(ТекстДокумента, "[ФИО]", ДанныеОбъекта.ФИО);
ЗаписьТекста = Новый ЗаписьТекста(ПутьКРаспакованномуФайлу, КодировкаТекста.UTF8);
ЗаписьТекста.Записать(ТекстДокумента);
ЗаписьТекста.Закрыть();
Важный нюанс: Чтобы избежать разрыва тегов (когда Word вставляет служебные символы внутри вашей переменной-шаблона), рекомендуется в шаблоне Word вводить метки целиком, либо использовать механизм "Полей" (Fields) или вставлять текст через буфер обмена без форматирования.
Если вам требуется сложное форматирование, работа с таблицами и списками, ручная правка XML может стать слишком трудоемкой. В этом случае рассмотрим вариант использования скрипта на языке Python. Подобный сценарий Python в среде Astra Linux позволяет значительно расширить возможности сервера 1С.
Библиотека docxtpl позволяет использовать синтаксис шаблонов (похожий на Jinja2) прямо внутри Word-файла. Вы подготавливаете шаблон, где переменные указаны в двойных фигурных скобках: {{ name }}. Скрипт на Python берет данные и "рендерит" готовый документ. Интересно, что несмотря на отказ от COM в Linux, знания о том, как устроен COM объект на Python для 1С, могут помочь в понимании принципов взаимодействия двух языков.
Пример скрипта:
from docxtpl import DocxTemplate
def generate_doc(template_path, output_path, data):
doc = DocxTemplate(template_path)
# data - это словарь с данными, например {'name': 'Иван Иванович'}
doc.render(data)
doc.save(output_path)
Из 1С этот скрипт можно вызвать через команду ЗапуститьПриложение. Это требует установленного интерпретатора Python на сервере или клиенте (в Astra Linux он предустановлен).
Рассмотрим ситуацию, когда 1С работает на Linux-сервере, а обработку документов мы хотим вынести в отдельный сервис. Мы можем написать примитивный веб-сервер на Python или Go, который будет принимать данные в формате JSON, заполнять шаблон и возвращать готовый файл.
Проанализируем пример реализации серверной части на Python (используя стандартную библиотеку http.server и docxtpl):
# Упрощенный фрагмент серверной части
class DocxHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
# Логика заполнения шаблона...
# ...
self.send_response(200)
self.send_header('Content-type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')
self.end_headers()
self.wfile.write(generated_file_binary)
В 1С код вызова такого сервиса будет выглядеть современно и платформенно-независимо:
&НаКлиенте
Процедура СформироватьДокумент(Команда)
Соединение = Новый HTTPСоединение("127.0.0.1", 8000);
Запрос = Новый HTTPЗапрос("/");
// Передаем имя шаблона и данные
СтруктураДанных = Новый Структура("ИмяШаблона, ФИО", "Договор.docx", "Иванов Иван");
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
Запрос.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
ДвоичныеДанные.Записать(ПутьКФайлуРезультату);
ЗапуститьПриложение(ПутьКФайлуРезультату);
КонецЕсли;
КонецПроцедуры
Если вам нужно не только заполнить поля, но и конвертировать результат в PDF, лучшим инструментом в Linux будет LibreOffice. Он поддерживает работу через командную строку без запуска графического интерфейса.
Проанализируем команду для конвертации:
libreoffice --headless --convert-to pdf имя_файла.docx
Этот метод отлично сочетается с первым методом (правка XML): сначала вы создаете .docx путем замены текста в XML, а затем вызываете LibreOffice для финальной конвертации в PDF, если это необходимо пользователю.
Мы рассмотрели несколько способов замены COM-технологии на Linux. Выбор конкретного пути зависит от ваших задач:
docxtpl. Это дает огромную гибкость при верстке.При переходе на Linux важно помнить, что идеология "управления приложением" (COM) уступает место идеологии "генерации контента". Рассмотрим этот переход не как проблему, а как возможность сделать систему более быстрой и стабильной.