В процессе автоматизации бизнес-процессов часто возникает задача отправить на печать большое количество внешних файлов (PDF-счетов, HTML-инструкций или сканов документов) непосредственно из интерфейса 1С. Основная сложность заключается в том, что платформа 1С не имеет встроенного метода «напечатать внешний файл» без открытия стороннего приложения. В этой статье мы разберем несколько проверенных способов реализации пакетной печати: от использования установленного Adobe Reader до применения легковесных утилит и системных скриптов.
Рассмотрим классический подход, который часто применяется в 1С. Он основан на использовании установленного в системе Adobe Reader. Основная идея заключается в вызове исполняемого файла программы с определенными ключами командной строки. Проанализируем пример кода, который позволяет отправить массив файлов на печать в фоновом режиме.
Для реализации нам потребуется объект WScript.Shell для запуска процесса и WbemScripting.SWbemLocator для мониторинга очереди печати Windows. Это необходимо, так как Adobe Reader не всегда корректно закрывается сам после выполнения задания.
Процедура ФоноваяПечатьPDFФайлов(МассивФайлов, ИмяПринтера = "") Экспорт
WshShell = Новый COMОбъект("WScript.Shell");
// Читаем путь к Adobe Reader из реестра
ПутьAdobeReader = WshShell.RegRead("HKCR\Software\Adobe\Acrobat\Exe\");
Если Не ЗначениеЗаполнено(ПутьAdobeReader) Тогда
Сообщить("Не найдена программа Adobe Reader! Печать pdf-файлов невозможна.", СтатусСообщения.Важное);
Возврат;
КонецЕсли;
oLocator = Новый COMОбъект("WbemScripting.SWbemLocator");
oService = oLocator.ConnectServer("", "", "", "");
oService.Security_.impersonationlevel = 3;
oService.Security_.Privileges.AddAsString("SeLoadDriverPrivilege");
Для каждого Файл Из МассивФайлов Цикл
// Ключ /N запускает новый экземпляр, /T отправляет на печать и завершает (в идеале)
WshShell.Run(ПутьAdobeReader + " /N /T " + """" + Файл.ПолноеИмя + """" + ?(ЗначениеЗаполнено(ИмяПринтера), " " + """" + ИмяПринтера + """", ""), 0);
ЗаданиеДобавлено = Ложь;
ТекущееВремя = ТекущаяДата();
// Ожидаем появления задания в очереди печати (таймаут 15 секунд)
Пока Не ЗаданиеДобавлено И ТекущаяДата() < ТекущееВремя + 15 Цикл
ОбработкаПрерыванияПользователя();
Для каждого ЗаданиеПечати Из oService.InstancesOf("Win32_PrintJob") Цикл
ЗаданиеДобавлено = ЗаданиеПечати.Document = Файл.Имя;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Ожидаем завершения печати всех заданий
ТекущееВремя = ТекущаяДата();
Пока (oService.InstancesOf("Win32_PrintJob").Count > 0) И (ТекущаяДата() < ТекущееВремя + 15) Цикл
// Пауза
КонецЦикла;
// Принудительно завершаем процесс Adobe Reader, так как он может остаться в памяти
ИмяПроцесса = "AcroRd32.exe"; // Или динамически извлечь из ПутьAdobeReader
WshShell.Run("taskkill /f /im " + ИмяПроцесса, 0);
КонецПроцедуры
Важный нюанс: использование taskkill — это «костыль», продиктованный особенностями работы Adobe Reader. Если в системе уже открыт другой PDF-документ пользователем, этот скрипт может его закрыть.
Если файлов очень много (более 50), Adobe Reader может начать захлебываться, открывая десятки окон. В этом случае эффективнее сначала «склеить» все PDF-файлы в один многостраничный документ, а затем отправить на печать один-единственный файл. Для этого удобно использовать бесплатную консольную утилиту pdftk.
Разберем алгоритм действий:
pdftk.exe с командой output для создания объединенного файла.
// Пример формирования команды для объединения
ВсеПутиКФайлам = "";
Для каждого Файл Из МассивФайлов Цикл
ВсеПутиКФайлам = ВсеПутиКФайлам + """" + Файл.ПолноеИмя + """ ";
КонецЦикла;
ФайлОбъединения = ПутьКВременнойПапке + "print_job_all.pdf";
Скрипт = Новый COMОбъект("WScript.Shell");
// Запуск pdftk: 0 - скрыть окно, 1 - дождаться завершения
Скрипт.Run("C:\Program Files (x86)\PDFtk\bin\pdftk.exe " + ВсеПутиКФайлам + " output " + ФайлОбъединения, 0, 1);
// Теперь печатаем ФайлОбъединения
Проанализировав недостатки Adobe Reader, многие разработчики переходят на SumatraPDF. Это маленькая, быстрая и бесплатная программа, которая идеально поддерживает командную строку. Она не оставляет «хвостов» в процессах и работает значительно стабильнее при пакетной обработке.
Для печати на конкретный принтер в тихом режиме используем следующую конструкцию:
// Команда для SumatraPDF
Команда = """" + ПутьКSumatra + """ -print-to """ + ИмяПринтера + """ -silent -exit-on-print """ + ПутьКФайлу + """";
ЗапуститьПриложение(Команда);
Параметр -exit-on-print гарантирует, что приложение закроется сразу после того, как данные уйдут в спулер печати Windows. Это избавляет нас от необходимости мониторить процессы и использовать taskkill.
Если мы не хотим привязываться к конкретному приложению (например, нужно печатать и PDF, и HTML, и DOCX), можно воспользоваться системным механизмом Shell.Application. Windows умеет вызывать команду «Печать» для любого зарегистрированного типа файла.
Shell = Новый COMОбъект("Shell.Application");
Папка = Shell.NameSpace(ПутьКПапкеСФайлом);
ФайлОбъект = Папка.ParseName(ИмяФайла);
// Вызываем действие "printto" (печать на конкретный принтер)
// Параметры: имя глагола, имя принтера
ФайлОбъект.InvokeVerbEx("printto", ИмяПринтера);
Плюс метода: универсальность. Минус: в системе должно быть установлено приложение по умолчанию для данного типа файла, поддерживающее печать из контекстного меню.
Печать HTML напрямую из командной строки сложнее, так как браузеры (Chrome, Edge) обычно открывают диалоговое окно печати. Однако мы можем использовать следующие подходы:
InternetExplorer.Application все еще доступен. Мы можем загрузить документ и вызвать метод ExecWB с параметром OLECMDID_PRINT.
// Пример конвертации HTML в PDF через Edge (командная строка)
Команда = "msedge --headless --print-to-pdf=""" + ПутьКРезультату + """ """ + ПутьКИсходнику + """";
ЗапуститьПриложение(Команда,, Истина); // Ждем завершения
Выясним основные причины, по которым печать может не работать или работать нестабильно:
USR1CV8). У этой учетной записи может не быть доступа к сетевым принтерам. В таких случаях печать лучше выносить на сторону клиента (через &НаКлиенте).\\Server\PrinterName.Таким образом, для простых задач идеально подойдет SumatraPDF, а для сложных случаев с объединением документов — связка 1С и pdftk. Выбор конкретного метода зависит от требований к стабильности и возможности установки стороннего ПО на рабочие станции пользователей.