В процессе работы с 1С часто возникает задача: для одного документа нужно иметь несколько вариантов печатных форм. Классический пример — документ, отражающий взаимоотношения с двумя контрагентами, например, поставщиком и покупателем. Хочется, чтобы в меню "Печать" были две разные кнопки: "Заказ Поставщику" и "Заказ Покупателя". При этом логично реализовать обе формы в рамках одной внешней обработки.
В старых конфигурациях, таких как "Бухгалтерия предприятия 2.0", для этого можно было при регистрации печатной формы задать дополнительные параметры и на их основе управлять логикой печати. Однако в современных конфигурациях на управляемых формах, в частности в БП 3.0, этот механизм изменился. Разберем, как правильно решить эту задачу, используя современный подход, рекомендованный фирмой "1С".
Современный и наиболее правильный способ — это регистрация нескольких команд печати в рамках одной внешней обработки. Вместо того чтобы передавать во внешнюю форму некий параметр, мы заранее определяем все возможные варианты печати в виде отдельных команд. Каждая команда будет отображаться в меню "Печать" документа своей строкой. Когда пользователь нажимает на одну из этих кнопок, система передает в нашу обработку уникальный идентификатор выбранной команды. Нам остается только проанализировать этот идентификатор и сформировать нужный макет.
Этот подход имеет ряд преимуществ:
Рассмотрим реализацию по шагам.
Это ключевая экспортная функция любой внешней обработки. Именно здесь мы "сообщаем" системе, какие возможности предоставляет наша обработка. Для нашей задачи нужно создать и описать две команды печати.
Проанализируем структуру кода. Для каждой команды мы создаем новый элемент в коллекции `ПараметрыРегистрации.Команды` и заполняем его свойства. Самые важные из них:
Представление — это текст, который пользователь увидит в меню "Печать".Идентификатор — это уникальное внутреннее имя команды. Именно по нему мы будем различать, какую кнопку нажал пользователь. Критически важно, чтобы идентификаторы для разных команд были разными!Назначение — массив типов документов, к которым будет привязана наша печатная форма.Модификатор — указывает тип команды, для печатных форм обычно ПечатьMXL.Посмотрим на пример кода для регистрации двух команд: "Заказ Поставщику" и "Заказ Покупателя" для нашего самописного документа "ЗаказНаПеремещение".
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
ПараметрыРегистрации.Вставить("Наименование", "Заказы (Поставщику и Покупателю)");
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
ПараметрыРегистрации.Вставить("Информация", "Печать заказов для поставщика и покупателя");
// Создаем таблицу команд
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
// Добавляем первую команду - "Заказ Поставщику"
НоваяКоманда = Команды.Добавить();
НоваяКоманда.Представление = "Заказ Поставщику";
НоваяКоманда.Идентификатор = "ЗаказПоставщику"; // Уникальный идентификатор
НоваяКоманда.Использование = "ВызовСерверногоМетода";
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL";
// Добавляем вторую команду - "Заказ Покупателя"
НоваяКоманда = Команды.Добавить();
НоваяКоманда.Представление = "Заказ Покупателя";
НоваяКоманда.Идентификатор = "ЗаказПокупателя"; // Другой уникальный идентификатор
НоваяКоманда.Использование = "ВызовСерверногоМетода";
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL";
ПараметрыРегистрации.Вставить("Команды", Команды);
// Указываем, к какому документу привязать команды
Назначение = Новый Массив;
Назначение.Добавить("Документ.ЗаказНаПеремещение"); // Замените на имя вашего документа
ПараметрыРегистрации.Вставить("Назначение", Назначение);
Возврат ПараметрыРегистрации;
КонецФункции
После регистрации такой обработки в справочнике Дополнительные отчеты и обработки в указанном документе в подменю "Печать" появятся две новые строки.
Теперь, когда команды зарегистрированы, нужно научить обработку их различать. Для этого служит экспортная процедура Печать. В ее параметры система передает всю необходимую информацию, включая массив ссылок на печатаемые объекты и структуру с параметрами вывода.
Идентификатор вызванной команды передается в параметре ПараметрыВывода. Это структура, у которой может быть свойство ИдентификаторКоманды. Проанализировав его значение, мы можем запустить формирование нужного макета.
Рассмотрим пример реализации процедуры Печать().
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Получаем идентификатор команды, которую выбрал пользователь.
ИдентификаторКоманды = ПараметрыВывода.ИдентификаторКоманды;
Если ИдентификаторКоманды = "ЗаказПоставщику" Тогда
// Логика формирования печатной формы "Заказ Поставщику"
УстановитьПривилегированныйРежим(Истина);
ТабличныйДокумент = СформироватьПечатнуюФормуЗаказПоставщику(МассивОбъектов, ОбъектыПечати);
УстановитьПривилегированныйРежим(Ложь);
// Выводим результат
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ЗаказПоставщику", // Имя для области макета
"Заказ Поставщику", // Синоним
ТабличныйДокумент
);
ИначеЕсли ИдентификаторКоманды = "ЗаказПокупателя" Тогда
// Логика формирования печатной формы "Заказ Покупателя"
УстановитьПривилегированныйРежим(Истина);
ТабличныйДокумент = СформироватьПечатнуюФормуЗаказПокупателю(МассивОбъектов, ОбъектыПечати);
УстановитьПривиле-гированныйРежим(Ложь);
// Выводим результат
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ЗаказПокупателя", // Имя для области макета
"Заказ Покупателя", // Синоним
ТабличныйДокумент
);
КонецЕсли;
КонецПроцедуры
// Вспомогательные функции для формирования каждого варианта
Функция СформироватьПечатнуюФормуЗаказПоставщику(МассивОбъектов, ОбъектыПечати)
// ... здесь код получения макета и его заполнения для поставщика
ТабДок = Новый ТабличныйДокумент;
// ...
Возврат ТабДок;
КонецФункции
Функция СформироватьПечатнуюФормуЗаказПокупателю(МассивОбъектов, ОбъектыПечати)
// ... здесь код получения макета и его заполнения для покупателя
ТабДок = Новый ТабличныйДокумент;
// ...
Возврат ТабДок;
КонецФункции
Таким образом, мы получаем элегантное и расширяемое решение. Если в будущем понадобится третий вариант печатной формы, достаточно будет добавить еще одну команду в СведенияОВнешнейОбработке() и новый блок ИначеЕсли в процедуру Печать().
Иногда упоминается и другой подход: создание одной команды печати, которая открывает промежуточную форму. На этой форме пользователь с помощью переключателей или кнопок выбирает нужный вариант, после чего запускается формирование отчета.
Почему этот вариант хуже?
Хотя такой способ и работоспособен, его стоит рассматривать только как вынужденную меру, если по каким-то причинам стандартный механизм команд не подходит. В подавляющем большинстве случаев решение с несколькими командами является предпочтительным.