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