При разработке интерфейсов на управляемых формах часто возникает задача динамического построения элементов: кнопок, групп или полей ввода. Одной из типичных проблем является программное обращение к уже созданной группе, чтобы поместить в нее другие элементы (например, кнопки), особенно когда эти группы создаются в цикле и имеют порядковые номера в именах. Разберем подробно, как правильно реализовать этот механизм, оптимизировать работу с данными и избежать типичных ошибок начинающих разработчиков.
В исходной ситуации разработчик пытается обратиться к элементу формы, используя конкатенацию строк напрямую через точку: ЭтаФорма.Элементы.ГруппаКнопкиСудов + "" + Счетчик. В языке 1С такой синтаксис недопустим. Если мы хотим обратиться к элементу коллекции, имя которого формируется динамически, мы должны использовать квадратные скобки [] для обращения по ключу (строковому имени).
Рассмотрим правильный подход к формированию имени и получению объекта элемента:
// Формируем строковое имя группы
ИмяГруппы = "ГруппаКнопкиСудов" + Формат(Счетчик, "ЧГ=0");
// Обращаемся к элементу через коллекцию Элементы
ГруппаДляКнопок = ЭтаФорма.Элементы[ИмяГруппы];
Использование функции Формат(Счетчик, "ЧГ=0") критически важно. Если просто использовать Строка(Счетчик), то при достижении значения 1000 система может вставить неразрывный пробел (например, "1 000"), что сделает имя элемента некорректным и приведет к ошибке выполнения.
Проанализируем представленный в теме код. Одной из серьезных архитектурных ошибок является выполнение запроса внутри цикла Для Счетчик = 1 по КоличествоСтрок. Это создает избыточную нагрузку на сервер базы данных. Правильным подходом будет получение всех необходимых данных одним запросом, а затем их распределение по группам на форме.
Разберем, как подготовить данные эффективно. Мы можем выбрать все подразделения, у которых заполнена ГруппаСудна, и упорядочить их. Проанализируем пример оптимизированного запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Подразделения.Наименование КАК Наименование,
| Подразделения.Код КАК Код,
| Подразделения.ГруппаСудна КАК ГруппаСудна
|ИЗ
| Справочник.ПодразделенияОрганизацийУпр КАК Подразделения
|ГДЕ
| Подразделения.ЭтоГруппа = ЛОЖЬ
| И Подразделения.ПометкаУдаления = ЛОЖЬ
| И Подразделения.АстраМарин = ИСТИНА
|УПОРЯДОЧИТЬ ПО
| Подразделения.ГруппаСудна,
| Наименование";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Теперь рассмотрим алгоритм совместного создания групп и размещения в них кнопок. Выясним, как правильно выстраивать иерархию элементов. При добавлении нового элемента методом Элементы.Добавить() третьим параметром необходимо передавать объект-родитель.
Шаг 1: Создание групп. Сначала мы создаем необходимое количество контейнеров (групп) на форме. Выясним, как задать им не только программное имя, но и понятный пользователю заголовок.
Для ИндексГруппы = 1 По 4 Цикл
ИмяГруппы = "ГруппаСудов_" + Формат(ИндексГруппы, "ЧГ=0");
// Проверяем, не создан ли элемент ранее
НоваяГруппа = Элементы.Найти(ИмяГруппы);
Если НоваяГруппа = Неопределено Тогда
// Добавляем группу на форму.
// Третий параметр - родитель (например, Элементы.ОсновнаяГруппа или ЭтаФорма)
НоваяГруппа = Элементы.Добавить(ИмяГруппы, Тип("ГруппаФормы"), ЭтаФорма.Элементы.ГруппаКнопкиСудов);
НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
НоваяГруппа.Заголовок = "Группа судов №" + ИндексГруппы;
НоваяГруппа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
КонецЕсли;
КонецЦикла;
Шаг 2: Распределение кнопок по группам. Проанализируем ситуацию, когда мы обходим выборку судов и ищем для каждого судна соответствующую ему группу по номеру, указанному в реквизите ГруппаСудна.
Пока Выборка.Следующий() Цикл
// Определяем имя группы, в которую должна попасть кнопка
ИмяГруппыРодителя = "ГруппаСудов_" + Формат(Выборка.ГруппаСудна, "ЧГ=0");
ГруппаРодитель = Элементы.Найти(ИмяГруппыРодителя);
Если ГруппаРодитель <> Неопределено Тогда
НаименованиеКнопки = Выборка.Наименование;
КодКнопки = "КнопкаСудно_" + СтрЗаменить(Выборка.Код, " ", "_");
// 1. Создаем команду
НоваяКоманда = Команды.Добавить(КодКнопки);
НоваяКоманда.Заголовок = НаименованиеКнопки;
НоваяКоманда.Действие = "Подключаемый_ДинамическаяКнопкаНажатие";
// 2. Создаем кнопку и привязываем ее к группе
НоваяКнопка = Элементы.Добавить(КодКнопки, Тип("КнопкаФормы"), ГруппаРодитель);
НоваяКнопка.ИмяКоманды = КодКнопки;
НоваяКнопка.Вид = ВидКнопкиФормы.ОбычнаяКнопка;
КонецЕсли;
КонецЦикла;
Важно помнить, что у любого элемента формы есть два ключевых свойства, которые новички часто путают:
Элементы. Используется только для программного доступа. Не может содержать пробелов и спецсимволов.Если вам нужно, чтобы на форме отображался номер группы, меняйте именно Заголовок. Имя же формируйте максимально простым для программной сборки.
Так как все созданные кнопки ссылаются на одно действие (процедуру), нам нужно понимать, какая именно кнопка была нажата. Посмотрим на пример обработчика:
&НаКлиенте
Процедура Подключаемый_ДинамическаяКнопкаНажатие(Команда)
// Извлекаем имя команды
ИмяКоманды = Команда.Имя; // Например, "КнопкаСудно_00001"
// Получаем код судна, отсекая префикс
КодОбъекта = СтрЗаменить(ИмяКоманды, "КнопкаСудно_", "");
// Выполняем полезное действие, например, открываем карточку
ПоказатьОповещениеПользователя("Выбрано судно с кодом: " + КодОбъекта);
КонецПроцедуры
Процесс создания динамических элементов должен происходить на сервере, как правило, в процедуре ПриСозданииНаСервере. Помните, что если вы планируете перерисовывать кнопки в процессе работы формы (например, при изменении каких-то фильтров), то перед повторным созданием старые элементы нужно удалить из коллекции Элементы и Команды, иначе система выдаст ошибку неуникальности имени.
Для удаления элементов используйте метод Элементы.Удалить(ИскомыйЭлемент). При этом удалять элементы нужно в обратном порядке: сначала кнопки, затем их родительские группы.
Таким образом, использование квадратных скобок для доступа к коллекции Элементы[Имя] в сочетании с правильным форматированием индекса позволяет гибко управлять интерфейсом 1С, создавая сложные динамические панели управления.