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