Как реализовать динамическую таблицу с произвольным количеством колонок на управляемой форме 1С 8.3

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Часто в практике разработчика 1С возникает задача отобразить таблицу, структура которой заранее неизвестна и зависит от внешних условий, например, от выбранного периода дат. В этом случае мы не можем использовать стандартную Табличную часть объекта, так как её состав колонок жестко задан в конфигураторе. Разберем подробно, как решить эту задачу с помощью программного изменения состава реквизитов формы.

Поймем разницу между Табличной частью и Таблицей значений на форме

Проанализируем сначала ключевую ошибку, с которой сталкиваются новички. ТабличнаяЧасть — это объект метаданных. Мы не можем «на лету» добавить в неё колонки в режиме 1С:Предприятие. Для реализации динамики нам необходимо использовать Таблицу значений как реквизит формы.

Рассмотрим стандартную цепочку действий для решения этой задачи:

  1. Создаем на форме «базовый» реквизит с типом ТаблицаЗначений (без колонок).
  2. На сервере рассчитываем необходимое количество колонок.
  3. Программным кодом добавляем колонки в состав реквизитов формы через метод ИзменитьРеквизиты.
  4. Программным кодом создаем элементы формы (визуальные поля), чтобы пользователь увидел эти колонки.
  5. Заполняем таблицу данными.

Шаг 1. Подготовка структуры данных на сервере

Выясним причину, по которой используется метод ИзменитьРеквизиты. На управляемых формах структура данных разделена на Реквизиты (данные в памяти) и Элементы (визуальное отображение). Сначала мы должны изменить структуру данных.

Допустим, у нас есть рассчитанная на сервере ТаблицаЗначений (назовем её ТЗ_Результат), в которой уже есть нужные нам колонки. Рассмотрим, как перенести эту структуру на форму:


// Создадим массив для новых реквизитов
МассивДобавляемыхРеквизитов = Новый Массив;

// Пройдемся циклом по колонкам нашей расчетной таблицы
Для Каждого Колонка Из ТЗ_Результат.Колонки Цикл
    // Формируем описание типа для колонки
    МассивТипов = Новый Массив;
    МассивТипов.Добавить(Колонка.ТипЗначения);
    ОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
    
    // Создаем новый реквизит формы. 
    // "ТЗ" — это имя основного реквизита таблицы на форме
    НовыйРеквизит = Новый РеквизитФормы(Колонка.Имя, ОписаниеТипов, "ТЗ", Колонка.Заголовок);
    МассивДобавляемыхРеквизитов.Добавить(НовыйРеквизит);
КонецЦикла;

// Применяем изменения к форме
ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);

Важный нюанс: метод ИзменитьРеквизиты принимает два параметра: массив добавляемых реквизитов и массив удаляемых реквизитов. Если вы планируете перестраивать таблицу несколько раз (например, при изменении периода), вам необходимо сначала собрать имена старых динамических колонок и передать их во второй параметр, чтобы не возникло ошибки дублирования имен.

Шаг 2. Визуализация колонок на форме

После выполнения кода выше данные в памяти сервера уже имеют новую структуру, но форма всё еще отображает пустую таблицу. Разберем по шагам, как добавить визуальные элементы:


// Получим элемент формы, в который будем добавлять колонки (саму таблицу)
ЭлементТаблица = Элементы.ТЗ;

Для Каждого Колонка Из ТЗ_Результат.Колонки Цикл
    // Добавляем новый элемент формы типа "ПолеФормы"
    // Имя элемента должно быть уникальным, например "ТЗ_" + ИмяКолонки
    ИмяЭлемента = "ТЗ_" + Колонка.Имя;
    НовыйЭлемент = Элементы.Добавить(ИмяЭлемента, Тип("ПолеФормы"), ЭлементТаблица);
    
    // Указываем, что это поле ввода
    НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
    
    // Связываем визуальный элемент с данными реквизита
    // Путь должен включать имя таблицы: "ТЗ.ИмяКолонки"
    НовыйЭлемент.ПутьКДанным = "ТЗ." + Колонка.Имя;
КонецЦикла;

Шаг 3. Загрузка данных в динамическую таблицу

Когда структура и визуальные элементы готовы, остается только загрузить данные. Проанализируем ситуацию: поскольку имена колонок в нашей временной ТаблицеЗначений и в реквизите формы теперь совпадают, мы можем использовать метод ЗначениеВРеквизитФормы.


// Загружаем данные из ТЗ_Результат в реквизит формы с именем "ТЗ"
ЗначениеВРеквизитФормы(ТЗ_Результат, "ТЗ");

Обработка событий в динамических колонках

Рассмотрим ситуацию, когда нам нужно, чтобы при изменении значения в динамической колонке срабатывал какой-то алгоритм. Поскольку колонка создана программно, мы не можем просто выбрать событие в конфигураторе. Выясним, как это сделать кодом:

Для этого используется метод УстановитьДействие. Нам нужно заранее создать процедуру в модуле формы с соответствующей сигнатурой (обычно это НаКлиенте), а затем связать её с элементом формы.


// Пример связывания события ПриИзменении
НовыйЭлемент.УстановитьДействие("ПриИзменении", "ДинамическаяКолонкаПриИзменении");

В самой процедуре ДинамическаяКолонкаПриИзменении мы сможем определить, в какой именно колонке и строке произошло изменение, используя свойства элемента ТекущиеДанные таблицы.

Резюме и практические советы

Проанализировав решение задачи, можно сделать следующие выводы:

Рассмотренный подход позволяет создавать интерфейсы любой сложности: от графиков отпусков и табелей учета времени до сложных матриц распределения затрат, где количество измерений определяется только бизнес-логикой вашей задачи.

← На главную