Разработчики и администраторы 1С часто сталкиваются с задачей экономии бумаги при печати первичных документов. Типичный пример — необходимость распечатать две накладные (например, экземпляр поставщика и экземпляр покупателя) на одном физическом листе формата А4. На первый взгляд задача кажется простой: достаточно настроить параметры макета или воспользоваться свойствами платформы. Однако на практике разработчики сталкиваются с тем, что при просмотре документ выглядит правильно, а при отправке на принтер настройки «слетают» и выводится только один экземпляр на всю страницу.
В этой статье мы подробно разберем причины такого поведения платформы 1С:Предприятие 8.3, проанализируем стандартные механизмы Библиотеки Стандартных Подсистем (БСП) и рассмотрим несколько надежных способов реализации печати двух экземпляров накладной на одной странице.
Прежде чем переходить к коду, выясним причину проблемы. В современных конфигурациях 1С (таких как «Бухгалтерия предприятия», «Управление нашей фирмой», «Управление торговлей» и др.) вывод документов на печать контролируется подсистемой печати БСП. Когда пользователь нажимает кнопку «Печать», система выполняет следующие действия:
ТабличныйДокумент.Именно поэтому свойство ЭкземпляровНаСтранице = 2, заданное в коде, игнорируется при прямой печати, хотя в режиме предварительного просмотра (который использует чистый табличный документ без наложения сохраненных настроек БСП) все отображается корректно.
Рассмотрим по шагам четыре практических способа решения этой проблемы.
Это наиболее изящный и правильный способ с точки зрения архитектуры 1С. Чтобы БСП не применяла старые сохраненные настройки обычной накладной к нашей новой «двойной» печатной форме, необходимо назначить табличному документу уникальный ключ параметров печати.
Разберем пример кода, который задает нужные настройки:
ТабДок = Новый ТабличныйДокумент;
// Указываем уникальный ключ, отличный от стандартной накладной
ТабДок.КлючПараметровПечати = "КлючПараметровПечати_НакладнаяДвойная";
// Настраиваем вывод двух экземпляров на одну страницу
ТабДок.АвтоМасштаб = Истина;
ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт; // Чаще всего для А5 рядом нужен ландшафт
ТабДок.ЭкземпляровНаСтранице = 2;
ТабДок.КоличествоЭкземпляров = 2; // Обязательное условие для работы ЭкземпляровНаСтранице
Важное замечание: Свойство ЭкземпляровНаСтранице = 2 работает в платформе 1С только тогда, когда общее количество отправляемых на печать копий (свойство КоличествоЭкземпляров) равно двум или более. Если вы передадите на печать только 1 копию, принтер распечатает один экземпляр на половине листа, оставив вторую половину пустой.
Если игры с настройками принтера и БСП не помогают (например, из-за специфических драйверов сетевых принтеров на рабочих местах пользователей), самым надежным и предсказуемым способом остается физическое дублирование вывода макета в один табличный документ.
В этом случае мы программно выводим сначала первый экземпляр документа, затем разделительную линию (или визуальный разделитель типа «ножницы»), а следом — второй экземпляр документа.
Проанализируем правильный алгоритм реализации этого метода в коде:
ТабДок = Новый ТабличныйДокумент;
ТабДок.АвтоМасштаб = Истина; // Позволит платформе сжать макет, если он не умещается по высоте
Макет = ПолучитьМакет("МакетНакладной");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьРазделитель = Макет.ПолучитьОбласть("РазделительЭкземпляров"); // Тонкая область с пунктиром
// Цикл вывода двух экземпляров
Для НомерЭкземпляра = 1 По 2 Цикл
// Выводим данные одного экземпляра
ТабДок.Вывести(ОбластьШапка);
Для Каждого СтрокаТЧ Из СсылкаНаДокумент.Товары Цикл
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, СтрокаТЧ);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
ТабДок.Вывести(ОбластьПодвал);
// Если это первый экземпляр, выводим разделитель перед вторым
Если НомерЭкземпляра = 1 Тогда
ТабДок.Вывести(ОбластьРазделитель);
КонецЕсли;
КонецЦикла;
При использовании этого метода крайне важно соблюдать следующие правила:
ТабДок.ВывестиГоризонтальныйРазделительСтраниц() принудительно отправит второй экземпляр на новый лист бумаги, что нарушит нашу задачу.ТабДок.АвтоМасштаб = Истина.Если клиенту требуется максимально быстро отправлять документы на печать без лишних диалоговых окон, можно воспользоваться приемом, предложенным автором темы на форуме. Этот метод заключается во вмешательстве в модуль формы печати документов БСП (например, ПечатьДокументов) для перехвата управления конкретным типом документа.
Посмотрим на пример доработки процедуры Печать в модуле формы ПечатьДокументов:
Если ТабличныеДокументы.Количество() > 0
И ОбъектыПечати.Количество() > 0
И ТипЗнч(ОбъектыПечати[0].Value) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// Отправляем первый табличный документ напрямую на принтер по умолчанию
ТабличныеДокументы[0].Value.Print();
Возврат; // Прерываем стандартный алгоритм БСП, чтобы не открывать форму просмотра
КонецЕсли;
Этот способ решает проблему сброса настроек, так как метод Print() (или Напечатать() в русскоязычной локализации) отправляет документ напрямую на драйвер принтера, используя текущие установленные в коде свойства объекта ТабличныйДокумент, минуя фазу наложения сохраненных пользовательских настроек БСП.
Иногда программный код написан абсолютно верно, но печать все равно работает некорректно. Причиной могут быть известные ошибки платформы 1С:Предприятие 8.3 (например, зарегистрированные баги в релизах ветки 8.3.24, связанные с игнорированием параметров размещения страниц при использовании предварительного просмотра).
Если вы столкнулись с подобным поведением, рекомендуется выполнить следующие действия:
v8sp.lst в профиле локального пользователя Windows).Выбор конкретного метода зависит от требований вашего бизнес-процесса. Если вам нужна гибкость и сохранение стандартного интерфейса БСП — используйте Способ 1 с уникальным ключом параметров печати. Если важна стопроцентная гарантия вывода на любом принтере без изменения настроек — используйте Способ 2 с физическим дублированием областей макета.