В чем проблема с двусторонней печатью?
Как известно, в настройках "Параметров страницы" печатной формы есть настройка "Двусторонняя печать" с вариантами: "Нет", "Переворот вверх", "Переворот влево", "Использовать настройки принтера".
Однако, этого параметра достаточно только когда мы выводим на печать одну печатную форму одного документа. В случае же, когда их несколько (печатаем сразу два и более документов) второй документ начинает печататься на обратной стороне листа, на котором закончился первый документ (если первый документ содержал нечетное количество страниц). Правильным, конечно же, является печать каждого нового документа на новом листе.
Разберем ситуацию на примере. Есть задача, по заданию Заказчика нужно разработать новую печатную форму документа "Реализация товаров и услуг" (РТУ) с возможностью печати с двух сторон. Причем пользователь должен иметь возможность выделить несколько документов реализации и распечатать их комплектом.
Как известно, в таком случае первое что нужно сделать, это создать новую обработку, которая будет являться "Внешней печатной формой"(ВПФ) документа РТУ.
Есть публикации других авторов, посвященные созданию ВПФ, например, эта: //infostart.ru/public/286059/, я же хочу привести минимально необходимый код:
1. для создания ВПФ документа;
2. для корректной работы двусторонней печати.
1. Создание простой Внешней печатной формы (ее можно скачать внизу статьи):
Как будет выглядеть печатная форма:
Дальше в "Модуле объекта" располагаем процедуру и две функции:
а)
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм,
"Пример двусторонней печати", "Пример двусторонней печати",
СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати));
КонецПроцедуры
- процедура Печать() обязательно должна быть у ВПФ. Она вызывается при формировании печатной форм документа (документов). Параметр МассивОбъектов - это Массив ссылок на документы, по которым мы формируем ВПФ. Параметр ОбъектыПечати - это СписокЗначений, также содержащий ссылки на документы.
б)
Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати) Экспорт
ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.АвтоМасштаб = Истина;
//для примера только в первый документ выведем 40 строк, в последующие - 5 строк.
НапечаталиПервыйДокумент = Ложь;
Для каждого СсылкаИзМассива Из МассивОбъектов Цикл
// Запомним номер строки, с которой начали выводить текущий документ.
// Нужно для возможности печатать покомплектно.
НомерСтрокиНачало = ТабДокумент.ВысотаТаблицы + 1;
Макет = ПолучитьМакет("Макет");
Шапка = Макет.ПолучитьОбласть("Заголовок");
Шапка.Параметры.Документ = Строка(СсылкаИзМассива);
ТабДокумент.Вывести(Шапка);
СтрокаОбласть = Макет.ПолучитьОбласть("Строка");
Для сч = 1 По 40 Цикл
//для примера только в первый документ выведем 40 строк,
//в последующие - 5 строк.
Если сч > 5 И НапечаталиПервыйДокумент Тогда
Прервать;
КонецЕсли;
СтрокаОбласть.Параметры.Номенклатура = "Товар " + Строка(сч);
СтрокаОбласть.Параметры.Количество = Строка(сч);
ТабДокумент.Вывести(СтрокаОбласть);
КонецЦикла;
// На последнем листе каждого документа делаем разрыв страницы.
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
НапечаталиПервыйДокумент = Истина;
КонецЦикла;
// Установим тип двусторонней печати
ТабДокумент.ДвусторонняяПечать = ТипДвустороннейПечати.ПереворотВлево;
Возврат ТабДокумент;
КонецФункции
- Функция СформироватьПечатнуюФорму() может называться и другим именем. Вызывается из процедуры Печать(). Ее суть в том, чтобы создать объект ТабличныйДокумент и в цикле (по документам содержащимся в параметре "МассивОбъектов") вывести в него заполненные области "Заголовок" и "Строка". В конце функции она возвращает готовый ТабличныйДокумент обратно в Процедуру Печать().
в)
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.1.3.1");
ПараметрыРегистрации.Наименование = "Пример двусторонней печати";
ПараметрыРегистрации.Вид ="ПечатнаяФорма";
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Истина;
ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Пример двусторонней печати";
НоваяКоманда.Идентификатор = "Пример двусторонней печати";
НоваяКоманда.Использование ="ВызовСерверногоМетода";
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL";
Возврат ПараметрыРегистрации;
КонецФункции
- Функция СведенияОВнешнейОбработке() - последняя функция нашего МодуляОбъекта. Она обязательна и стандартная для ВПФ. Содержит параметры, позволяющие добавить ее в "Дополнительные отчеты и обработки" (меню Администрирование - Печатные формы, отчеты, обработки).
Готово.
Теперь запускаем 1С:Предприятие. Добавляем ВПФ в "Дополнительные отчеты и обработки". Открываем список документов "Реализация товаров", выделяем например два любых документа и нажимаем "Печать" - "Пример двусторонней печати". Открывается заполненная печатная форма по двум документам. Нажимаем большую желтую кнопку "Печать" . Если все сделано правильно, то на нашем принтере, поддерживающем двустороннюю печать, распечатается два листа с двух сторон. Первая реализация на первый лист не влезет (т.к. строк в таблице 40) и закончится на одной стороне второго листа. Вторая реализация на печатается на обратной стороне второго листа. Таким образом, мы создали ВПФ и увидели проблему двусторонней печати. Рассмотрим ее решение ниже.
2. Что необходимо добавить для корректной двусторонней печати.
В функцию СформироватьПечатнуюФорму() добавляем следующий ключевой фрагмент кода:
// В табличном документе зададим имя области, в которую был
// выведен объект. Нужно для возможности печатать покомплектно.
УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабДокумент,
НомерСтрокиНачало, ОбъектыПечати, СсылкаИзМассива);
- вставить его нужно перед концом цикла по "Массиву объектов":
НапечаталиПервыйДокумент = Истина;
// В табличном документе зададим имя области, в которую был
// выведен объект. Нужно для возможности печатать покомплектно.
УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабДокумент,
НомерСтрокиНачало, ОбъектыПечати, СсылкаИзМассива);
КонецЦикла;
// Установим тип двусторонней печати
ТабДокумент.ДвусторонняяПечать = ТипДвустороннейПечати.ПереворотВлево;
- этот фрагмент выполняет вызов Процедуры ЗадатьОбластьПечатиДокумента() из общего модуля УправлениеПечатью. Суть процедуры в том, чтобы в передаваемом ТабличномДокументе выделить именованной областью каждый документ отдельно (на скриншотах подчеркнуты красным):
Начало второго документа:
Разберем параметры Процедуры УправлениеПечатью.ЗадатьОбластьПечатиДокумента():
ТабДокумент - формируемый табличный документ. НомерСтрокиНачало - передаем номер строки табличного документа с которой должна начинаться именованная область документа. ОбъектыПечати - Список значений с ссылками на документы. СсылкаИзМассива - ссылка на документ текущей итерации цикла).
Сама процедура простая и небольшая, можете посмотреть ее самостоятельно в общем модуле УправлениеПечатью, чтобы не перегружать статью лишним.
Полученные именованные области успешно обрабатывает метод Напечатать() объекта ПакетОтображаемыхДокументов, который в конечном итоге выполняется при формировании любой "Внешней печатной формы". (Рассмотрение, в какой момент метод вызывается, посчитал лишним для этой статьи.) Именованные области служат для того, чтобы отправлять печатную форму на печать покомплектно (по каждому документу отдельно).
Проблема решена.
К сведению: В сентябре 2016г через франчайзи писал обращение разработчикам о том, что на платформе 8.3.8.2054 (а также 8.2137 и 9.1818) перестала работать двусторонняя покомплектная печать объектом ПакетОтображаемыхДокументов. Это касалось даже типовых печатных форм Счет-фактура, Счет на оплату, ТОРГ-12 и т.д. Код ошибки на bugboard.v8.1c.ru: 10167935. Начиная с 8.3.9.2033 ее исправили.
Не судите за большое количество текста, старался написать максимально доступно. Буду рад комментариям. Это первая статья.