Как найти и подменить элементы справочника по коду в запросе СКД

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет Финансы и профессиональные услуги
← На главную

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

Способ 1. Использование строковых функций в тексте запроса

Самый прямой путь — это преобразование кода справочника непосредственно в тексте запроса. Если мы знаем структуру кода, мы можем «вырезать» нужные части и собрать из них шаблон, по которому затем присоединим нужный нам «эталонный» элемент. Проанализируем пример, где код состоит из 5 символов, и нам нужно заменить 3-й и 4-й символы на нули.

Для этого в языке запросов используется функция ПОДСТРОКА. Разберем пример реализации через ЛЕВОЕ СОЕДИНЕНИЕ:


ВЫБРАТЬ
    Продажи.Номенклатура КАК ИсходнаяНоменклатура,
    Продажи.Количество КАК Количество,
    ЕСТЬNULL(СпрШаблон.Ссылка, Продажи.Номенклатура) КАК НоменклатураПоШаблону
ИЗ
    РегистрНакопления.Продажи КАК Продажи
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрШаблон
        ПО (ПОДСТРОКА(Продажи.Номенклатура.Код, 1, 2) + "00" + ПОДСТРОКА(Продажи.Номенклатура.Код, 5, 1)) = СпрШаблон.Код

Важный нюанс: использование функций обработки строк в условии соединения (JOIN) крайне негативно сказывается на производительности. База данных (SQL) не может использовать индексы по полю Код, что приведет к полному сканированию таблицы. Если в вашем отчете тысячи или десятки тысяч строк, такой отчет будет «тормозить».

Способ 2. Вычисляемые поля и внешние функции СКД

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

  1. Создайте в общем модуле (с флагом «Вызов сервера») функцию, которая принимает исходную ссылку и возвращает найденную по шаблону.
  2. В схеме компоновки данных на закладке «Вычисляемые поля» добавьте новое поле.
  3. В колонке «Выражение» пропишите вызов вашей функции: МойОбщийМодуль.НайтиНоменклатуруПоШаблону(Номенклатура).

Этот метод позволяет использовать всю мощь объектной модели 1С, включая метод НайтиПоКоду(), который недоступен в самом запросе. Однако помните, что функция будет вызываться для каждой строки результата, что также может замедлить формирование отчета при больших объемах данных.

Способ 3. Создание промежуточной временной таблицы (Оптимальный)

Чтобы избежать проблем с производительностью и сохранить возможность группировки в СКД, проанализируем наиболее профессиональный подход. Мы можем подготовить таблицу соответствий «Старый код — Новый элемент» во временной таблице.


// Сначала выбираем все уникальные КПС/Товары, которые участвуют в отчете
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ХозрасчетныйОстатки.Субконто1 КАК ИсходныйЭлемент,
    ПОДСТРОКА(ХозрасчетныйОстатки.Субконто1.Код, 1, 2) + "00" + ПОДСТРОКА(ХозрасчетныйОстатки.Субконто1.Код, 5, 1) КАК СформированныйКод
ПОМЕСТИТЬ ВТ_Коды
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки КАК ХозрасчетныйОстатки
;

// Затем соединяем их со справочником один раз
ВЫБРАТЬ
    ВТ_Коды.ИсходныйЭлемент,
    Справочник.Ссылка КАК ЦелевойЭлемент
ПОМЕСТИТЬ ВТ_Соответствие
ИЗ
    ВТ_Коды КАК ВТ_Коды
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Справочник
        ПО ВТ_Коды.СформированныйКод = Справочник.Код
;

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

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

Особенности работы с типовыми отчетами (БГУ) и Конструктором запросов

Часто программисты сталкиваются с тем, что после внесения изменений в запрос типового отчета (например, «Журнал операций» или «Оборотно-сальдовая ведомость»), отчет перестает работать с ошибкой «Поле не найдено». Выясним причину.

Типовые отчеты 1С часто содержат в тексте запроса специальные комментарии-маркеры, например:

Внимание: Если вы откроете такой запрос через «Конструктор запроса» и нажмете «ОК», конструктор автоматически удалит эти комментарии. Программный код отчета, который ищет эти метки для динамической подстановки условий (например, фильтра по организации или периоду), не сможет выполнить замену, и структура запроса «развалится».

Рекомендация: Редактируйте запросы в таких отчетах вручную в текстовом окне, либо копируйте запрос в текстовый редактор перед использованием конструктора, чтобы потом вручную вернуть все служебные комментарии на свои места.

Способ 4. Программная обработка результата через Таблицу Значений

Если задача стоит крайне остро и нужно «вклиниться» в отчет, который формируется сложным программным путем, можно перехватить результат компоновки. Посмотрим на алгоритм:

  1. В модуле отчета в процедуре ПриКомпоновкеРезультата (или перед ней) выполните запрос стандартным образом.
  2. Выгрузите результат в ТаблицаЗначений.
  3. Запустите цикл по таблице и для каждой строки найдите нужный элемент справочника по коду через Справочники.Номенклатура.НайтиПоКоду(...).
  4. Замените значение в колонке.
  5. Передайте модифицированную таблицу обратно в СКД в качестве внешнего набора данных.

Этот метод самый трудозатратный в плане кодинга, но он дает 100% гарантию того, что вы сможете подменить любые данные, даже если логика шаблона очень сложная и не описывается простым запросом.

Подведем итог: Для простых задач используйте ПОДСТРОКА в вычисляемых полях, для производительных решений — временные таблицы с индексами, а при работе с типовыми отчетами БГУ будьте предельно осторожны с конструктором запросов, чтобы не затереть служебные маркеры системы.

← На главную