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