Рассмотрим частую задачу, с которой сталкиваются разработчики и системные администраторы: на одном рабочем месте установлено несколько принтеров — для этого подойдёт инструментарий для системного администрирования и выполнения команд. Например, локальный принтер этикеток или квитанций ПД-4 и обычный сетевой принтер для документов (например, счетов на оплату). По умолчанию в операционной системе Windows установлен сетевой принтер, и документы из 1С печатаются на него без проблем. Однако при печати этикеток система должна автоматически перенаправлять вывод на принтер этикеток, не требуя от пользователя ручного выбора устройства.
Разберем по шагам, почему стандартные средства платформы иногда не справляются с этой задачей, и проанализируем работающие способы решения проблемы.
Многие программисты пытаются решить задачу "в лоб" (поможет консоль для отладки кода 1С в Предприятии), указывая принтер в свойствах табличного документа и вызывая стандартный метод вывода на экран:
ТабДокументШтрих.ИмяПринтера = "\\Server\Gprinter GP-3120TN";
ТабДокументШтрих.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_Штрих";
ТабДокументШтрих.Показать();
Проанализируем ситуацию: при вызове метода Показать() платформа 1С передает управление интерфейсу операционной системы. Диалог предпросмотра Windows часто игнорирует программно заданное свойство ИмяПринтера и подставляет либо системный принтер по умолчанию, либо тот принтер, который пользователь выбирал в этом диалоге в прошлый раз.
Попытки программно очистить кэш настроек с помощью ХранилищеСистемныхНастроек.Удалить() также не приносят гарантированного результата. Дело в том, что платформа 1С кэширует настройки печати (включая последний выбранный принтер) в локальных файлах пользователя на компьютере. Если принтер "залип", часто помогает только физическая очистка кэша 1С в профиле пользователя ОС.
Выясним причину успешной работы этого метода. Если мы отказываемся от интерактивного показа документа пользователю (или его экспорта в изображения) и отправляем его сразу на печать, платформа жестко применяет переданные нами настройки табличного документа.
Рассмотрим пример кода для формирования табличного документа и его немедленной отправки на нужный принтер:
// Формируем ТабДок и заполняем его данными
ТабДок = Новый ТабличныйДокумент;
// ... код вывода областей макета ...
// Устанавливаем конкретный принтер для этикеток
ТабДок.ИмяПринтера = "Gprinter GP-3120TN";
ТабДок.АвтоМасштаб = Истина;
// Отправляем на печать без показа диалога
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
Важно: При таком подходе системный принтер по умолчанию в самой Windows остается прежним (сетевым). Мы лишь точечно направляем конкретный табличный документ на устройство печати этикеток — есть обработка для автоматизации пакетной печати документов.
Посмотрим на пример работы с принтерами через средства операционной системы. Если необходимо получить список установленных принтеров и предоставить пользователю выбор перед прямой печатью, можно использовать COM-объект. Рассмотрим код для управляемых форм (выполняется на клиенте):
&НаКлиенте
Процедура ВыбратьПринтерИНапечатать()
СписокПринтеров = Новый СписокЗначений;
Принтеры = Новый COMОбъект("WScript.Network");
КоллекцияПринтеров = Принтеры.EnumPrinterConnections();
// Перебираем коллекцию. Имя принтера находится на нечетных индексах
Счетчик = 0;
Пока Счетчик < КоллекцияПринтеров.Count() - 1 Цикл
ИмяУстройства = КоллекцияПринтеров.Item(Счетчик + 1);
СписокПринтеров.Добавить(ИмяУстройства);
Счетчик = Счетчик + 2;
КонецЦикла;
// Предлагаем пользователю выбрать из списка
ВыбранныйЭлемент = ВыбратьИзМеню(СписокПринтеров, Элементы.КнопкаПечати);
Если ВыбранныйЭлемент <> Неопределено Тогда
ТабДок.ИмяПринтера = ВыбранныйЭлемент.Значение;
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
КонецЕсли;
КонецПроцедуры
Почему этот подход считается устаревшим? Разберем современные ограничения: COMОбъект работает исключительно в среде Windows. Если предприятие использует клиентские рабочие места на базе Linux или пользователи работают через веб-клиент в браузере, этот код вызовет критическую ошибку. Более того, в 64-битных клиентах 1С могут возникать проблемы с инициализацией некоторых библиотек.
Если стоит строгая задача временно изменить именно системный принтер по умолчанию в Windows (чтобы работали другие приложения или метод Показать()), мы можем воспользоваться утилитами командной строки.
Рассмотрим схему работы: перед формированием этикетки 1С вызывает системную команду для смены принтера по умолчанию на принтер этикеток, показывает документ, а затем (после закрытия формы или по кнопке) возвращает обычный принтер обратно.
Пример команды для установки принтера:
ИмяПринтераЭтикеток = "Gprinter GP-3120TN";
СтрокаКоманды = "rundll32 printui.dll,PrintUIEntry /y /n """ + ИмяПринтераЭтикеток + """";
ЗапуститьПриложение(СтрокаКоманды, , Истина);
Этот метод работает безотказно на уровне ОС Windows, так как физически меняет настройку в реестре системы, имитируя ручные действия пользователя в панели управления.
Посмотрим на самое корректное архитектурное решение для современных типовых конфигураций (ERP, УТ, КА, БП). В них интегрирована Библиотека стандартных подсистем (БСП) с подсистемой "Управление печатью".
Вместо жесткого кодирования имен принтеров, мы можем настроить маршрутизацию печати в пользовательском режиме:
УправлениеПечатьюКлиент.ВыполнитьКомандуПечатиНаПринтер.Подсистема сама разберется, куда отправить макет. Она автоматически переопределит настройки табличного документа и отправит его на целевой принтер в фоновом режиме, ничего не ломая в операционной системе.
Резюме: Если вы работаете в современной базе на управляемых формах, старайтесь использовать механизмы БСП или прямую печать без предпросмотра (свойство ИмяПринтера + метод Напечатать()). Использование COM-объектов и системных скриптов следует оставить только для узкоспециализированных задач на локальных серверах под управлением Windows.