1с как получить запрос динамического списка

Устали копаться в коде? Узнайте, как получить запрос динамического списка простым способом. Готовый рецепт для 1С-программистов внутри!

Бесплатная консультация юриста

+7 (800) 302-87-29

Реклама jurik.ru

Динамические списки, один из самых мощных и гибких инструментов платформы 1С:Предприятие 8․3 для отображения данных на управляемых формах․ Их ключевая особенность заключается в том, что итоговый SQL-запрос формируется платформой автоматически на этапе выполнения на основе настроек пользователя (отборы, сортировка, условное оформление) и параметров, заданных разработчиком․

Часто возникает необходимость получить текст этого исполняемого запроса программно: для отладки, для передачи данных во внешние обработки, для программного изменения текста запроса «на лету» или для выполнения сложных алгоритмов обработки данных с учетом текущих пользовательских настроек․


Основные способы получения запроса

В современных версиях платформы (начиная с 8․3․10+) существует два основных подхода к получению текста запроса динамического списка․

Метод ПолучитьИсполняемуюСхемуКомпоновкиДанных (Рекомендуемый)

Это самый правильный и универсальный способ․ Он возвращает объект типа СхемаКомпоновкиДанных, который содержит полную информацию о запросе: текст, параметры, структуру полей, настройки варианта отчета и т․д․ Этот метод учитывает все пользовательские настройки (отборы, сортировку, скрытые колонки), примененные к списку на момент вызова․

Пример получения текста запроса и параметров:

&НаСервере
Функция ПолучитьТекстЗапросаДС(ЭлементДинамическогоСписка)
	// 1․ Получаем исполняемую схему компоновки данных
	СхемаКД = ЭлементДинамическогоСписка․ПолучитьИсполняемуюСхемуКомпоновкиДанных;
	
	// 2․ Получаем компоновщик настроек из схемы
	КомпоновщикНастроек = СхемаКД․КомпоновщикНастроек;
	
	// 3․ Получаем настройки варианта отчета (текущие настройки пользователя + программные)
	НастройкиВарианта = КомпоновщикНастроек․ПолучитьНастройкиВарианта;
	
	// 4․ Формируем текст запроса с учетом настроек
	// Метод Выполнить возвращает объект РезультатКомпоновкиДанных, но нам нужен текст․
	// Для получения чистого текста запроса используем ПроцессорКомпоновкиДанных․
	ПроцессорКД = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКД․Инициализировать(СхемаКД, НастройкиВарианта);
	
	// Текст запроса (поле ТекстЗапроса содержит готовый SQL-подобный текст для СКД)
	ТекстЗапроса = ПроцессорКД․ТекстЗапроса;
		// Параметры запроса (структура)
	ПараметрыЗапроса = ПроцессорКД․ПараметрыЗапроса;
	
	Возвратить Новый Структура("ТекстЗапроса, ПараметрыЗапроса", ТекстЗапроса, ПараметрыЗапроса);
КонецФункции

Важно: Метод ПолучитьИсполняемуюСхемуКомпоновкиДанных доступен только на сервере (в процедурах с директивой &НаСервере или &НаСервереБезКонтекста)․ На клиенте он не существует․

Свойство ТекстЗапроса (Для произвольных запросов)

Если в свойствах динамического списка установлен флаг «Произвольный запрос», то у элемента формы (и у соответствующего реквизита формы) появляется свойство ТекстЗапроса․

  • Чтение: Возвращает текст запроса, заданный разработчиком в конфигураторе или измененный программно до применения настроек пользователя (без учета отборов, сортировки, полей СКД)․
  • Запись: Позволяет полностью заменить текст запроса программно․

Пример программного изменения произвольного запроса:

&НаКлиенте
Процедура ЦФУПриИзменении(Элемент)
	Если ЗначениеЗаполнено(ЦФУ) Тогда
		// Устанавливаем новый текст запроса с фильтром
		Элементы․Список․ТекстЗапроса = ПолучитьТекстЗапросаСФильтром;
		// Передаем параметр в запрос
		Элементы․Список․Параметры․УстановитьЗначениеПараметра("ЦФУ", ЦФУ);
	Иначе
		// Возвращаем типовой запрос
		Элементы․Список․ТекстЗапроса = ПолучитьТиповойТекстЗапроса;
	КонецЕсли;
	
	// Обязательно обновляем отображение данных
	Элементы․Список․Обновить;
	ОбновитьОтображениеДанных;
КонецПроцедуры

Программное создание динамического списка

Иногда требуется создать динамический список полностью в коде (например, в универсальных обработках или отчетах)․ Для этого используется процедура работы с реквизитами формы и элементами управления․

Пример создания ДС на сервере:

&НаСервере
Процедура СозданиеДинамическогоСписка(
		ИмяДинамичСписка, // Строка ⸺ имя реквизита и элемента на форме
		ТекстЗапроса, // Строка ⏤ текст запроса (если не указан, нужна ОсновнаяТаблица)
		МассивКолонокДС, // Массив строк ⸺ имена колонок для табличного поля
		ТаблицаСписка = "", // Строка ⸺ имя основной таблицы (если запрос не задан)
		ПараметрыЗапроса = Неопределено // Структура ⏤ параметры запроса
	)
	
	// 1․ Создаем реквизит формы типа ДинамическийСписок
	РеквизитФормы = РеквизитыФормы․Добавить(ИмяДинамичСписка, Новый ОписаниеТипов("ДинамическийСписок"));
	
	// 2․ Настраиваем реквизит
	ДС = РеквизитФормы․Значение; // Получаем объект ДинамическийСписок
	ДС․ПроизвольныйЗапрос = Истина;
	ДС․ТекстЗапроса = ТекстЗапроса;
	
	Если ПараметрыЗапроса <> Неопределено Тогда
		Для Каждого КлючЗначение Из ПараметрыЗапроса Цикл
			ДС․Параметры․УстановитьЗначениеПараметра(КлючЗначение․Ключ, КлючЗначение․Значение);
		КонецЦикла;
	КонецЕсли;
	
	// 3․ Создаем элемент формы (ТабличноеПоле) и привязываем к реквизиту
	ЭлементФормы = ЭлементыФормы․Добавить(ИмяДинамичСписка, Тип("ТабличноеПолеФормы"), ЭлементыФормы․ОбластьФормы);
	ЭлементФормы․ПутьКДанным = ИмяДинамичСписка;
	ЭлементФормы․АвтоЗаголовок = Истина;
	
	// 4․ Создаем колонки программно
	Для Каждого ИмяКолонки Из МассивКолонокДС Цикл
		Колонка = ЭлементФормы․Колонки․Добавить(ИмяКолонки, Тип("ПолеТабличногоПоляФормы"));
		Колонка․ПутьКДанным = ИмяКолонки;
		Колонка․Заголовок = ИмяКолонки; // Можно сделать красивее через Метаданные
	КонецЦикла;
	
	// 5․ Обновляем форму (если нужно сразу показать)
	// ИзменениеРеквизита(ИмяДинамичСписка); // Вызов на клиенте после возврата с сервера
КонецПроцедуры

Отладка и анализ запроса динамического списка

Для диагностики производительности и правильности формирования запроса полезно выводить итоговый текст запроса и его параметры в консоль или в сообщения пользователю․

Универсальная функция отладки (Сервер):

&НаСервере
Функция ЗапросДинамическогоСпискаВТекст(ЭлементДС) Экспорт
	Попытка
		СхемаКД = ЭлементДС․ПолучитьИсполняемуюСхемуКомпоновкиДанных;
		ПроцессорКД = Новый ПроцессорКомпоновкиДанных;
		ПроцессорКД․Инициализировать(СхемаКД, СхемаКД․КомпоновщикНастроек․ПолучитьНастройкиВарианта);
		
		Результат = Новый Структура;
		Результат․Вставить("ТекстЗапроса", ПроцессорКД․ТекстЗапроса);
		Результат․Вставить("Параметры", ПроцессорКД․ПараметрыЗапроса);
		Результат․Вставить("СхемаКД", СхемаКД); // Для глубокой отладки
		
		Возвратить Результат;
	Исключение
		Возвратить Новый Структура("Ошибка", ОписаниеОшибки);
	КонецПопытки;
КонецФункции

Вызов из клиента (для кнопки «Показать запрос»):

&НаКлиенте
Процедура ПоказатьЗапросДСКоманда(Команда)
	Результат = ЗапросДинамическогоСпискаВТекстНаСервере(Элементы․СписокДокументов);
	
	Если Результат․Свойство("Ошибка") Тогда
		Сообщить("Ошибка получения запроса: " + Результат․Ошибка);
		Возврат;
	КонецЕсли;
		ПоказатьВопрос(Новый ОписаниеОповещения("ОбработатьТекстЗапроса", ЭтотОбъект), 
		"Текст запроса ДС:", Результат․ТекстЗапроса, РежимДиалогаВводаСтроки․Многострочный);
		
	// Параметры можно вывести отдельно
	Если Результат․Параметры․Количество > 0 Тогда
		СтрПарам = "";
		Для Каждого П Из Результат․Параметры Цикл
			СтрПарам = СтрПарам + П․Ключ + " = " + Строка(П․Значение) + Символы․ПС;
		КонецЦикла;
		Сообщить("Параметры:" + Символы․ПС + СтрПарам);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьТекстЗапроса(РезультатВвода, ДопПараметры) Экспорт
	// Просто закрываем диалог, текст уже показан
КонецПроцедуры

Работа с данными динамического списка (Выгрузка с учетом отборов)

Частая задача: получить данные, которые видит пользователь (с учетом его отборов и сортировки), в ТаблицуЗначений для дальнейшей обработки (например, массовое изменение, печать, экспорт)․

Правильный способ через ПроцессорКомпоновкиДанных:

&НаСервере
Функция ПолучитьДанныеДСВТаблицуЗначений(ЭлементДС)
	СхемаКД = ЭлементДС․ПолучитьИсполняемуюСхемуКомпоновкиДанных;
	НастройкиВарианта = СхемаКД․КомпоновщикНастроек․ПолучитьНастройкиВарианта;
	
	ПроцессорКД = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКД․Инициализировать(СхемаКД, НастройкиВарианта);
	
	// Выполняем компоновку в табличный документ, а потом выгружаем в ТЗ
	// Но эффективнее: ПроцессорКД позволяет получить набор данных напрямую
	// Однако стандартный способ ⸺ через ТабличныйДокумент или РезультатКомпоновкиДанных
	
	РезультатКД = ПроцессорКД․Выполнить;
	
	// Преобразуем результат в ТаблицуЗначений
	// Для этого удобно использовать вывод в ТабличныйДокумент, а потом ТД․Выгрузить
	// Или, если нужно просто прочитать строки:
	ТаблицаРезультат = Новый ТаблицаЗначений;
	
	// Добавляем колонки согласно схеме
	Для Каждого Поле Из СхемаКД․НаборыДанных[0]․Поля Цикл
		ТаблицаРезультат․Колонки․Добавить(Поле․Имя, Поле․ТипЗначения);
	КонецЦикла;
	
	// Обход результата (иерархический!)
	// Простой обход только строк верхнего уровня:
	ОбластьДанных = РезультатКД․ОбластьДанных;
	Пока ОбластьДанных․Следующий Цикл
		СтрокаТЗ = ТаблицаРезультат․Добавить;
		Для Каждого Поле Из СхемаКД․НаборыДанных[0]․Поля Цикл
			СтрокаТЗ[Поле․Имя] = ОбластьДанных[Поле․Имя];
		КонецЦикла;
	КонецЦикла;
		
	Возвратить ТаблицаРезультат;
КонецФункции

Совет: Если вам нужна просто таблица строк без иерархии, убедитесь, что в настройках варианта отчета (или программно) отключена иерархия или используйте набор данных «Список» (а не «Дерево»)․


Типичные ошибки и лучшие практики

  1. Вызов ПолучитьИсполняемуюСхемуКомпоновкиДанных на клиенте․ Этот метод работает только на сервере․ Всегда оборачивайте вызов в &НаСервере функцию․
  2. Игнорирование параметров запроса․ При ручном выполнении запроса (через объект Запрос) разработчики часто забывают передать параметры, которые платформа подставляет автоматически (например, параметры отборов пользователя, права доступа RLS)․ Использование ПроцессорКомпоновкиДанных решает эту проблему автоматически․
  3. Сложные запросы в свойстве «Произвольный запрос»․ Старайтесь делать запросы простыми․ Сложная логика (вложенные подзапросы, множественные JOIN) затрудняет работу СКД по добавлению полей, отборов и сортировок․ Лучше оптимизировать архитектуру хранения данных (регистры накопления, информационные регистры, материализованные представления)․
  4. Несвоевременное обновление․ После программного изменения ТекстЗапроса или параметров обязательно вызывайте Элемент․Обновить и/или ОбновитьОтображениеДанных․
  5. Путаница между «ТекстЗапроса» (реквизит/элемент) и «Исполняемым запросом»․ Свойство ТекстЗапроса — это «сырой» шаблон․ Исполняемый запрос — это результат работы СКД с учетом всех настроек․ Для отладки и выгрузки данных всегда используйте исполняемую схему․

Резюме: что выбрать?

Задача Инструмент Контекст
Получить итоговый SQL с учетом отборов пользователя для отладки/логирования ПолучитьИсполняемуюСхемуКомпоновкиДанных + ПроцессорКомпоновкиДанных Только Сервер
Получить данные (ТаблицаЗначений) с учетом отборов пользователя ПроцессорКомпоновкиДанных․Выполнить + обход области данных Только Сервер
Программно изменить/подставить запрос (режим «Произвольный запрос») Свойство Элемент․ТекстЗапроса + Элемент․Параметры Клиент / Сервер
Создать ДС полностью в коде Создание реквизита ДинамическийСписок + элемента ТабличноеПоле Сервер (инициализация)
Прочитать заданный разработчиком текст запроса (без настроек пользователя) Элемент․ТекстЗапроса (или Реквизит․ТекстЗапроса) Клиент / Сервер

Понимание разницы между «шаблоном запроса» (ТекстЗапроса) и «исполняемым запросом» (результат работы СКД), ключ к эффективной работе с динамическими списками в 1С․ Используйте инструменты платформы (ПроцессорКомпоновкиДанных) для получения готовых результатов, а не пытайтесь парсить и собирать SQL-строки вручную․