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