Как реализовать пакетную печать PDF и HTML файлов из 1С на выбранный принтер

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе автоматизации бизнес-процессов часто возникает задача отправить на печать большое количество внешних файлов (PDF-счетов, HTML-инструкций или сканов документов) непосредственно из интерфейса 1С. Основная сложность заключается в том, что платформа 1С не имеет встроенного метода «напечатать внешний файл» без открытия стороннего приложения. В этой статье мы разберем несколько проверенных способов реализации пакетной печати: от использования установленного Adobe Reader до применения легковесных утилит и системных скриптов.

Способ 1. Печать через Adobe Reader и COM-объект WScript.Shell

Рассмотрим классический подход, который часто применяется в 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-документ пользователем, этот скрипт может его закрыть.

Способ 2. Объединение PDF-файлов перед печатью (утилита pdftk)

Если файлов очень много (более 50), Adobe Reader может начать захлебываться, открывая десятки окон. В этом случае эффективнее сначала «склеить» все PDF-файлы в один многостраничный документ, а затем отправить на печать один-единственный файл. Для этого удобно использовать бесплатную консольную утилиту pdftk.

Разберем алгоритм действий:

  1. Собираем полные пути ко всем временным файлам в одну строку через пробел.
  2. Вызываем pdftk.exe с командой output для создания объединенного файла.
  3. Печатаем полученный файл любым доступным способом.
  4. Удаляем временные файлы.

// Пример формирования команды для объединения
ВсеПутиКФайлам = "";
Для каждого Файл Из МассивФайлов Цикл
    ВсеПутиКФайлам = ВсеПутиКФайлам + """" + Файл.ПолноеИмя + """ ";
КонецЦикла;

ФайлОбъединения = ПутьКВременнойПапке + "print_job_all.pdf";
Скрипт = Новый COMОбъект("WScript.Shell");

// Запуск pdftk: 0 - скрыть окно, 1 - дождаться завершения
Скрипт.Run("C:\Program Files (x86)\PDFtk\bin\pdftk.exe " + ВсеПутиКФайлам + " output " + ФайлОбъединения, 0, 1);

// Теперь печатаем ФайлОбъединения

Способ 3. Использование SumatraPDF (рекомендуемый вариант)

Проанализировав недостатки Adobe Reader, многие разработчики переходят на SumatraPDF. Это маленькая, быстрая и бесплатная программа, которая идеально поддерживает командную строку. Она не оставляет «хвостов» в процессах и работает значительно стабильнее при пакетной обработке.

Для печати на конкретный принтер в тихом режиме используем следующую конструкцию:


// Команда для SumatraPDF
Команда = """" + ПутьКSumatra + """ -print-to """ + ИмяПринтера + """ -silent -exit-on-print """ + ПутьКФайлу + """";
ЗапуститьПриложение(Команда);

Параметр -exit-on-print гарантирует, что приложение закроется сразу после того, как данные уйдут в спулер печати Windows. Это избавляет нас от необходимости мониторить процессы и использовать taskkill.

Способ 4. Печать через Windows Shell (Verb PrintTo)

Если мы не хотим привязываться к конкретному приложению (например, нужно печатать и PDF, и HTML, и DOCX), можно воспользоваться системным механизмом Shell.Application. Windows умеет вызывать команду «Печать» для любого зарегистрированного типа файла.


Shell = Новый COMОбъект("Shell.Application");
Папка = Shell.NameSpace(ПутьКПапкеСФайлом);
ФайлОбъект = Папка.ParseName(ИмяФайла);
// Вызываем действие "printto" (печать на конкретный принтер)
// Параметры: имя глагола, имя принтера
ФайлОбъект.InvokeVerbEx("printto", ИмяПринтера);

Плюс метода: универсальность. Минус: в системе должно быть установлено приложение по умолчанию для данного типа файла, поддерживающее печать из контекстного меню.

Способ 5. Особенности печати HTML

Печать HTML напрямую из командной строки сложнее, так как браузеры (Chrome, Edge) обычно открывают диалоговое окно печати. Однако мы можем использовать следующие подходы:

  1. Internet Explorer COM-объект: Несмотря на его устаревание, движок InternetExplorer.Application все еще доступен. Мы можем загрузить документ и вызвать метод ExecWB с параметром OLECMDID_PRINT.
  2. Конвертация в PDF: Самый надежный современный способ — программно конвертировать HTML в PDF (например, через Headless-режим Chrome/Edge), а затем распечатать полученный PDF одним из способов, описанных выше.

// Пример конвертации HTML в PDF через Edge (командная строка)
Команда = "msedge --headless --print-to-pdf=""" + ПутьКРезультату + """ """ + ПутьКИсходнику + """";
ЗапуститьПриложение(Команда,, Истина); // Ждем завершения

Общие рекомендации при работе с пакетной печатью

Выясним основные причины, по которым печать может не работать или работать нестабильно:

Таким образом, для простых задач идеально подойдет SumatraPDF, а для сложных случаев с объединением документов — связка 1С и pdftk. Выбор конкретного метода зависит от требований к стабильности и возможности установки стороннего ПО на рабочие станции пользователей.

← На главную