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

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

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

Ключевое различие: ТаблицаЗначений и Реквизит формы

Чтобы понять причину проблемы, нужно уяснить фундаментальное различие между двумя объектами, которые оба могут называться "таблицей".

1. Объект ТаблицаЗначений

Когда вы пишете код ТЗ = Новый ТаблицаЗначений;, вы создаете универсальный объект встроенного языка для хранения и обработки данных в памяти. Это мощный инструмент для вычислений, хранения результатов запросов, обмена данными. Однако, как справедливо было отмечено в обсуждении, у этого объекта есть важное ограничение по доступности.

В документации (Синтакс-Помощнике) указана его доступность:

Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер).

Ключевой момент: в списке отсутствует тонкий и веб-клиент, на которых и работают управляемые формы. Это означает, что объект ТаблицаЗначений — это исключительно серверный или "толстый" объект. Он не имеет визуального представления и не может быть напрямую отображен на управляемой форме.

2. Реквизит формы и Элемент формы

Архитектура управляемых форм четко разделяет данные и их визуальное представление.

Связь между ними устанавливается через свойство элемента ПутьКДанным, которое указывает на имя реквизита формы. Именно этот механизм и нужно использовать.

Пошаговый алгоритм вывода динамической таблицы на форму

Теперь, когда мы разобрались с теорией, перейдем к практике. Основная сложность, с которой столкнулся автор темы, — это динамическое количество колонок. Если бы колонки были известны заранее, мы бы просто создали реквизит в конфигураторе. Но в нашем случае структуру таблицы нужно формировать программно.

Важно: все операции по изменению структуры реквизитов формы и созданию элементов должны выполняться на сервере, например, в процедуре с директивой &НаСервере.

Шаг 1. Подготовка данных в ТаблицеЗначений (если необходимо)

Начнем с того, что у нас есть некие данные, полученные, например, из запроса или путем расчетов. Они, как правило, хранятся в обычной ТаблицеЗначений. Этот шаг остается неизменным — сначала готовим данные на сервере.


// Пример серверной процедуры
&НаСервере
Процедура СформироватьИВывестиТаблицуНаСервере()

    // 1. Создаем и заполняем исходную ТаблицуЗначений
    ИсходнаяТЗ = Новый ТаблицаЗначений;
    ИсходнаяТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    ИсходнаяТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(10, 3)));
    ИсходнаяТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(15, 2)));

    // ... здесь код заполнения ИсходнаяТЗ данными ...
    
КонецПроцедуры

Шаг 2. Программное создание реквизита формы

Это ключевой шаг для решения проблемы с динамическими колонками. Нам нужно "сообщить" форме, что у нее появился новый реквизит с нужной нам структурой. Для этого используется метод формы ИзменитьРеквизиты().

  1. Создаем массив для новых реквизитов.
  2. Для каждого нового реквизита создаем объект РеквизитФормы, указывая его имя, тип (в нашем случае ТаблицаЗначений, платформа сама преобразует его в ДанныеФормыКоллекция) и заголовок.
  3. Для реквизита-таблицы нужно описать его колонки. Создаем массив колонок и для каждой колонки также создаем объект РеквизитФормы с указанием имени, типа и заголовка.
  4. Вызываем метод ИзменитьРеквизиты(), передавая в него массив с новыми реквизитами.

Посмотрим на пример кода, продолжающий предыдущий:


// 2. Программно создаем реквизит формы
ИмяРеквизита = "МояДинамическаяТаблица";

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

// Описываем сам реквизит-таблицу
РеквизитТаблица = Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("ТаблицаЗначений"), "", "Моя таблица");

// Описываем колонки реквизита-таблицы
Для Каждого Колонка Из ИсходнаяТЗ.Колонки Цикл
    НоваяКолонкаРеквизита = Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, ИмяРеквизита, Колонка.Имя);
    РеквизитТаблица.Реквизиты.Добавить(НоваяКолонкаРеквизита);
КонецЦикла;

МассивДобавляемыхРеквизитов.Добавить(РеквизитТаблица);

// Вызываем метод изменения реквизитов
ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);

Шаг 3. Перенос данных в новый реквизит

После того как реквизит создан, он пуст. Нам нужно перенести в него данные из нашей серверной ТаблицыЗначений. Для этого существует удобная функция ЗначениеВДанныеФормы().


// 3. Копируем данные из ТЗ в новый реквизит формы
ЗначениеВДанныеФормы(ИсходнаяТЗ, ЭтотОбъект[ИмяРеквизита]);

Теперь данные находятся в форме, но мы их все еще не видим. Остался последний шаг.

Шаг 4. Создание визуального элемента ТаблицаФормы

Теперь создадим визуальный элемент и свяжем его с нашим реквизитом. Здесь автор темы допускал ошибку, пытаясь передать объект данных в качестве родителя. Правильно — указывать родительский элемент формы (например, саму форму ЭтаФорма или группу элементов).

Используем метод Элементы.Добавить().


// 4. Создаем визуальный элемент на форме
ИмяЭлемента = "ТаблицаНаФорме";
    
// Перед добавлением нового элемента стоит удалить старый, если он есть
// Это полезно, если процедура может вызываться многократно
Если Элементы.Найти(ИмяЭлемента) <> Неопределено Тогда
    Элементы.Удалить(Элементы[ИмяЭлемента]);
КонецЕсли;

// Добавляем саму таблицу
ЭлементТаблица = Элементы.Добавить(ИмяЭлемента, Тип("ТаблицаФормы"), ЭтаФорма);
ЭлементТаблица.ПутьКДанным = ИмяРеквизита; // Связываем элемент с данными!

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

Обратите внимание на свойство ПутьКДанным. Для самой таблицы мы указываем имя реквизита ("МояДинамическаяТаблица"), а для каждой ее колонки — путь через точку ("МояДинамическаяТаблица.Номенклатура"). Это и есть та самая магия, которая связывает визуальное представление с данными формы.

После выполнения этого кода на форме появится таблица с нужными колонками и данными.

Итог

Чтобы программно вывести таблицу на управляемую форму, особенно с динамическим набором колонок, всегда следуйте этому алгоритму:

  1. (На сервере) Подготовьте данные в объекте ТаблицаЗначений.
  2. (На сервере) С помощью ИзменитьРеквизиты() создайте на форме новый реквизит с необходимой структурой колонок.
  3. (На сервере) Перенесите данные из ТаблицыЗначений в новый реквизит с помощью ЗначениеВДанныеФормы().
  4. (На сервере) С помощью Элементы.Добавить() создайте визуальный элемент ТаблицаФормы и его дочерние элементы-колонки, правильно указав для каждого свойство ПутьКДанным.

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

← На главную