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