Как правильно получить несколько дополнительных реквизитов объекта в запросе 1С и вывести их в отчет?

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

При разработке отчетов и печатных форм часто возникает задача вывести значения нескольких дополнительных реквизитов для одного объекта (например, для справочника Должности или Сотрудники). В процессе решения начинающие разработчики сталкиваются с рядом типичных ошибок: попыткой модификации выборки запроса, выполнением запросов внутри цикла, эффектом «залипания» данных в макете и неправильным использованием левых соединений. Разберем по шагам эти проблемы и рассмотрим оптимальные варианты построения запроса.

Анализ частых ошибок при работе с дополнительными реквизитами

Проанализируем основные неточности, возникающие при попытке извлечь и отобразить свойства объектов:

  1. Попытка присвоения значения полю выборки. Конструкция вида Выборка.Свойство = ПланыВидовХарактеристик... приводит к исключению «Поле объекта недоступно для записи». Объект ВыборкаИзРезультатаЗапроса предназначен исключительно для чтения данных.
  2. Выполнение запроса в цикле. Получение дополнительных реквизитов отдельным запросом на каждой итерации обхода основного списка объектов резко снижает производительность системы и создает избыточную нагрузку на СУБД (проблема N+1).
  3. «Залипание» значений в макете табличного документа. Если область макета получена один раз до входа в цикл, ее параметры не очищаются автоматически на следующей итерации. Если для текущей строки значение доп. реквизита не найдено, в отчет попадает значение из предыдущей строки.
  4. Превращение левого соединения во внутреннее. При попытке связать табличную часть ДополнительныеРеквизиты через ЛЕВОЕ СОЕДИНЕНИЕ и указании отбора по свойству в секции ГДЕ, строки с незаполненными реквизитами полностью исключаются из итоговой выборки.

Способ 1. Получение реквизитов через множественные левые соединения

Рассмотрим классический способ получения нескольких реквизитов в одном запросе. Чтобы объекты с незаполненными дополнительными реквизитами не выпадали из отчета, условие по конкретному свойству обязательно указывается в секции ПО, а не в секции ГДЕ.

Посмотрим на пример формирования запроса и передачи параметров:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	КадровыеДанные.Сотрудник КАК Сотрудник,
|	КадровыеДанные.Должность КАК Должность,
|	ЕСТЬNULL(ДопРекНазвание.Значение, """") КАК Название,
|	ЕСТЬNULL(ДопРекФакторы.Значение, """") КАК Факторы,
|	ЕСТЬNULL(ДопРекПериодичность.Значение, """") КАК Периодичность
|ИЗ
|	РегистрСведений.КадровыеСведения.СрезПоследних(&Период, Организация = &Организация) КАК КадровыеДанные
|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Должности.ДополнительныеРеквизиты КАК ДопРекНазвание
|		ПО (КадровыеДанные.Должность = ДопРекНазвание.Ссылка)
|		И (ДопРекНазвание.Свойство = &СвойствоНазвание)
|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Должности.ДополнительныеРеквизиты КАК ДопРекФакторы
|		ПО (КадровыеДанные.Должность = ДопРекФакторы.Ссылка)
|		И (ДопРекФакторы.Свойство = &СвойствоФакторы)
|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Должности.ДополнительныеРеквизиты КАК ДопРекПериодичность
|		ПО (КадровыеДанные.Должность = ДопРекПериодичность.Ссылка)
|		И (ДопРекПериодичность.Свойство = &СвойствоПериодичность)";

Запрос.УстановитьПараметр("Период", КонецДня(ДатаОтчета));
Запрос.УстановитьПараметр("Организация", Организация);

// Устанавливаем ссылки на свойства из плана видов характеристик
Запрос.УстановитьПараметр("СвойствоНазвание", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Название (Должности)"));
Запрос.УстановитьПараметр("СвойствоФакторы", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Факторы (Должности)"));
Запрос.УстановитьПараметр("СвойствоПериодичность", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Периодичность (Должности)"));

РезультатЗапроса = Запрос.Выполнить();

Способ 2. Разворот строк в колонки через агрегацию (ВЫБОР КОГДА)

Когда требуется выбрать большое количество дополнительных реквизитов, множество левых соединений с одной и той же табличной частью может усложнить план запроса. В таких случаях эффективнее объединить реквизиты через одно соединение с группировкой и условной агрегацией МАКСИМУМ(ВЫБОР...).

Разберем структуру такого запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	Должности.Ссылка КАК Должность,
|	МАКСИМУМ(ВЫБОР 
|		КОГДА ДопРек.Свойство = &СвойствоНазвание ТОГДА ДопРек.Значение 
|		ИНАЧЕ НЕОПРЕДЕЛЕНО 
|	КОНЕЦ) КАК Название,
|	МАКСИМУМ(ВЫБОР 
|		КОГДА ДопРек.Свойство = &СвойствоФакторы ТОГДА ДопРек.Значение 
|		ИНАЧЕ НЕОПРЕДЕЛЕНО 
|	КОНЕЦ) КАК Факторы,
|	МАКСИМУМ(ВЫБОР 
|		КОГДА ДопРек.Свойство = &СвойствоПериодичность ТОГДА ДопРек.Значение 
|		ИНАЧЕ НЕОПРЕДЕЛЕНО 
|	КОНЕЦ) КАК Периодичность
|ИЗ
|	Справочник.Должности КАК Должности
|	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Должности.ДополнительныеРеквизиты КАК ДопРек
|		ПО (Должности.Ссылка = ДопРек.Ссылка)
|		И (ДопРек.Свойство В (&МассивСвойств))
|СГРУППИРОВАТЬ ПО
|	Должности.Ссылка";

МассивСвойств = Новый Массив;
МассивСвойств.Добавить(СвойствоНазвание);
МассивСвойств.Добавить(СвойствоФакторы);
МассивСвойств.Добавить(СвойствоПериодичность);

Запрос.УстановитьПараметр("МассивСвойств", МассивСвойств);
Запрос.УстановитьПараметр("СвойствоНазвание", СвойствоНазвание);
Запрос.УстановитьПараметр("СвойствоФакторы", СвойствоФакторы);
Запрос.УстановитьПараметр("СвойствоПериодичность", СвойствоПериодичность);

Корректный вывод данных в табличный документ

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

Посмотрим на пример правильной организации цикла вывода:


Выборка = Запрос.Выполнить().Выбрать();
НомерСтроки = 1;

Пока Выборка.Следующий() Цикл
	// Получаем чистую область макета для текущей строки
	СекцияСтрока = Макет.ПолучитьОбласть("Строка");
	
	// Заполняем совпадающие параметры напрямую из выборки
	СекцияСтрока.Параметры.Заполнить(Выборка);
	СекцияСтрока.Параметры.НП = НомерСтроки;
	
	// Явно передаем значения дополнительных реквизитов
	СекцияСтрока.Параметры.Название = Выборка.Название;
	СекцияСтрока.Параметры.Факторы = Выборка.Факторы;
	СекцияСтрока.Параметры.Периодичность = Выборка.Периодичность;
	
	ТабДок.Вывести(СекцияСтрока);
	НомерСтроки = НомерСтроки + 1;
КонецЦикла;

Рекомендации по работе с БСП

Если в конфигурации внедрена Библиотека Стандартных Подсистем (БСП), обратите внимание на следующие правила:

  1. Отказ от поиска по наименованию. Метод НайтиПоНаименованию ненадежен, так как пользователи могут переименовать реквизит в режиме предприятия. В БСП для стабильного программного обращения используется реквизит Имя плана видов характеристик ДополнительныеРеквизитыИСведения.
  2. Использование модуля УправлениеСвойствами. Для чтения и записи значений свойств вне сложных аналитических запросов рекомендуется применять стандартные методы общего модуля УправлениеСвойствами, что исключает ошибки прямой работы с табличной частью.
← На главную