При разработке механизмов печати в системе 1С:Предприятие 8 часто возникает ситуация, когда стандартные функции конфигурации отправляют документ сразу на принтер по умолчанию. Это удобно для массовой потоковой печати, но создает трудности, если пользователю необходимо выбрать конкретное устройство (например, переключиться на сетевой принтер в другом кабинете или отправить документ в PDF-принтер). Рассмотрим подробнее, как изменить поведение системы и вызвать стандартный диалог выбора принтера "как в Windows" или реализовать собственную форму выбора.
Самый простой и правильный путь, заложенный в платформу 1С — это использование метода Напечатать объекта ТабличныйДокумент. Многие программисты по привычке используют процедуры из общих модулей (например, УниверсальныеМеханизмы), которые по умолчанию настроены на прямую печать. Разберем, как вызвать системный диалог выбора принтера программно.
Для этого в объекте ТабличныйДокумент предусмотрен специальный параметр РежимИспользованияДиалогаПечати. Рассмотрим пример кода:
// Предположим, ТабДок — это сформированный печатный макет документа
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.Использовать);
При выполнении этой строки кода 1С не отправит документ на печать мгновенно. Вместо этого откроется стандартное окно ОС Windows, где пользователь сможет выбрать принтер, указать количество копий и диапазон страниц. Это наиболее универсальный метод, так как он не требует написания сложного кода по перебору системных устройств.
Проанализируем ситуацию автора темы, который работает в конфигурации Комплексная автоматизация 1.1. В этой конфигурации (и аналогичных на обычных формах, таких как УПП 1.3) печать часто реализована через модуль УниверсальныеМеханизмы.
В коде автора используется функция НапечататьДокументПоУмолчанию. Само название говорит о том, что она игнорирует настройки и печатает на основное устройство. Чтобы исправить это, нам нужно использовать другую функцию — НапечататьДокумент. Выясним разницу: функция НапечататьДокумент принимает параметр НепосредственнаяПечать. Если передать в него значение Ложь, система предложит выбор.
Изменим исходный код автора из первого сообщения:
Для Каждого Элемент Из Массив Цикл
// Заменяем НапечататьДокументПоУмолчанию на универсальную процедуру
// Третий параметр (Ложь) отвечает за непосредственную печать
УниверсальныеМеханизмы.НапечататьДокумент(Элемент.ПолучитьОбъект(), 1, Ложь, Истина);
КонецЦикла;
Иногда пользователю удобнее сначала увидеть документ на экране, а уже потом нажать Ctrl+P. Для этого используется метод Показать(). Это "дружелюбное" решение, которое позволяет визуально проверить корректность заполнения макета. Рассмотрим, как это работает:
ТабДок.ТолькоПросмотр = Истина; // Запрещаем редактирование для пользователя
ТабДок.ОтображатьСетку = Ложь;
ТабДок.Показать("Печать счета на оплату");
Из открывшегося окна просмотра пользователь всегда может вызвать диалог печати через системное меню или панель инструментов.
Бывают специфические задачи, когда стандартный диалог Windows не подходит (например, нужно ограничить список доступных принтеров только определенными моделями или внедрить выбор принтера непосредственно в форму 1С). В этом случае мы можем воспользоваться средствами операционной системы через COM-объект WScript.Network.
Разберем по шагам, как получить список установленных принтеров и загрузить их в СписокЗначений на форме 1С:
ВыборПринтеров = Новый СписокЗначений;
Попытка
Network = Новый COMОбъект("WScript.Network");
Printers = Network.EnumPrinterConnections();
// В коллекции WScript принтеры идут парами: (Порт, Имя)
// Нас интересуют только имена, которые находятся на нечетных позициях
Для i = 0 По Printers.Count() - 1 Цикл
Если i % 2 <> 0 Тогда
ВыборПринтеров.Добавить(Printers.Item(i));
КонецЕсли;
КонецЦикла;
Исключение
Сообщить("Не удалось получить список принтеров: " + ОписаниеОшибки());
КонецПопытки;
// Теперь можно передать этот список в элемент управления на форме
ЭлементыФормы.ПолеВыбораПринтера.СписокВыбора = ВыборПринтеров;
После того как пользователь выберет имя принтера из списка, нам останется лишь назначить его табличному документу перед печатью с помощью свойства ИмяПринтера:
ТабДок.ИмяПринтера = ВыбранноеИмяПринтера;
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
Проанализируем критическую ошибку, которую часто допускают новички. В первом сообщении темы автор использует цикл Для Каждого Элемент Из Массив. Если внутри такого цикла вызвать метод Напечатать(РежимИспользованияДиалогаПечати.Использовать), то при попытке распечатать 20 документов пользователь получит 20 всплывающих окон подряд. Это крайне неудобно.
Правильное решение для групповой печати:
ТабличныйДокумент.Вывести().ВывестиГоризонтальныйРазделительСтраниц().Пример реализации групповой печати с одним диалогом:
ОбщийТабДок = Новый ТабличныйДокумент;
Для Каждого ДокументСсылка Из МассивОбъектов Цикл
// Получаем печатную форму конкретного документа
ТекущийТабДок = СформироватьПечатнуюФорму(ДокументСсылка);
// Добавляем к общему документу
ОбщийТабДок.Вывести(ТекущийТабДок);
// Чтобы каждый документ начинался с новой страницы
ОбщийТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЦикла;
// Вызываем окно выбора принтера ОДИН раз для всех документов сразу
ОбщийТабДок.Напечатать(РежимИспользованияДиалогаПечати.Использовать);
Таким образом, мы выяснили, что наиболее эффективным и безопасным способом является использование стандартного метода Напечатать с параметром РежимИспользованияДиалогаПечати.Использовать. Это избавляет от необходимости вручную программировать взаимодействие с ОС и корректно учитывает все настройки драйверов принтеров, сохраненные в профиле пользователя 1С.