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