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