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

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

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

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

Почему строки не выводятся на форму автоматически?

Главная причина кроется в клиент-серверной архитектуре управляемых форм 1С. Объект встроенного языка ТаблицаЗначений может существовать только на сервере. Управляемая форма не умеет напрямую работать с этим типом для отображения данных пользователю.

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

Решение проблемы: загрузка данных в реквизит формы

Чтобы строки появились в интерфейсе, воспользуемся методом копирования данных. Рассмотрим два основных способа, как это можно сделать.

  1. Использование метода Загрузить() соответствующего реквизита формы:

// Предположим, мы программно создали реквизит формы с именем "Список"
ЭтаФорма.Список.Загрузить(ТЗ);
  1. Использование глобального метода ЗначениеВРеквизитФормы(), который напрямую сериализует серверный объект в данные формы:

ЗначениеВРеквизитФормы(ТЗ, "Список");

После вызова любого из этих методов все строки, которые мы заботливо добавили в серверную таблицу ТЗ, отобразятся на форме.

Оптимизация программного создания реквизитов

Посмотрим на пример кода автора темы. В нем метод ИзменитьРеквизиты() вызывается дважды:


ИзменитьРеквизиты(МассивТаблицыЗначений);
// ... цикл по добавлению колонок в массив ...
ИзменитьРеквизиты(МассивРеквизитов);

Проанализируем эту ситуацию. Использовать ИзменитьРеквизиты() несколько раз в одной процедуре — крайне плохая практика. Каждый вызов этого метода заставляет платформу полностью перестраивать внутреннее дерево реквизитов формы и сбрасывать кэши. Множественные вызовы приводят к существенному замедлению работы (особенно при большом количестве колонок) и могут вызывать мерцание интерфейса.

Правильный подход: формировать единый массив для добавления. Сначала добавляем в него саму таблицу (как корневой реквизит), а затем в цикле — все ее колонки, указывая третьим параметром конструктора РеквизитФормы имя корневого реквизита. После этого вызываем метод ровно один раз:


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

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

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

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

Обработка повторного вызова алгоритма и очистка формы

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

Для предотвращения этой ошибки необходимо удалять старые колонки и элементы интерфейса перед созданием новых. Подготовим массив удаляемых реквизитов и передадим его вторым параметром:


МассивУдаляемыхРеквизитов = Новый Массив;
// Заполняем массив именами ранее созданных колонок, например: "Список.Цена1", "Список.Цена2"

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

Не забудем также очистить элементы управления на самой форме перед созданием новых полей:


Элементы.Удалить(Элементы["СписокЦена1"]); // Пример удаления старого элемента интерфейса

Тонкости настройки элементов интерфейса

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

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

← На главную