Как реализовать автоматическую печать табличных документов из серверного контекста в 1С?

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

В процессе разработки автоматизированных систем на базе 1С часто возникает задача реализации регламентной печати. Типичный пример: регламентное задание должно собрать данные, сформировать накладные или этикетки и отправить их на принтер без участия пользователя. Однако программисты сразу сталкиваются с жестким ограничением платформы: метод ТабличныйДокумент.Напечатать() доступен только на клиенте. Попытка вызвать его на сервере приведет к ошибке, так как серверный контекст не имеет доступа к графической подсистеме и интерфейсу драйверов принтера в интерактивном режиме.

В этой статье мы подробно разберем, как обойти это ограничение, рассмотрим архитектурные подходы и выберем наиболее надежные инструменты для работы как в среде Windows, так и на Linux-серверах.

Почему метод Напечатать() не работает на сервере?

Прежде чем переходить к решениям, разберем причину проблемы. Объект ТабличныйДокумент на сервере — это лишь структура данных в памяти. Метод Напечатать() требует взаимодействия с очередью печати операционной системы (Print Spooler), выбора принтера через диалоговое окно или использования настроек по умолчанию из профиля пользователя. Служба сервера 1С (обычно usr1cv8) работает в так называемой «Сессии 0», которая изолирована от рабочего стола и пользовательского интерфейса. Именно поэтому нам требуются «обходные пути», которые позволят передать сформированный документ в операционную систему для вывода на печать.

Решение 1: Конвертация в PDF и использование консольных утилит (Windows)

Это самый популярный и стабильный метод. Общая схема выглядит так: формируем ТабличныйДокумент, сохраняем его во временный PDF-файл и вызываем внешнюю утилиту, которая умеет отправлять PDF на принтер в «тихом» режиме через командную строку.

Рассмотрим по шагам реализацию этого механизма. Сначала подготовим файл на сервере:


// Формируем табличный документ
ТабДок = Новый ТабличныйДокумент;
// ... заполнение документа данными ...

// Сохраняем во временный файл в формате PDF
ИмяФайла = ПолучитьИмяВременногоФайла("pdf");
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);

Теперь проанализируем инструменты для печати полученного PDF. Нам понадобятся бесплатные консольные утилиты, такие как PDFtoPrinter или SumatraPDF.

Вариант А: PDFtoPrinter. Эта крошечная программа специально создана для печати из командной строки. Она крайне проста в использовании. Пример вызова из 1С:


ПутьКУтилите = "C:\Utilities\PDFtoPrinter.exe";
ИмяПринтера = "\\Server\HP_LaserJet_400"; // Можно указать сетевое имя
КомандаЗапуска = СтрШаблон("%1 ""%2"" ""%3""", ПутьКУтилите, ИмяФайла, ИмяПринтера);

// Запускаем приложение на сервере
ЗапуститьПриложение(КомандаЗапуска, , Истина); 

Вариант Б: SumatraPDF. Более универсальный просмотрщик, поддерживающий ключи командной строки. Команда будет выглядеть так: SumatraPDF.exe -print-to "ИмяПринтера" -silent "путь_к_файлу". Этот метод хорош тем, что SumatraPDF очень корректно обрабатывает сложные шрифты и масштабирование. Для пакетного вывода графических файлов в аналогичном консольном режиме можно использовать решение для пакетной печати с помощью утилиты IrfanView.

Решение 2: Печать в среде Linux (CUPS)

Если ваш сервер 1С работает под управлением Linux, использование Windows-утилит невозможно. Однако в Linux задача решается еще проще благодаря стандартной системе печати CUPS, а реализация инфраструктуры на базе Astra Linux позволит автоматизировать процесс. Мы воспользуемся встроенной командой lp или lpr.

Проанализируем пример кода для Linux-сервера:


// Сохраняем файл
ИмяФайла = "/tmp/doc_to_print.pdf";
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);

// Формируем команду для системы печати CUPS
// -d указывает на имя принтера
ИмяПринтера = "Zebra_Label_Printer";
Команда = СтрШаблон("lp -d %1 %2", ИмяПринтера, ИмяФайла);

// Выполняем команду через оболочку
ЗапуститьПриложение(Команда, , Истина);

Важный нюанс: Убедитесь, что пользователь usr1cv8, от имени которого запущен процесс rphost, имеет права на выполнение команд печати и принтер виден в системе через команду lpstat -p.

Решение 3: Метод «Принт-сервера» на базе Тонкого клиента

Если использование внешних утилит по каким-то причинам запрещено политикой безопасности, можно реализовать архитектуру с выделенным сеансом 1С. Выясним, как это работает:

  1. Создаем в базе специальный регистр сведений (например, ОчередьПечати) с ресурсом типа ХранилищеЗначения, куда будем сохранять ТабличныйДокумент, полученный через механизмы БСП.
  2. На отдельном компьютере (или на самом сервере под обычным пользователем) запускаем 1С в режиме Тонкого клиента.
  3. В этом сеансе запускаем обработку, которая по таймеру (обработчик ожидания) проверяет наличие записей в регистре ОчередьПечати.
  4. При обнаружении записи обработка извлекает ТабличныйДокумент и выполняет штатный метод ТабДок.Напечатать(Ложь).

Этот способ является наиболее «нативным» для 1С, так как печать происходит в клиентском контексте, где доступны все установленные драйверы и настройки принтера по умолчанию, что позволяет реализовать полноценную групповую печать. Для автоматизации вывода стандартных форм подойдет обработка для печати любых печатных форм БСП.

Пример кода для клиентского «обработчика»:


&НаКлиенте
Процедура ПроверитьОчередьПечати()
    ЗаписьОчереди = ПолучитьЗаписьИзРегистраНаСервере();
    Если ЗаписьОчереди <> Неопределено Тогда
        ТабДок = ЗаписьОчереди.Данные.Получить();
        Если ТабДок <> Неопределено Тогда
            ТабДок.Напечатать(Ложь); // Печать без диалога
            УдалитьЗаписьИзОчередиНаСервере(ЗаписьОчереди.Ключ);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Решение 4: Прямая печать на термопринтеры (ZPL/ESC/POS)

Рассмотрим ситуацию с печатью этикеток. Часто при конвертации в PDF качество штрихкодов падает. Чтобы избежать этого, можно использовать прямую отправку команд на языке принтера (например, ZPL для Zebra). В этом случае нам вообще не нужен ТабличныйДокумент.

Мы формируем текстовую строку с командами управления и отправляем её напрямую в порт принтера (обычно TCP 9100) или через обертку командной строки copy file.txt \\server\printer. Это гарантирует идеальную четкость печати, так как используются встроенные шрифты принтера.

Технические тонкости и настройки прав

При реализации серверной печати необходимо учитывать несколько критических факторов, без которых решение не заработает:

  1. Права доступа: Пользователь usr1cv8 должен обладать правами на запуск внешних приложений (настройка в консоли администрирования кластера — «Разрешить запуск внешних программ»).
  2. Доступность принтера: Принтеры должны быть установлены как локальные на сервере. Если принтер сетевой, устанавливайте его через локальный порт (Local Port) с указанием UNC-пути \\server\printer, иначе служба сервера 1С может его «не увидеть».
  3. Шрифты на Linux: Если вы используете Linux, обязательно установите пакет шрифтов Microsoft (msttcorefonts). Без них ТабличныйДокумент при сохранении в PDF может сильно исказиться: колонки «поедут», а текст выйдет за границы ячеек.
  4. Сессия 0: Помните, что вы не увидите окон ошибок от сторонних утилит. Всегда перенаправляйте вывод ошибок в лог-файл для отладки, например: PDFtoPrinter.exe doc.pdf > log.txt 2>&1.

Подведем итог. Наиболее универсальным и рекомендуемым способом для Windows-инфраструктуры является связка 1С + PDF + PDFtoPrinter. Для кроссплатформенных решений или при жестких ограничениях безопасности лучше выбрать метод с выделенным клиентским сеансом, который будет выполнять роль диспетчера печати.

← На главную