При разработке дополнительных отчетов и обработок для конфигураций на базе БСП (Библиотека стандартных подсистем) часто возникает задача создать универсальный инструмент. Например, обработка должна уметь заполнять табличную часть (ТЧ) документа, находясь непосредственно в его контексте, и одновременно с этим открываться как самостоятельная форма из общего списка дополнительных обработок для выполнения произвольных действий.
Рассмотрим, как правильно настроить внешнюю обработку, чтобы она поддерживала оба сценария использования, и разберем программные механизмы управления контекстом.
Самый правильный и архитектурно верный способ — это использование возможностей БСП по регистрации нескольких команд в одной обработке. Для этого нам необходимо модифицировать экспортную функцию СведенияОВнешнейОбработке в модуле объекта. Мы можем добавить в таблицу команд столько строк, сколько нам нужно, настраивая их поведение через колонку Использование.
Проанализируем типовую структуру функции регистрации:
Функция СведенияОВнешнейОбработке(ВерсияБСП = "") Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
ПараметрыРегистрации.Наименование = "Моя универсальная обработка";
// Указываем документы, в которых будет доступна обработка
ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
// Команда №1: Заполнение ТЧ из документа
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Заполнить данные из файла (в контексте)";
НоваяКоманда.Идентификатор = "ЗаполнениеИзДокумента";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
НоваяКоманда.ПоказыватьОповещение = Истина;
// Команда №2: Просто открытие формы (вне контекста)
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Открыть помощник (свободный режим)";
НоваяКоманда.Идентификатор = "СвободноеОткрытие";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
НоваяКоманда.ПоказыватьОповещение = Ложь;
Возврат ПараметрыРегистрации;
КонецФункции
В данном примере мы создаем две команды. Первая имеет тип ВызовКлиентскогоМетода — она предназначена для работы с формой документа. Вторая имеет тип ОткрытиеФормы — она просто откроет основную форму обработки. При этом важно понимать, что если вид обработки указан как ЗаполнениеОбъекта, то в общем интерфейсе "Дополнительные обработки" (вне документа) она может не отобразиться без дополнительных настроек видимости в БСП.
Иногда требуется вызвать форму обработки из другой внешней обработки или из кода расширения. В этом случае мы можем использовать механизм подключения внешней обработки "на лету" по её имени в справочнике. Разберем, как это реализовать программно.
Для начала создадим на сервере функцию для поиска ссылки на обработку по её наименованию:
&НаСервереБезКонтекста
Функция ПолучитьСсылкуНаВнешнююОбработку(ИмяОбработки)
Возврат Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ИмяОбработки);
КонецФункции
Затем реализуем клиентскую процедуру открытия. Выясним причину, по которой нам нужно использовать именно программный вызов: это позволяет передать в обработку произвольные параметры, которые не предусмотрены стандартным механизмом БСП.
&НаКлиенте
Процедура ОткрытьВнешнююОбработкуПрограммно(ИмяОтчетаОбработки, ПараметрыОткрытия)
СсылкаНаОбъект = ПолучитьСсылкуНаВнешнююОбработку(ИмяОтчетаОбработки);
Если СсылкаНаОбъект.Пустая() Тогда
Сообщить("Обработка не найдена в справочнике!");
Возврат;
КонецЕсли;
// Подключаем обработку во временное хранилище
ИмяОбработкиСлужебное = ДополнительныеОтчетыИОбработкиВызовСервера.ПодключитьВнешнююОбработку(СсылкаНаОбъект);
// Открываем форму подключенной обработки
ОткрытьФорму("ВнешняяОбработка." + ИмяОбработкиСлужебное + ".Форма", ПараметрыОткрытия);
КонецПроцедуры
Этот метод позволяет "обмануть" ограничения назначения и открывать форму обработки в любой момент, независимо от того, к какому документу она привязана в настройках СведенияОВнешнейОбработке.
Теперь рассмотрим ситуацию, когда форма обработки уже открыта. Нам необходимо понять: запущена она из документа для заполнения ТЧ или открыта самостоятельно? От этого зависит, сможем ли мы получить доступ к данным владельца.
В модуле формы, в обработчике ПриСозданииНаСервере, проанализируем входящие параметры. БСП при контекстном запуске всегда передает структуру ДополнительныеОтчетыИОбработки или массив ОбъектыНазначения.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, есть ли контекст документа
Если Параметры.Свойство("ОбъектыНазначения") Тогда
// Обработка запущена из документа
ОбъектДокумент = Параметры.ОбъектыНазначения[0];
Элементы.ГруппаКонтекстныеДействия.Видимость = Истина;
Иначе
// Обработка запущена самостоятельно
Элементы.ГруппаКонтекстныеДействия.Видимость = Ложь;
// Здесь можно инициализировать форму для автономной работы
КонецЕсли;
КонецПроцедуры
Важный момент: если вы используете команду типа ВызовКлиентскогоМетода, то в модуле формы должна присутствовать экспортная процедура ВыполнитьКоманду. Именно она является точкой входа при запуске из меню "Заполнение".
&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
Если ИдентификаторКоманды = "ЗаполнениеИзДокумента" Тогда
// Логика получения данных из формы владельца
Владелец = ЭтаФорма.ВладелецФормы;
// Работаем с Владелец.Объект.Товары и т.д.
КонецЕсли;
КонецПроцедуры
Выясним, какой из подходов лучше выбрать в конкретной ситуации:
СведенияОВнешнейОбработке, если вам нужно, чтобы обе возможности были доступны пользователю интерактивно через интерфейс системы.ПодключитьВнешнююОбработку, если одна обработка должна вызывать другую "вспомогательную" форму, не захламляя при этом командный интерфейс пользователя лишними кнопками.Помните, что при работе с внешними обработками в режиме Безопасного режима, программное подключение и открытие форм может требовать настройки соответствующих разрешений в профилях безопасности.