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