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