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