Как программно распечатать внешний отчет или обработку в 1С:Предприятии на управляемых формах без вывода диалога?

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

При работе с системой 1С:Предприятие версии 8.3 на управляемых формах перед разработчиками и опытными пользователями часто возникает задача программной печати табличных документов. Нередко требуется не просто вывести документ на печать, а сделать это без интерактивного участия пользователя, то есть без показа стандартного системного диалога выбора принтера и настройки печати. Мы с вами подробно рассмотрим, как эффективно добиться этой цели, используя мощные возможности платформы 1С:Предприятие и стандартной библиотеки подсистем (БСП).

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

Ограничения и особенности работы с печатью в архитектуре управляемых форм

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

Таким образом, наша задача заключается в том, чтобы найти способ обойти это ограничение, не нарушая принципов безопасности. Решение обычно кроется в использовании серверного кода. Однако даже на сервере прямой доступ к *клиентским* принтерам невозможен по той же причине – сервер физически не имеет прямого доступа к устройствам, подключенным к клиентскому компьютеру. Истинное решение заключается в следующем многошаговом процессе: мы формируем табличный документ на сервере, а затем передаем специальную команду печати обратно на клиент. Клиентское приложение, получив эту команду, уже выполняет фактическую печать, но при этом ему можно явно указать, что диалог печати показывать не нужно. Этот механизм реализован в 1С через подсистему "Управление печатью".

Ключевая роль подсистемы "Управление печатью" из БСП

Самым надежным, масштабируемым и рекомендованным способом реализации программной печати без диалога в 1С:Предприятии является активное использование функциональности подсистемы "Управление печатью", которая является неотъемлемой частью Библиотеки стандартных подсистем (БСП). Если ваша конфигурация основана на типовых решениях или разработана с использованием БСП (а подавляющее большинство современных типовых конфигураций 1С активно ее используют), то мы имеем в своем распоряжении мощный и гибкий инструмент для унифицированной работы с печатью.

Подсистема "Управление печатью" предоставляет стандартизированные и хорошо отлаженные механизмы для выполнения ряда важных задач:

  1. Формирование и вывод печатных форм: Она централизует логику создания и отображения различных печатных документов.
  2. Сохранение и использование настроек печати: Позволяет каждому пользователю сохранять свои предпочтительные настройки печати (например, принтер по умолчанию, количество копий, ориентация страницы), которые затем могут быть автоматически применены при последующей печати.
  3. Печать документов без интерактивного диалога: Это именно та функция, которая является критически важной для нашей текущей задачи.

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

Пошаговое решение: Организация программной печати табличного документа без диалога

Теперь давайте подробно разберем весь процесс по шагам, предоставляя конкретные примеры кода, которые мы можем интегрировать в нашу собственную разработку.

Шаг 1: Подготовка и формирование табличного документа

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

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


&НаСервере
// Функция формирует табличный документ для последующей печати.
// В реальной системе здесь будет содержаться логика формирования конкретного отчета или формы.
Функция СформироватьТабличныйДокументДляПечати()

    // Создаем новый экземпляр табличного документа
    Перем ТабДок;
    ТабДок = Новый ТабличныйДокумент;

    // Опционально: устанавливаем имя параметров печати. Это может быть полезно
    // для сохранения специфичных настроек печати, связанных именно с этим типом документа.
    ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_МОЕГО_ОТЧЕТА";

    // --- Блок кода для наполнения табличного документа данными ---
    // Это пример простейшего заполнения. В вашем случае здесь будет сложная логика
    // получения данных, их форматирования и вывода в табличный документ.

    // 1. Получим область для вывода заголовка
    Макет = ПолучитьМакет("МакетТестовогоДокумента"); // Предполагаем, что есть такой макет
    ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
    ОбластьЗаголовок.Параметры.ТекстЗаголовка = "Программная печать без диалога";
    ОбластьЗаголовок.Параметры.ДатаФормирования = ТекущаяДата();
    ТабДок.Вывести(ОбластьЗаголовок);

    // 2. Выведем некоторую табличную часть
    ОбластьТаблицыШапка = Макет.ПолучитьОбласть("Таблица.Шапка");
    ТабДок.Вывести(ОбластьТаблицыШапка);

    Для Инд = 1 По 5 Цикл
        ОбластьТаблицыСтрока = Макет.ПолучитьОбласть("Таблица.Строка");
        ОбластьТаблицыСтрока.Параметры.НомерСтроки = Инд;
        ОбластьТаблицыСтрока.Параметры.Наименование = "Тестовая позиция №" + Инд;
        ОбластьТаблицыСтрока.Параметры.Количество = 10 * Инд;
        ОбластьТаблицыСтрока.Параметры.Цена = 100.00 + Инд;
        ОбластьТаблицыСтрока.Параметры.Сумма = ОбластьТаблицыСтрока.Параметры.Количество * ОбластьТаблицыСтрока.Параметры.Цена;
        ТабДок.Вывести(ОбластьТаблицыСтрока);
    КонецЦикла;

    // --- Настройки печати самого табличного документа (поля, ориентация и т.д.) ---
    // Эти настройки влияют на внешний вид документа, но не на процесс вывода на принтер.
    ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
    ТабДок.ПолеСлева = 15; // в миллиметрах
    ТабДок.ПолеСверху = 15;
    ТабДок.ПолеСправа = 10;
    ТабДок.ПолеСнизу = 10;
    ТабДок.АвтоМасштаб = Истина; // Автоматическое масштабирование документа по ширине страницы
    ТабДок.ПроцентМасштаба = 100; // Если АвтоМасштаб = Ложь, можно задать конкретный процент

    Возврат ТабДок;

КонецФункции

// Пример макета для демонстрации
// В реальной конфигурации макет будет прикреплен к отчету/обработке
// Или находиться в общем макете конфигурации
/*
МакетТестовогоДокумента
[Заголовок]
#ТекстЗаголовка
Дата формирования: #ДатаФормирования
[Таблица.Шапка]
|№ |Наименование |Количество |Цена |Сумма |
[Таблица.Строка]
|#НомерСтроки |#Наименование |#Количество |#Цена |#Сумма |
*/

Мы включили в этот пример не только создание нового объекта ТабличныйДокумент, но и демонстрацию его наполнения данными, используя макет. Это делает пример более реалистичным. Важно также установить различные параметры самого табличного документа, такие как ориентация страницы, поля, масштаб. Эти параметры влияют на то, как документ будет выглядеть на бумаге, но не на сам механизм отправки на принтер.

Шаг 2: Инициирование печати без диалога с помощью серверной процедуры БСП

После того как наш табличный документ готов, мы должны передать его в специальную серверную процедуру. Именно эта процедура будет использовать функциональность подсистемы "Управление печатью" БСП для инициирования процесса печати без вывода интерактивного диалога. Крайне важно, чтобы эта процедура была помечена директивой &НаСервереБезКонтекста. Это позволит нам вызвать ее из клиентского кода без передачи контекста формы, а также обеспечит ее доступ к серверным общим модулям БСП, где реализована вся логика печати.


&НаКлиенте
// Процедура-обработчик команды, которая будет вызвана, например, по нажатию кнопки.
Процедура КомандаПечатьБезДиалога(Команда)
    // 1. Формируем табличный документ.
    // Если формирование требует данных с сервера или сложной логики, вызываем серверную функцию.
    // Если данные уже есть на клиенте и логика простая, можно сформировать и на клиенте.
    ТабДок = СформироватьТабличныйДокументДляПечати(); // Вызываем нашу серверную функцию формирования

    // 2. Вызываем серверную процедуру, которая фактически отправит документ на печать
    // с использованием БСП и без вывода диалога.
    НапечататьТабличныйДокументНаПринтерБезДиалога(ТабДок);
КонецПроцедуры

&НаСервереБезКонтекста
// Эта серверная процедура является точкой входа для печати без диалога.
// Она взаимодействует с подсистемой "УправлениеПечатью" БСП.
Процедура НапечататьТабличныйДокументНаПринтерБезДиалога(ТабличныйДокументДляПечати)

    // Прежде всего, мы должны убедиться, что подсистема "УправлениеПечатью"
    // вообще существует и подключена в текущей конфигурации.
    // Для этого используется вспомогательная функция ОбщегоНазначенияБСП.ПодсистемаСуществует().
    Если ОбщегоНазначенияБСП.ПодсистемаСуществует("УправлениеПечатью") Тогда

        // Получаем настройки печати для текущего пользователя (принтер по умолчанию, количество копий).
        // Мы рассмотрим этот шаг подробнее в следующем разделе, но здесь уже используем готовый результат.
        НастройкиПечати = УправлениеПечатью.ПолучитьНастройкиПечатиПоУмолчанию();
        
        // Извлекаем конкретные параметры из полученных настроек
        ИмяПринтера = НастройкиПечати.ИмяПринтера;       // Имя принтера. Если строка пустая, будет использоваться принтер по умолчанию ОС.
        КоличествоКопий = НастройкиПечати.КоличествоКопий; // Количество копий документа для печати, по умолчанию обычно 1.

        // Вызываем центральную функцию БСП для выполнения печати.
        // Именно этот метод обеспечивает печать без вывода диалога.
        УправлениеПечатью.НапечататьДокументНаСервере(ТабличныйДокументДляПечати, КоличествоКопий, ИмяПринтера);

    Иначе
        // В случае, если подсистема "УправлениеПечатью" не обнаружена или не подключена,
        // мы должны предусмотреть альтернативный сценарий.
        // Можно выдать предупреждение пользователю о невозможности автоматической печати.
        Сообщить("Внимание! Подсистема 'УправлениеПечатью' не найдена в конфигурации. Автоматическая печать без диалога невозможна. Будет предложена стандартная печать.", СтатусСообщения.Важное);
        // Как запасной вариант, предлагаем стандартную печать, которая вызовет диалог.
        ТабличныйДокументДляПечати.Напечатать(); // Этот вызов спровоцирует диалог печати на стороне клиента.
    КонецЕсли;

КонецПроцедуры

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

Шаг 3: Динамическое получение настроек печати (имя принтера и количество копий)

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

Для динамического получения настроек печати мы можем использовать функцию УправлениеПечатью.ПолучитьНастройкиПечатиПоУмолчанию(). Эта функция является частью подсистемы "Управление печатью" и возвращает структурированный объект (обычно это структура или подобный объект), который содержит информацию о предпочтительном принтере и количестве копий для текущего пользователя.

Вот как мы можем усовершенствовать нашу серверную процедуру, чтобы она динамически получала и применяла пользовательские настройки:


&НаСервереБезКонтекста
// Улучшенная серверная процедура для печати, учитывающая пользовательские настройки.
Процедура НапечататьТабличныйДокументНаПринтерБезДиалога(ТабличныйДокументДляПечати)
    Если ОбщегоНазначенияБСП.ПодсистемаСуществует("УправлениеПечатью") Тогда

        // 1. Получаем объект с настройками печати для текущего пользователя.
        // Эта функция возвращает структуру, содержащую ИмяПринтера и КоличествоКопий.
        НастройкиПечати = УправлениеПечатью.ПолучитьНастройкиПечатиПоУмолчанию();
        
        // 2. Извлекаем конкретные параметры из полученных настроек для использования в вызове.
        ИмяПринтера = НастройкиПечати.ИмяПринтера;
        КоличествоКопий = НастройкиПечати.КоличествоКопий;

        // Важно: если по логике вашей задачи требуется печатать на строго определенный принтер,
        // независимо от пользовательских настроек, вы можете переопределить ИмяПринтера.
        // Например:
        // ИмяПринтера = "HP LaserJet Pro MFP M428-M429 (USB001)"; // Указать точное имя сетевого или локального принтера

        // 3. Вызываем основную функцию печати из БСП с полученными или явно заданными параметрами.
        УправлениеПечатью.НапечататьДокументНаСервере(ТабличныйДокументДляПечати, КоличествоКопий, ИмяПринтера);

    Иначе
        // Действия, если БСП или подсистема печати недоступны.
        // Важно, чтобы пользователь получил обратную связь.
        Сообщить("Ошибка: Подсистема 'УправлениеПечатью' не найдена. Печать без диалога не может быть выполнена.", СтатусСообщения.Ошибка);
        ТабличныйДокументДляПечати.Напечатать(); // Откат к стандартной печати с диалогом
    КонецЕсли;
КонецПроцедуры

Метод УправлениеПечатью.ПолучитьНастройкиПечатиПоУмолчанию() представляет собой очень умную функцию. Он не просто берет первое попавшееся значение, а анализирует настройки текущего пользователя, а также может учитывать общие настройки конфигурации или даже настройки, специфичные для конкретного вида печатной формы (если они были предварительно заданы в системе). Это обеспечивает максимальную гибкость и удобство как для разработчика, так и для конечных пользователей, позволяя им настроить свою работу с печатью в соответствии с личными предпочтениями.

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

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

  1. Права пользователя: Это один из наиболее частых источников проблем. Убедитесь, что у пользователя, под которым выполняется операция печати, есть все необходимые права на интерактивную печать. Если у пользователя отсутствуют соответствующие роли или разрешения, даже самый корректный вызов через БСП может завершиться ошибкой или быть заблокирован системой безопасности 1С. Проверьте роли "Печать", "Интерактивная печать" и связанные с ними.
  2. Актуальность и наличие БСП: Как мы уже указывали в примерах кода, критически важно убедиться, что подсистема "Управление печатью" вообще присутствует в вашей конфигурации и находится в актуальном состоянии. Если конфигурация не использует БСП, или подсистема была удалена/отключена, вам придется либо отказаться от печати без диалога, либо реализовать собственный, более сложный механизм печати. Последнее может потребовать использования низкоуровневых COM-объектов на сервере (что крайне не рекомендуется для кроссплатформенных решений и создает значительные риски безопасности и стабильности) или принятия решения о всегда показывать диалог печати.
  3. Точность имени принтера: Если вы передаете пустое значение в параметр ИмяПринтера (как это происходит по умолчанию, если в настройках пользователя не указано иначе), будет использован принтер, установленный в операционной системе по умолчанию для текущего пользователя. Однако, если вы намерены печатать на конкретный, предопределенный принтер (например, сетевой принтер в определенном отделе), его имя должно быть точно указано. Это имя можно получить из системных настроек пользователя, из настроек, сохраненных в 1С (например, в регистре сведений НастройкиПользователей), или жестко задать в коде, если это оправдано бизнес-логикой. Помните, что имя принтера должно точно соответствовать тому, как оно отображается в операционной системе.
  4. Комплексное тестирование: Всегда проводите тщательное тестирование функциональности печати в различных операционных средах (тонкий клиент, веб-клиент, возможно, мобильный клиент) и под разными пользователями. Это позволит выявить потенциальные проблемы, связанные с различиями в настройках ОС, версиях браузеров или правах доступа.
  5. Печать в фоновых заданиях: Если ваша задача подразумевает печать в полностью фоновом режиме, то есть когда сервер сам инициирует печать без участия активного клиентского сеанса (например, по расписанию ночью), задача становится существенно сложнее. Метод УправлениеПечатью.НапечататьДокументНаСервере в таком сценарии не будет работать, так как ему для фактического вывода документа на принтер требуется активный клиентский сеанс. Для реализации истинной фоновой печати потребуется либо программно сохранять файл печатной формы на диске сервера и затем отправлять его на печать через команды операционной системы (что требует сложной настройки сервера, установки специального ПО и создает потенциальные уязвимости в безопасности), либо использовать специализированные сторонние сервисы и утилиты для печати, которые могут взаимодействовать с 1С через внешние компоненты или веб-сервисы. Однако для интерактивной, но бездиалоговой печати, рассмотренный подход является оптимальным и наиболее безопасным решением.

Итоги и финальные рекомендации по реализации

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

Мы глубоко проанализировали механизм работы этой функции, которая функционирует в тесной связке клиент-сервер: сервер готовит и отправляет команду, а клиент исполняет печать, аккуратно обходя стандартные системные диалоги. Кроме того, мы подробно рассмотрели, как эффективно получать и применять пользовательские настройки принтера и количество копий, что делает наше решение значительно более удобным, гибким и соответствующим ожиданиям конечных пользователей. Всегда помните о необходимости тщательной проверки прав доступа пользователей и актуальности версии БСП в вашей конфигурации, так как эти факторы критически влияют на стабильность и работоспособность решения.

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

← На главную