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

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

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

Разберем детально, как обойти это ограничение, какие инструменты использовать и на что обратить внимание при настройке серверной печати.

Причина ограничения и анализ ситуации

Проанализируем, почему метод Напечатать() не работает на сервере. Серверный процесс 1С (обычно это rphost.exe) работает в так называемой "Сессии 0" операционной системы Windows. Это изолированная среда, не имеющая доступа к графическому интерфейсу и настройкам принтеров текущего пользователя. Метод Напечатать() требует взаимодействия с подсистемой печати ОС, которая на сервере для фоновых процессов просто не инициализирована в контексте визуального вывода.

Для решения задачи нам необходимо "вынести" процесс отправки на принтер за пределы встроенных методов платформы 1С. Рассмотрим основные варианты решения.

Решение 1: Печать через сохранение в PDF и внешние утилиты

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

Выясним, какие утилиты лучше всего подходят для этой задачи:

  1. SumatraPDF — легкая и бесплатная программа, поддерживающая печать без открытия окна (флаг -print-to-printer).
  2. PDFtoPrinter — специализированная крошечная утилита, созданная именно для отправки PDF на печать из командной строки.
  3. Adobe Acrobat Reader — стандартное решение, но оно более тяжеловесное и может "зависать" в памяти сервера.

Рассмотрим пример кода, реализующий этот алгоритм на стороне сервера:


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

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

// 3. Формируем команду для печати (пример для SumatraPDF)
ПутьКПрограмме = """C:\Program Files\SumatraPDF\SumatraPDF.exe""";
ИмяПринтера = "HP_LaserJet_Professional_P1102";
Команда = ПутьКПрограмме + " -print-to """ + ИмяПринтера + """ """ + ИмяФайла + """";

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

Важный момент: Если вы используете Adobe Reader, параметры запуска будут другими. Например, флаг /t позволяет отправить файл на конкретный принтер, но после этого процесс Reader часто остается висеть в памяти. Именно поэтому для серверных решений мы рекомендуем SumatraPDF или PDFtoPrinter.

Решение 2: Возврат документа на клиент через временное хранилище

Если фоновое задание инициируется пользователем из активного сеанса, мы можем применить другой подход. Вместо того чтобы пытаться печатать "силами сервера", мы передадим результат работы обратно в клиентское приложение.

Разберем этот процесс по шагам:

  1. Фоновое задание формирует ТабличныйДокумент.
  2. Документ помещается во временное хранилище по адресу, который был передан из клиентской части.
  3. Клиентское приложение периодически проверяет статус задания.
  4. Как только задание завершено, клиент забирает документ из хранилища и вызывает штатный метод Напечатать().

Посмотрим на пример кода для клиентской части:


// В обработчике ожидания завершения фонового задания
Результат = ПолучитьИзВременногоХранилища(АдресХранилища);
Если ТипЗнч(Результат) = Тип("ТабличныйДокумент") Тогда
    Результат.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
КонецЕсли;

Этот метод является самым "чистым" с точки зрения лицензирования и прав доступа, так как печать происходит в контексте текущего пользователя Windows.

Решение 3: Использование специализированных компонент (Yoksel)

Для более сложных случаев, когда стандартных возможностей сохранения в PDF недостаточно или требуется специфическое управление принтером, можно использовать внешние библиотеки, такие как Yoksel. Это мощный инструмент для работы с электронными таблицами, который умеет взаимодействовать с системными драйверами печати напрямую через COM-интерфейс или Native API.

Однако стоит учитывать, что использование COM-объектов на сервере требует их предварительной регистрации в системе и настройки прав доступа в консоли DCOM, что не всегда возможно в облачных инфраструктурах.

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

При использовании любого метода печати непосредственно с сервера (Решение 1), мы обязательно столкнемся с проблемой прав доступа. Рассмотрим типичные ошибки:

Права пользователя службы: По умолчанию служба 1С работает под учетной записью USR1CV8. У этого пользователя нет установленных принтеров. Чтобы печать заработала, необходимо либо запустить службу 1С под доменной учетной записью, у которой есть доступ к сетевым принтерам, либо установить принтеры локально для системной учетной записи через специальные утилиты.

Сетевые пути: Сервер не видит сетевые принтеры, подключенные как LPT1 или по именам типа \\Workstation\Printer, если они не прописаны в его сессии. Рекомендуется использовать статические IP-адреса принтеров или устанавливать их как локальные TCP/IP порты на самом сервере.

Очистка временных файлов: Не забывайте удалять временные PDF-файлы после печати. Если задание завершилось ошибкой, файлы могут накапливаться, забивая дисковое пространство сервера. Мы рекомендуем использовать конструкцию Попытка...Исключение или регламентное задание по очистке папки временных файлов.


Попытка
    ЗапуститьПриложение(Команда, , Истина);
    УдалитьФайлы(ИмяФайла);
Исключение
    ЗаписьЖурналаРегистрации("ПечатьНаСервере", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
КонецПопытки;

Резюме

Мы выяснили, что для печати табличного документа на сервере необходимо выйти за рамки стандартного метода Напечатать(). Самым гибким решением является связка сохранение в PDF + консольная утилита печати. Если же взаимодействие происходит в рамках пользовательской сессии, наиболее правильным будет возврат данных на клиент через временное хранилище. Выбор метода зависит от архитектуры вашего решения и возможности настройки серверного окружения.

← На главную