Разработчики 1С часто сталкиваются с задачей вывода документов на печать. Но что делать, если файл уже сформирован сторонней системой в формате PDF, получен по API или загружен из внешнего источника? Попытка применить старые решения из интернета часто приводит к путанице, как это случилось в рассматриваемой теме форума.
Давайте подробно разберем, почему популярный виртуальный принтер Bullzip PDF Printer не подходит для отправки готовых PDF-файлов на печать, выясним физический смысл процесса и рассмотрим самые надежные современные способы решения этой задачи.
Автор темы пытался использовать следующий код, найденный на просторах интернета:
Принтер = Новый ComObject("Bullzip.PDFPrinterSettings");
принтер.SetValue("output", ИмяВременногоФайла);
принтер.SetValue("ShowSaveAS", "never");
принтер.WriteSettings();
Таб.Имяпринтера = "Office_10";
Таб.Напечатать(Истина);
Проанализируем эту ситуацию. Здесь происходит принципиальная методологическая ошибка. Bullzip PDF Printer — это виртуальный принтер. Его основная и единственная задача — перехватить поток печати из программы (в данном случае из объекта 1С ТабличныйДокумент, который передан в переменную Таб) и сохранить этот поток в файл формата PDF на диске.
Когда мы пишем Таб.Напечатать(), платформа 1С берет пустой или заполненный макет (табличный документ) и отправляет его на виртуальный принтер Bullzip, который генерирует новый PDF-файл. Если у нас на входе уже есть готовый PDF-файл (например, полученный в виде двоичных данных через API), нам вообще не нужен табличный документ 1С, и тем более нам не нужен виртуальный принтер Bullzip. Нам требуется отправить существующий файл на реальный, физический (или сетевой) принтер вроде Office_10.
Выяснив причину заблуждения, рассмотрим работающие и эффективные способы отправки готового PDF на печать.
Начиная с версии платформы 1С:Предприятие 8.3.21, у разработчиков появился великолепный инструмент — встроенный объект ДокументPDF. Теперь для работы с файлами PDF и их отправки на печать больше не нужно устанавливать сторонние программы (такие как Adobe Acrobat Reader, Foxit Reader или специализированные утилиты).
Рассмотрим по шагам, как реализовать печать готового PDF-файла встроенными средствами платформы:
ДокументPDF и считываем данные.Посмотрим на пример реализации этого метода в коде:
// Предположим, что ДвоичныеДанныеФайла мы уже получили из API или хранилища
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресФайла);
// Создаем поток в оперативной памяти
Поток = Новый ПотокИзДвоичныхДанных(ДвоичныеДанныеФайла);
// Инициализируем объект ДокументPDF, встроенный в платформу
Документ = Новый ДокументPDF();
Попытка
// Считываем документ из потока памяти
Документ.Прочитать(Поток);
// Печатаем документ в "тихом" режиме без показа диалогового окна
// Внимание: печать будет произведена на принтер по умолчанию!
Документ.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
Поток.Закрыть();
Исключение
Поток.Закрыть();
ЗаписатьЛогОшибок(ОписаниеОшибки());
ВызватьИсключение "Не удалось прочитать или распечатать PDF-документ средствами платформы.";
КонецПопытки;
Важное ограничение штатного метода: при вызове метода Напечатать() с параметром РежимИспользованияДиалогаПечати.НеИспользовать система всегда отправляет документ на принтер, установленный в операционной системе Windows по умолчанию. Программно передать имя конкретного сетевого принтера (например, Office_10) напрямую в объект ДокументPDF без вывода интерактивного диалога в текущих версиях платформы невозможно. Если вам требуется автоматическая отправка на строго определенный принтер, отличный от принтера по умолчанию, перейдем к рассмотрению следующего способа.
Если вам необходимо отправлять файлы на конкретные сетевые принтеры в фоновом режиме без какого-либо участия пользователя, а версия вашей платформы ниже 8.3.21 или штатный механизм вам не подходит, лучшим решением станет использование сторонних консольных утилит.
Многие разработчики совершают ошибку, используя для тихой печати тяжелые программы вроде Adobe Acrobat Reader. Процессы этих программ часто остаются "висеть" в диспетчере задач Windows, блокируя файлы и потребляя ресурсы сервера. Для решения этой проблемы мы рекомендуем использовать крошечную, бесплатную и невероятно стабильную консольную утилиту PDFtoPrinter.exe.
Разберем по шагам, как настроить печать через эту утилиту:
PDFtoPrinter.exe и сохраните его в доступный для 1С каталог (например, в папку шаблонов на сервере или в общую сетевую папку).Рассмотрим пример кода для реализации этого алгоритма:
// 1. Получаем имя временного файла на диске клиента или сервера
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("pdf");
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресФайла);
ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
// 2. Указываем путь к утилите и имя целевого принтера
ПутьКУтилите = "C:\Program Files\PDFtoPrinter\PDFtoPrinter.exe";
ИмяПринтера = "Office_10"; // Точное имя сетевого или локального принтера
// 3. Формируем параметры запуска. Шаблон: "ПутьКФайлу" "ИмяПринтера"
// Кавычки необходимы на случай наличия пробелов в путях или именах принтеров
ПараметрыЗапуска = """" + ИмяВременногоФайла + """ """ + ИмяПринтера + """";
Попытка
// Запускаем утилиту. Третий параметр "Истина" заставляет 1С ожидать окончания процесса печати
ЗапуститьПриложение(ПутьКУтилите + " " + ПараметрыЗапуска, , Истина);
// После успешной печати обязательно удаляем временный файл
УдалитьФайлы(ИмяВременногоФайла);
Исключение
// В случае сбоя также пытаемся очистить временный файл
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
КонецПопытки;
ВызватьИсключение "Ошибка печати через PDFtoPrinter: " + ОписаниеОшибки();
КонецПопытки;
Этот способ является промышленным стандартом для серверной печати этикеток, накладных и счетов из 1С. Утилита работает мгновенно, не создает окон на экране и гарантированно завершает свой процесс в операционной системе после отправки файла в очередь печати.
В процессе обсуждения автор темы пришел к выводу, что проблему можно решить с помощью популярного PDF-ридера Foxit Reader (в сообщении он назвал его "Roxit"). Данная программа действительно поддерживает управление через командную строку.
Для "тихой" отправки файла на определенный принтер в Foxit Reader используется специальный ключ запуска /t. Давайте проанализируем, как это запрограммировать в 1С:
// Путь к установленному приложению Foxit Reader на компьютере пользователя
ПутьКFoxit = "C:\Program Files (x86)\Foxit Software\Foxit PDF Reader\FoxitPDFReader.exe";
// Путь к файлу, который нужно распечатать
ИмяВременногоФайла = "C:\Temp\Document.pdf";
ИмяПринтера = "Office_10";
// Формируем параметры запуска программы: /t "ПутьКФайлу" "ИмяПринтера"
ПараметрыЗапуска = " /t """ + ИмяВременногоФайла + """ """ + ИмяПринтера + """";
// Запускаем приложение в режиме ожидания завершения
ЗапуститьПриложение(ПутьКFoxit + ПараметрыЗапуска, , Истина);
Преимущества метода: если на рабочих станциях пользователей уже установлен Foxit Reader в качестве основного просмотрщика PDF-файлов, вам не потребуется скачивать и распространять дополнительные утилиты.
Недостатки метода: Foxit Reader — это тяжелое GUI-приложение. При вызове через командную строку на сервере или слабом клиенте оно может запускаться со значительной задержкой, а в некоторых версиях программа может не закрыться автоматически после завершения печати, оставляя процесс висеть в памяти.
Аналогично Foxit Reader, классический Adobe Acrobat Reader поддерживает запуск с параметрами командной строки. Нам понадобятся ключи:
/h — запуск приложения в свернутом (скрытом) режиме./t — отправка документа на печать на указанный принтер. Полный синтаксис ключа: /t <имя_файла> <имя_принтера> <имя_драйвера> <имя_порта>. На практике в современных операционных системах Windows достаточно передать только имя файла и имя принтера.Рассмотрим пример кода:
ПутьКAdobe = "C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe";
ИмяВременногоФайла = "C:\Temp\Document.pdf";
ИмяПринтера = "Office_10";
// Настраиваем команду для скрытой печати на выбранный принтер
ПараметрыЗапуска = " /h /t """ + ИмяВременногоФайла + """ """ + ИмяПринтера + """";
ЗапуститьПриложение(ПутьКAdobe + ПараметрыЗапуска, , Истина);
Обратите внимание, что Adobe Acrobat Reader печатает файлы качественно, с сохранением всех шрифтов и разметки, однако проблема "зависания" процесса в памяти Windows у него выражена сильнее, чем у Foxit Reader. При регулярной массовой печати на сервере вам может потребоваться периодически принудительно завершать процессы AcroRd32.exe программным путем с помощью команды taskkill. Для устранения зависших заданий в спулере операционной системы подойдёт программа для очистки очереди печати принтера.
Подведем итоги нашего исследования и выберем оптимальную архитектуру для решения вашей задачи:
ДокументPDF. Это избавит вас от зависимости от стороннего софта и проблем с правами доступа к операционной системе.PDFtoPrinter.exe. Она работает стабильно, предсказуемо и не оставляет "мусорных" процессов в памяти операционной системы.Foxit Reader или Adobe Reader, и вам нужно быстро внедрить печать без установки нового софта — используйте запуск этих программ с ключом /t через функцию ЗапуститьПриложение().