При автоматизации бизнес-процессов часто возникает задача формирования печатных форм в формате PDF. Это может быть отправка договоров клиентам по электронной почте, выгрузка закрывающих документов для личного кабинета или архивация отчетов. Часто разработчики сталкиваются с дилеммой: исходный макет разработан в формате Microsoft Word (DOC/DOCX), а на выходе требуется получить строго PDF, да еще и объединить несколько разных документов в один файл.
В этой статье мы подробно и по шагам разберем все основные способы решения этой задачи — от простых встроенных механизмов платформы «1С:Предприятие» до продвинутых кроссплатформенных методов конвертации шаблонов Word без использования COM-объектов, которые отлично работают в том числе на серверах под управлением ОС Linux.
Если ваша печатная форма изначально реализована как стандартный табличный документ 1С (объект ТабличныйДокумент), то задача решается буквально несколькими строками кода «из коробки». Платформа 1С обладает мощным встроенным конвертером, который преобразует макет в PDF без привлечения сторонних программ.
Рассмотрим пример кода, в котором мы заполняем табличный документ, настраиваем параметры страницы для корректного отображения и сохраняем его на диск:
Процедура СформироватьИСохранитьТабДокВPDF(ДокументСсылка, ПутьДляСохранения)
// Получаем заполненный табличный документ из функции печати вашей конфигурации
ТабДок = ПолучитьПечатнуюФорму(ДокументСсылка);
// Настраиваем автоматический масштаб, чтобы документ красиво укладывался по ширине страницы
ТабДок.АвтоМасштаб = Истина;
// Задаем ориентацию страницы (при необходимости)
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
// Формируем уникальное имя файла
ИмяФайла = "Договор_" + СокрЛП(ДокументСсылка.Номер) + ".pdf";
ПолныйПуть = ПутьДляСохранения + "\" + ИмяФайла;
// Записываем документ в формате PDF
Попытка
ТабДок.Записать(ПолныйПуть, ТипФайлаТабличногоДокумента.PDF);
Сообщить("Документ успешно сохранен: " + ПолныйПуть);
Исключение
ЗаписьЖурналаРегистрации("Печать в PDF", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Не удалось сохранить файл PDF. Обратитесь к администратору.";
КонецПопытки;
КонецПроцедуры
Обратите внимание на важную деталь: начиная с версии платформы 1С 8.3.16, при сохранении табличного документа разработчикам доступен выбор специализированных стандартов долгосрочного хранения PDF/A-2 и PDF/A-3. Это гарантирует, что все шрифты будут внедрены непосредственно в сам файл, и документ отобразится абсолютно идентично на любом компьютере, смартфоне или в веб-браузере.
Если бизнес-логика вашей системы завязана на подготовленные пользователями шаблоны Microsoft Word (файлы .doc или .docx), в которые программно подставляются реквизиты, задача усложняется. Нам необходимо сначала заполнить файл Word, а затем перевести его в PDF.
Для операционных систем семейства Windows самым популярным методом является использование COM-соединения с установленным пакетом Microsoft Office. Давайте разберем этот процесс по шагам.
Проанализируем пример кода конвертации заполненного файла Word в PDF с помощью метода SaveAs:
Процедура КонвертироватьDocxВPdfЧерезCOM(ПутьКФайлуDocx, ПутьКФайлуPdf)
Попытка
// Инициализируем COM-объект MS Word
MSWord = Новый COMОбъект("Word.Application");
Исключение
ВызватьИсключение "На компьютере/сервере не установлен Microsoft Word или отсутствуют права на его запуск.";
КонецПопытки;
// Скрываем окно приложения, чтобы пользователь не видел процесс конвертации
MSWord.Visible = Ложь;
MSWord.DisplayAlerts = 0; // Отключаем предупреждения и диалоговые окна
Попытка
// Открываем исходный документ DOCX
Документ = MSWord.Documents.Open(ПутьКФайлуDocx);
// Код формата 17 соответствует константе wdFormatPDF в объектной модели MS Word
КодФорматаPDF = 17;
// Сохраняем в PDF
Документ.SaveAs(ПутьКФайлуPdf, КодФорматаPDF);
// Закрываем документ без сохранения изменений в оригинальном docx
Документ.Close(0);
Исключение
// Обязательно корректно закрываем процесс Word в случае непредвиденной ошибки
MSWord.Quit();
ЗаписьЖурналаРегистрации("Конвертация DOCX в PDF", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Ошибка конвертации документа через MS Word.";
КонецПопытки;
// Завершаем работу с приложением Word
MSWord.Quit();
КонецПроцедуры
Важное предупреждение для серверных решений: Использование COM-объектов MS Office (технология DCOM) крайне не рекомендуется компанией Microsoft для использования в фоновых заданиях, веб-сервисах и на стороне сервера 1С. Сессия пользователя winword.exe может зависнуть в памяти из-за скрытого диалогового окна (например, сообщения о проверке орфографии или активации лицензии), что приведет к утечке ресурсов и блокировке работы сервера.
Если серверная часть вашей системы 1С работает под управлением операционной системы Linux или вы хотите отказаться от использования проприетарного MS Office на сервере Windows, идеальным решением станет использование бесплатного пакета LibreOffice.
Мы можем запустить LibreOffice в так называемом «безголовом» режиме (headless), передав ему параметры конвертации через командную строку. Для этого используется стандартный метод 1С ЗапуститьПриложение().
Рассмотрим, как выглядит этот кроссплатформенный вызов:
Процедура КонвертироватьЧерезLibreOffice(ПутьКФайлуDocx, КаталогНазначения)
// Для Windows путь обычно выглядит так: "C:\Program Files\LibreOffice\program\soffice.exe"
// Для Linux достаточно вызвать системную команду: "libreoffice"
ИмяПриложения = ?(ПолучитьСистемнуюИнформацию().ТипПлатформы = ТипПлатформы.Windows_x86
Или ПолучитьСистемнуюИнформацию().ТипПлатформы = ТипПлатформы.Windows_x86_64,
"""C:\Program Files\LibreOffice\program\soffice.exe""",
"libreoffice");
// Формируем параметры запуска для конвертации без графического интерфейса
ПараметрыЗапуска = " --headless --convert-to pdf """ + ПутьКФайлуDocx + """ --outdir """ + КаталогНазначения + """";
// Запускаем процесс в синхронном режиме (третий параметр = Истина), ожидания завершения конвертации
Попытка
ЗапуститьПриложение(ИмяПриложения + ПараметрыЗапуска, , Истина);
Исключение
ЗаписьЖурналаРегистрации("LibreOffice Конвертер", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Не удалось запустить конвертер LibreOffice. Проверьте правильность путей и права доступа.";
КонецПопытки;
КонецПроцедуры
Этот способ отличается высочайшей стабильностью, производительностью и полной независимостью от лицензирования продуктов Microsoft.
В практике часто встречается ситуация, когда пользователю требуется распечатать комплект из нескольких документов (например: Договор, Счет, Акт и Спецификация). Если выводить их на печать по отдельности, откроется несколько окон или сформируется несколько файлов. Рассмотрим, как объединить их в один общий файл PDF.
Если все объединяемые документы генерируются внутри 1С в виде табличных документов, мы можем использовать специальный платформенный объект ПакетОтображаемыхДокументов. Он позволяет собрать коллекцию документов и сохранить их как один PDF-файл с сохранением индивидуальных настроек (например, ориентации страниц) для каждой части пакета.
Разберем по шагам практический пример реализации:
Процедура ОбъединитьТабДокиВЕдиныйPDF(МассивТабличныхДокументов, ПутьКФайлуРезультата)
// Создаем объект пакета документов
ПакетДокументов = Новый ПакетОтображаемыхДокументов;
// Обходим массив переданных печатных форм и добавляем их в состав пакета
Для Каждого ТекущийТабДок Из МассивТабличныхДокументов Цикл
НовыйЭлементПакет = ПакетДокументов.Состав.Добавить();
НовыйЭлементПакет.Данные = ТекущийТабДок;
КонецЦикла;
// Записываем собранный пакет в один файл PDF
Попытка
ПакетДокументов.Записать(ПутьКФайлуРезультата, ТипФайлаПакетаОтображаемыхДокументов.PDF);
Сообщить("Пакет документов успешно объединен и записан!");
Исключение
ВызватьИсключение "Ошибка записи пакета документов в PDF: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
КонецПроцедуры
Если файлы PDF уже сформированы из сторонних источников (например, сконвертированы из Word) и лежат на диске, объединить их средствами самой 1С напрямую не получится. В этом случае мы рекомендуем использовать консольные утилиты, такие как pdftk (PDF Toolkit) или Ghostscript.
Пример вызова утилиты pdftk из кода 1С для склеивания файлов:
Процедура СклеитьВнешниеPdfФайлы(МассивПутейКФайлам, ВыходнойФайл)
// Формируем список файлов для передачи утилите
СписокФайлов = "";
Для Каждого ПутьКФайлу Из МассивПутейКФайлам Цикл
СписокФайлов = СписокФайлов + """" + ПутьКФайлу + """ ";
КонецЦикла;
// Шаблон команды: pdftk файл1.pdf файл2.pdf cat output результат.pdf
КомандаЗапуска = "pdftk " + СписокФайлов + "cat output """ + ВыходнойФайл + """";
Попытка
ЗапуститьПриложение(КомандаЗапуска, , Истина);
Исключение
ВызватьИсключение "Ошибка объединения PDF через pdftk: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
КонецПроцедуры
Бывают ситуации, когда архитектура конфигурации 1С устарела или закрыта для редактирования кода формирования печатных форм, но при этом требуется автоматический вывод документов в PDF-файлы. В таких случаях на помощь приходят виртуальные принтеры, например, Bullzip PDF Printer или PDFCreator.
Эти программы устанавливаются в операционной системе Windows как обычные принтеры, но вместо физического вывода на бумагу они генерируют PDF-файл. Настройка выполняется следующим образом:
Рассмотрим, как направить печатную форму на определенный виртуальный принтер из 1С:
Процедура НаправитьПечатьНаВиртуальныйПринтер(ТабДок)
// Задаем имя принтера ровно так, как оно зарегистрировано в системе
ТабДок.ИмяПринтера = "Bullzip PDF Printer";
// Отправляем на печать без вывода диалога выбора принтера пользователю
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
КонецПроцедуры
Этот метод является отличным «обходным» решением в сложных инфраструктурных проектах, где отсутствует прямая возможность программного переопределения логики выгрузки документов.
Начиная с версии платформы 1С 8.3.22, разработчикам больше не требуется устанавливать на рабочие станции пользователей сторонний софт (Adobe Acrobat Reader или Foxit Reader) для визуализации PDF-файлов. В платформе появился встроенный объект просмотра.
Вы можете открыть сформированный PDF-файл прямо во встроенном окне просмотра 1С следующим образом:
Процедура ПоказатьPdfФайлПользователю(ПутьКФайлу)
Попытка
// Создаем встроенный объект PDF-документа
ДокументPDF = Новый ДокументPDF;
ДокументPDF.Прочитать(ПутьКФайлу);
// Открываем интерактивное окно просмотра в интерфейсе платформы
ДокументPDF.Показать();
Исключение
ВызватьИсключение "Не удалось прочитать или отобразить файл PDF.";
КонецПопытки;
КонецПроцедуры
Этот инструмент предоставляет пользователям удобный интерфейс с возможностью масштабирования, поворота страниц, поиска текста и прямой печати на физический принтер.
Подводя итоги, дадим несколько практических советов для выбора оптимального пути реализации: