В процессе автоматизации документооборота в 1С программисты часто сталкиваются с нестандартными запросами пользователей. Один из ярких примеров — необходимость распечатать прикрепленный к карточке номенклатуры или заказа PDF-файл в виде брошюры (книжки). Это означает, что страницы документа должны быть масштабированы, развернуты в альбомную ориентацию и распределены по две штуки на одном листе бумаги с обеих сторон так, чтобы после сложения стопки листов пополам получилась аккуратная книжка с правильным порядком страниц.
По умолчанию стандартный функционал платформы 1С не имеет встроенного механизма для распределения страниц PDF в формате буклета (спуска полос). Настройки диалогового окна печати операционной системы Windows также не всегда позволяют передать нужные параметры программно без участия пользователя. В этой статье мы подробно разберем четыре эффективных метода реализации этой задачи, проанализируем их плюсы и минусы, а также рассмотрим примеры программного кода.
Если печать выполняется на определенный офисный принтер, самым стабильным и простым в реализации решением будет делегирование задачи раскладки страниц самому драйверу печати. Для этого мы создадим в операционной системе Windows копию существующего физического принтера, но с жестко заданными настройками по умолчанию.
Выясним алгоритм настройки по шагам:
Kyocera_Brochure.Рассмотрим пример кода на встроенном языке 1С для отправки документа на печать через утилиту SumatraPDF:
ИмяПринтераБрошюра = "Kyocera_Brochure";
ПутьКФайлу = "C:\temp\Instruction.pdf";
ПутьКSumatra = "C:\Program Files\SumatraPDF\SumatraPDF.exe";
// Формируем параметры запуска для скрытой отправки на целевой принтер
ПараметрыЗапуска = "-print-to """ + ИмяПринтераБрошюра + """ -silent """ + ПутьКФайлу + """";
Попытка
ЗапуститьПриложение(ПутьКSumatra + " " + ПараметрыЗапуска, , Истина);
ЗаписьЖурналаРегистрации("Печать PDF", УровеньЖурналаРегистрации.Информация, , , "Файл успешно отправлен на печать брошюрой.");
Исключение
ВызватьИсключение "Не удалось запустить утилиту печати SumatraPDF: " + ОписаниеОшибки();
КонецПопытки;
Преимущества метода: Высокая скорость работы, отсутствие сложного программирования, надежность (настройки брошюры контролируются самим драйвером принтера).
Недостатки: Требуется предварительная ручная настройка виртуального принтера на каждом рабочем месте пользователя (или централизованное развертывание системными администраторами).
Если нам нужно сделать решение универсальным, не зависящим от настроек локальных принтеров конкретного пользователя, мы должны пересобрать структуру самого PDF-файла перед отправкой на печать. Этот процесс называется спуском полос (Imposition). Мы преобразуем исходный многостраничный документ формата А4 в новый PDF-файл, в котором страницы будут программно скомпонованы попарно на листах А4 в альбомной ориентации в правильном «книжном» порядке.
Для автоматизации этой процедуры отлично подходит связка консольных утилит Ghostscript и psutils, либо специализированная консольная утилита pdfbook2.
Проанализируем шаги выполнения этой операции в фоновом режиме из 1С:
Input.pdf.Output_Booklet.pdf.Посмотрим на пример вызова утилиты pdfbook2 из кода 1С:
КаталогИнструментов = "C:\Program Files\pdfbook2\";
ИсходныйФайл = "C:\Storage\Specification.pdf";
РезультатФайл = "C:\Storage\Specification-book.pdf";
// Утилита автоматически создаст файл с суффиксом -book.pdf в той же папке
КомандаЗапуска = """" + КаталогИнструментов + "pdfbook2.exe"" --paper=a4paper --short-edge """ + ИсходныйФайл + """";
КодВозврата = 0;
ЗапуститьПриложение(КомандаЗапуска, , Истина, КодВозврата);
Если КодВозврата = 0 Тогда
// Полученный файл Specification-book.pdf отправляем на стандартную двустороннюю печать
// Драйвер принтера теперь не нужно настраивать на брошюру, так как страницы уже перегруппированы!
Шелл = Новый COMОбъект("WScript.Shell");
Шелл.Run("rundll32.exe mshtml.dll,PrintHTML """ + РезультатФайл + """", 0, Истина);
Иначе
ВызватьИсключение "Ошибка при генерации спуска полос брошюры. Код ошибки: " + Строка(КодВозврата);
КонецЕсли;
Преимущества метода: Полная независимость от модели принтера и его драйверов. Файл готов к печати «как есть» на любом дуплексном устройстве.
Недостатки: Требуется наличие установленных утилит Ghostscript или pdfbook2 на сервере 1С или клиентском компьютере.
Для конфигураций, работающих под управлением операционной системы Windows, классическим подходом является интеграция с установленным в системе приложением Adobe Acrobat через механизмы COM-соединения.
Выясним причину, почему разработчики часто выбирают этот способ: Acrobat Reader обладает мощным внутренним скриптовым движком (Acrobat JavaScript API), который позволяет программно управлять параметрами печати, включая раскладку буклета.
Ниже представлен пример инициализации COM-объекта и вызова настроек печати:
ПутьКФайлу = "D:\Documents\Report.pdf";
Попытка
// Создаем объект приложения Acrobat
AcroApp = Новый COMОбъект("AcroExch.App");
// Создаем объект документа для визуального отображения (AVDoc)
AVDoc = Новый COMОбъект("AcroExch.AVDoc");
Если AVDoc.Open(ПутьКФайлу, "") Тогда
// Получаем объект представления данных (PDDoc)
PDDoc = AVDoc.GetPDDoc();
// Получаем объект JavaScript для тонкой настройки параметров
JSO = PDDoc.GetJSObject();
// Задаем параметры печати через встроенный JS API Acrobat
// Нам нужно определить параметры "Booklet" в объекте PrintParams
ПараметрыПечати = JSO.getPrintParams();
ПараметрыПечати.pageHandling = ПараметрыПечати.constants.pageHandling.booklet;
ПараметрыПечати.interactive = ПараметрыПечати.constants.interactionLevel.silent; // печать без вывода диалогов
// Выполняем печать документа
JSO.print(ПараметрыПечати);
// Закрываем документ без сохранения изменений
AVDoc.Close(Истина);
КонецЕсли;
// Закрываем Acrobat Reader
AcroApp.Exit();
Исключение
Сообщить("Не удалось напечатать через Acrobat COM: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Преимущества метода: Точное соответствие алгоритмам спуска полос от Adobe, высокое качество рендеринга шрифтов и векторной графики.
Недостатки: Метод нестабилен при обновлении версий Adobe Reader. Если пользователь обновит программу или переустановит ее, COM-объекты могут перерегистрироваться с другими идентификаторами, что приведет к падению кода в 1С. Также метод не является кроссплатформенным.
В современных управляемых формах 1С (начиная с платформы 8.3.14, где встроенный движок отображения HTML переведен на WebKit/Chromium) разработчики могут использовать возможности JavaScript прямо внутри интерфейса программы.
Мы можем загрузить JS-библиотеку PDF.js (разработка Mozilla) в макет нашей конфигурации 1С и использовать ее для рендеринга страниц PDF внутри ПоляHTMLДокумента на форме. Это позволяет не только отображать PDF без использования внешних программ, но и использовать возможности современных браузеров для масштабирования и управления компоновкой печати.
Разберем по шагам логику интеграции:
PDF.js.ПолеHTMLДокумента.PDF.js, принимает двоичные данные файла PDF из 1С и инициализирует отрисовку страниц в объекте canvas.@media print мы перегруппируем выводимые холсты canvas по две штуки на один печатный лист, имитируя режим брошюры на уровне браузерного макета страницы.Пример подготовки HTML-кода для отправки в форму 1С:
&НаСервере
Функция ПолучитьHTMLКодДляПечати(АдресВременногоХранилища) Экспорт
// Формируем HTML-контейнер с подключением скриптов раскладки
ТекстHTML =
"<html>" +
"<head>" +
" <script src='pdf.js'></script>" +
" <style>" +
" @media print {" +
" .page-break { page-break-after: always; }" +
" canvas { width: 49%; display: inline-block; }" +
" }" +
" </style>" +
"</head>" +
"<body onload='initPrint()'>" +
" <div id='print-container'></div>" +
" <script>" +
" function initPrint() {" +
" // Логика загрузки PDF через PDF.js и рендеринг попарно в canvas" +
" // ... " +
" window.print();" +
" }" +
" </script>" +
"</body>" +
"</html>";
Возврат ТекстHTML;
КонецФункции
Преимущества метода: Работает непосредственно внутри тонкого клиента 1С без вызова внешних окон ОС Windows. Полностью контролируется кодом разработчика.
Недостатки: Требует глубоких знаний JavaScript, CSS Media Queries и архитектуры библиотеки PDF.js.
Выбор конкретного решения зависит от ИТ-инфраструктуры вашего клиента: