При разработке специализированных печатных форм в решениях на платформе 1С (в частности, в конфигурации «1С:Управление автотранспортом») часто возникает бизнес-требование: печатная форма должна формироваться строго тогда, когда документ введен на основании конкретного документа — например, «Заказ на ТС». Рассмотрим, как правильно реализовать такое ограничение, с какими сложностями механизмов Библиотеки стандартных подсистем (БСП) можно столкнуться и какие подходы к решению задачи являются наиболее надежными.
Проанализируем архитектуру подменю Печать. В управляемых формах на базе БСП выпадающий список команд формируется динамически. Когда мы подключаем печатную форму как внешнюю обработку (ВПФ) через справочник дополнительных отчетов и обработок, регистрация команды в функции СведенияОВнешнейОбработке() носит статический характер. Подсистема БСП не предоставляет стандартного интерфейса для передачи индивидуальных условий видимости или доступности непосредственно из файла внешней обработки.
Штатная процедура УправлениеПечатью.ДобавитьУсловиеВидимостиКоманды(), используемая в модулях менеджеров документов конфигурации, имеет ряд жестких ограничений:
ДокументОснование) или анализировать строки табличных частей.ПриАктивизацииСтроки приводит к постоянным вызовам сервера и критическому замедлению работы интерфейса пользователя.Выясним причину, почему в «1С:УАТ» дополнительно усложняется связка документов. В этой конфигурации путевой лист связывается с заказом на ТС не только через реквизит шапки ДокументОснование. В зависимости от специфики бизнес-процесса заказы могут указываться списком в табличной части путевого листа либо связываться опосредованно через документ «Маршрутный лист». Если просто заблокировать кнопку по условию одного реквизита шапки, часть валидных документов перестанет печататься.
Разберем самый гибкий и отказоустойчивый способ, к которому пришли участники обсуждения: оставить команду печати доступной всегда, но выполнять проверку условий непосредственно при нажатии. Для наглядности можно добавить понятное уточнение прямо в наименование команды, например: Путевой лист (только по Заказам ТС).
Посмотрим на пример реализации логики внутри экспортной процедуры Печать() внешней печатной формы. В момент выполнения мы получаем массив проверяемых объектов, проверяем наличие нужного основания и, если документ не соответствует правилу, выводим пользователю информационное сообщение без формирования пустого макета.
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
ПараметрыПечати = Новый Структура;
// Получаем описание команды из коллекции
УправлениеПечатью.ИнициализироватьКоллекциюПечатныхФорм(
КоллекцияПечатныхФорм,
"ПутевойЛистПоЗаказу",
НСтр("ru = 'Путевой лист (по Заказам ТС)'"));
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ПутевойЛист";
Для Каждого ТекущийДокумент Из МассивОбъектов Цикл
// Проверяем тип документа-основания
Основание = ТекущийДокумент.ДокументОснование;
ЭтоЗаказТС = (ТипЗнч(Основание) = Тип("ДокументСсылка.уатЗаказГрузоперевозки")
Или ТипЗнч(Основание) = Тип("ДокументСсылка.уатЗаказТС"));
Если Не ЭтоЗаказТС Тогда
ТекстСообщения = СтрШаблон(
НСтр("ru = 'Печатная форма доступна только для путевых листов на основании Заказа ТС! Документ: %1'"),
ТекущийДокумент);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, ТекущийДокумент);
Продолжить;
КонецЕсли;
// Формирование макета для корректного документа
СформироватьПечатнуюФорму(ТабличныйДокумент, ТекущийДокумент, ОбъектыПечати);
КонецЦикла;
Если ТабличныйДокумент.ВысотаТаблицы > 0 Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ПутевойЛистПоЗаказу",
НСтр("ru = 'Путевой лист (по Заказам ТС)'"),
ТабличныйДокумент);
КонецЕсли;
КонецПроцедуры
Преимущества такого подхода очевидны: не требуется вносить изменения в типовую конфигурацию, внешняя обработка обновляется независимо, а пользователь получает точное и понятное объяснение, почему печатная форма не была сформирована.
Рассмотрим альтернативную ситуацию, когда по требованиям регламента кнопку в подменю необходимо обязательно делать неактивной (Доступность = Ложь) или скрывать (Видимость = Ложь). В этом случае внешнюю печатную форму встроить стандартно не получится — потребуется механизм расширений.
Разберем по шагам алгоритм реализации в расширении конфигурации:
ПриЧтенииНаСервере и ПослеЗаписиНаСервере (используем аннотацию &После).Посмотрим на пример кода в модуле формы документа:
&После("ПриЧтенииНаСервере")
Процедура Расш1_ПриЧтенииНаСервере(ТекущийОбъект)
ОбновитьДоступностьКомандыПечати();
КонецПроцедуры
&После("ПослеЗаписиНаСервере")
Процедура Расш1_ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
ОбновитьДоступностьКомандыПечати();
КонецПроцедуры
&НаСервере
Процедура ОбновитьДоступностьКомандыПечати()
// Проверяем заполненность и тип документа основания
Основание = Объект.ДокументОснование;
ДокументПодходит = ЗначениеЗаполнено(Основание)
И (ТипЗнч(Основание) = Тип("ДокументСсылка.уатЗаказТС")
Или ТипЗнч(Основание) = Тип("ДокументСсылка.уатЗаказГрузоперевозки"));
// Поиск элемента подменю печати по имени созданной команды БСП
ИмяЭлемента = "ФормаПечать_ПутевойЛистПоЗаказу";
ЭлементМеню = Элементы.Найти(ИмяЭлемента);
Если ЭлементМеню <> Неопределено Тогда
ЭлементМеню.Доступность = ДокументПодходит;
КонецЕсли;
КонецПроцедуры
Если бизнес-процесс требует изолировать специализированную печать от стандартного подменю БСП, целесообразно вынести отдельную кнопку на командную панель формы через расширение конфигурации:
ПечатьПоЗаказуТС, и размещаем её на командной панели.ПриСозданииНаСервере, ПриЧтенииНаСервере и ПослеЗаписиНаСервере регулируем свойство Элементы.ПечатьПоЗаказуТС.Видимость или Элементы.ПечатьПоЗаказуТС.Доступность напрямую без поиска по динамическим коллекциям БСП.Проанализировав все варианты, для большинства практических задач наиболее надежным и простым в сопровождении остается Решение 1: использование внешней печатной формы со встроенным контролем оснований и информированием пользователя через ОбщегоНазначенияКлиентСервер.СообщитьПользователю.