При автоматизации документооборота в 1С часто возникает задача предоставить пользователю для просмотра или последующей печати целый пакет документов. Это могут быть счета, расходные накладные, акты, счета-фактуры или внешние файлы (например, сканы сертификатов номенклатуры).
Если открывать каждый файл по отдельности в цикле через стандартные системные механизмы, операционная система пользователя мгновенно перегружается кучей окон браузера или стороннего просмотрщика. Рассмотрим классический пример неоптимального кода:
Shell = Новый COMОбъект("Shell.Application");
Для каждого Файл Из МассивФайлов Цикл
Shell.ShellExecute(Файл.ПолноеИмя);
КонецЦикла;
Такой подход крайне неудобен для конечного пользователя, которому приходится закрывать десятки окон или вручную отправлять каждый файл на печать. Намного удобнее склеить все PDF-документы в один многостраничный файл и отобразить его в едином окне. Разберем подробно, какими способами можно решить эту задачу, начиная с классических вариантов и заканчивая самыми современными механизмами платформы 1С:Предприятие.
Если вы работаете на современных версиях платформы 1С:Предприятие, вам больше не нужны внешние утилиты, библиотеки или сложные интеграции. Фирма «1С» добавила мощный встроенный механизм для работы с PDF-документами.
Проанализируем работу с новым типом данных ДокументPDF. Этот объект позволяет читать файлы PDF с диска, извлекать информацию и передавать их на форму без использования сторонних плагинов или браузеров. Чтобы показать итоговый файл пользователю, мы можем использовать элемент управляемой формы Поле PDF документа.
Разберем по шагам, как вывести готовый PDF-файл на форму в тонком или веб-клиенте:
АдресPDFВоВременномХранилище с типом Строка).
&НаКлиенте
Процедура ОткрытьPDFДокумент(ПутьКФайлу)
// Создаем объект встроенного языка 1С
Документ = Новый ДокументPDF;
Документ.Прочитать(ПутьКФайлу);
// Либо открываем документ в стандартном встроенном окне просмотра
Документ.Показать("Просмотр пакета документов");
КонецПроцедуры
Этот метод работает нативно во всех клиентах 1С, включая веб-клиент (в любом современном браузере), и не требует установки дополнительного софта на компьютеры пользователей.
Выясним ситуацию, когда исходные документы генерируются непосредственно в самой базе 1С из макетов табличных документов. В этом случае задача объединения решается полностью на стороне сервера без привлечения сторонних приложений.
Для этого мы применим встроенный объект класса ПакетОтображаемыхДокументов. Рассмотрим пример реализации функции, которая собирает массив табличных документов в единый многостраничный PDF-файл:
&НаСервере
Функция СформироватьПакетPDF(МассивТабличныхДокументов) Экспорт
Пакет = Новый ПакетОтображаемыхДокументов;
// Последовательно добавляем все табличные документы в пакет
Для каждого ТабДок Из МассивТабличныхДокументов Цикл
ЭлементПакета = Пакет.Состав.Добавить();
// Помещаем табличный документ во временное хранилище
ЭлементПакета.Данные = ПоместитьВоВременноеХранилище(ТабДок);
КонецЦикла;
// Задаем имя временного файла для сохранения
ИмяФайла = ПолучитьИмяВременногоФайла("pdf");
// Записываем объединенный файл в формате PDF
Пакет.ЗаписатьФайлДляПечати(ИмяФайла, СпособСжатияИзображенийPDF.СжатиеJPEG);
Возврат ИмяФайла;
КонецФункции
Такой подход идеален для работы в облачных сервисах (например, 1С:Фреш), так как он не использует файловую систему сервера напрямую для вызова сторонних программ и работает на любой операционной системе (Windows или Linux).
Что делать, если исходные файлы PDF поступают из внешних источников (например, готовые сканы документов, загруженные пользователями) и их необходимо склеить на сервере программно? Одним из проверенных временем и стабильных решений является крошечная консольная утилита PDFTK.
Преимущество PDFTK заключается в том, что она не требует полноценной установки на сервер. Достаточно скопировать исполняемый файл pdftk.exe и одну динамическую библиотеку libiconv2.dll в каталог на сервере (или прикрепить их как макет двоичных данных в саму конфигурацию 1С).
Посмотрим на пример кода, который склеивает массив файлов в один результирующий с помощью PDFTK:
&НаСервере
Процедура СклеитьФайлыЧерезPDFTK(МассивПутейКФайлам, ПутьКРезультату)
ПутьКПрограмме = "C:\Program Files\PDFTK\pdftk.exe"; // Укажите актуальный путь к утилите
// Формируем список файлов для передачи в командную строку
СписокФайловСтрокой = "";
Для каждого ПутьИзМассива Из МассивПутейКФайлам Цикл
СписокФайловСтрокой = СписокФайловСтрокой + """" + ПутьИзМассива + """ ";
КонецЦикла;
// Синтаксис PDFTK: pdftk file1.pdf file2.pdf cat output merged.pdf
ПараметрыЗапуска = СписокФайловСтрокой + "cat output """ + ПутьКРезультату + """";
// Запускаем приложение в синхронном режиме ожидания завершения
ЗапуститьПриложение(ПутьКПрограмме + " " + ПараметрыЗапуска,, Истина);
КонецПроцедуры
Важное примечание: Если ваш сервер 1С работает под управлением операционной системы Linux (что стало стандартом во многих современных инсталляциях), Windows-версия PDFTK работать не будет. В случае Linux-серверов мы рекомендуем использовать стандартную утилиту pdfunite, которая входит в пакет poppler-utils. Команда вызова в Linux выглядит следующим образом:
// Пример вызова pdfunite в Linux-окружении
КомандаLinux = "pdfunite " + СписокФайловСтрокой + """" + ПутьКРезультату + """";
ЗапуститьПриложение(КомандаLinux,, Истина);
Если вы используете более ранние версии платформы 1С (до 8.3.21) и у вас нет встроенного элемента Поле PDF документа, задачу вывода файла на форму в браузере можно решить с помощью стандартного поля HTML-документа и JS-библиотек.
Одним из самых популярных инструментов для рендеринга PDF внутри браузера является библиотека PDF.js от Mozilla. Разберем, как реализовать этот подход:
PDF.js и разместите ее файлы на веб-сервере или прямо в макете конфигурации как текстовый макет.Строка и видом элемента Поле HTML документа.
&НаКлиенте
Процедура ЗагрузитьPDFВHTMLПоле(ДвоичныеДанныеPDF)
СтрокаBase64 = ПолучитьСтрокуBase64ИзДвоичныхДанных(ДвоичныеДанныеPDF);
HTMLКод =
"<html>
|<head>
| <script src='https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.12.313/pdf.min.js'></script>
|</head>
|<body style='margin:0; padding:0; overflow:hidden;'>
| <canvas id='pdf-canvas' style='width:100%; height:100vh;'></canvas>
| <script>
| var pdfData = atob('" + СтрокаBase64 + "');
| pdfjsLib.getDocument({data: pdfData}).promise.then(function(pdf) {
| pdf.getPage(1).then(function(page) {
| var scale = 1.5;
| var viewport = page.getViewport({scale: scale});
| var canvas = document.getElementById('pdf-canvas');
| var context = canvas.getContext('2d');
| canvas.height = viewport.height;
| canvas.width = viewport.width;
| var renderContext = {
| canvasContext: context,
| viewport: viewport
| };
| page.render(renderContext);
| });
| });
| </script>
|</body>
|</html>";
// Записываем HTML-код в реквизит формы, связанный с Полем HTML-документа
СодержимоеHTMLПоля = HTMLКод;
КонецПроцедуры
Использование локальных JS-библиотек гарантирует стабильную работу решения внутри закрытых корпоративных сетей без необходимости обращения к внешним CDN-серверам (например, Cloudflare), что особенно важно при строгих требованиях к информационной безопасности предприятия.
Выбирайте наиболее подходящий для вашей инфраструктуры метод и делайте работу ваших пользователей с документами максимально комфортной!