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