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