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