Как вывести одну номенклатуру в нескольких группах прайс-листа в 1С

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При формировании прайс-листов в конфигурации «Управление торговлей 10.3» часто возникает задача отобразить один и тот же товар сразу в нескольких разделах. Например, товар может относиться к основной группе по иерархии справочника, но также должен дублироваться в категории «Акционные предложения» или «Новинки», определяемые через дополнительные свойства или категории.

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

Метод 1. Дублирование строк на уровне запроса (UNION ALL)

Проанализируем самый производительный и правильный с точки зрения архитектуры 1С подход. Вместо того чтобы пытаться программно «вклинивать» строки в процессе вывода в таблицу, мы подготовим данные в самом запросе так, чтобы одна номенклатура физически присутствовала в нескольких строках с разными родителями.

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


ВЫБРАТЬ
    Номенклатура.Родитель КАК ГруппаПрайса,
    Номенклатура.Ссылка КАК Товар,
    Номенклатура.Цена КАК Цена
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    НЕ Номенклатура.ЭтоГруппа

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Номенклатура.ДополнительноеСвойствоГруппа.Значение КАК ГруппаПрайса,
    Номенклатура.Ссылка КАК Товар,
    Номенклатура.Цена КАК Цена
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    НЕ Номенклатура.ЭтоГруппа
    И Номенклатура.ДополнительноеСвойствоГруппа.Значение <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)

В данном случае оператор ОБЪЕДИНИТЬ ВСЕ создает плоскую таблицу, где один и тот же товар имеет две разные привязки к полю ГруппаПрайса. После этого достаточно выполнить обход по группировкам, и система автоматически выведет товар во все нужные разделы без сложной логики в коде 1С.

Метод 2. Использование временных таблиц для связей

Если логика распределения товаров по группам сложная (например, товар должен попадать во все группы, указанные в регистре сведений), мы можем использовать механизм временных таблиц. Рассмотрим этот процесс по шагам:

  1. Создаем временную таблицу ВТ_СвязиНоменклатуры, в которой хранятся пары «Группа — Номенклатура».
  2. В эту таблицу помещаем данные из иерархии и данные из всех дополнительных источников.
  3. Соединяем основную таблицу с ценами и остатками с этой временной таблицей.
  4. Группируем результат по полю «Группа» из временной таблицы.

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

Метод 3. Работа с Таблицей Значений вместо Выборки

Выясним причину, по которой у автора возникли сложности с методом НайтиСледующий(). Выборка — это однонаправленный поток данных. Чтобы иметь возможность свободно искать данные и не терять позицию, лучше выгрузить результат запроса в объект ТаблицаЗначений.

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


Результат = Запрос.Выполнить();
ТаблицаДанных = Результат.Выгрузить();

// Допустим, мы итерируемся по списку групп
Для Каждого СтрокаГруппы Из СписокГрупп Цикл
    // Выводим заголовок группы в макет
    
    // Ищем все товары для этой группы в общей таблице
    ПараметрыОтбора = Новый Структура("ГруппаПрайса", СтрокаГруппы.Ссылка);
    НайденныеСтроки = ТаблицаДанных.НайтиСтроки(ПараметрыОтбора);
    
    Для Каждого СтрокаТовара Из НайденныеСтроки Цикл
        // Выводим товар. Индекс основного цикла не сбивается.
    КонецЦикла;
КонецЦикла;

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

Метод 4. Клонирование выборки (две независимые выборки)

Если вы по каким-то причинам не хотите выгружать результат в таблицу (например, из-за огромного объема данных), можно создать две независимые выборки из одного и того же результата запроса. Это позволит одной выборке отвечать за основной цикл, а второй — за поиск дополнительных позиций.


РезультатЗапроса = Запрос.Выполнить();
ВыборкаОсновная = РезультатЗапроса.Выбрать();
ВыборкаПоиска = РезультатЗапроса.Выбрать();

Пока ВыборкаОсновная.Следующий() Цикл
    // Основной вывод
    // ...
    
    // Если нужно найти что-то дополнительно, используем вторую выборку
    Если НужноВывестиДопТовар Тогда
        Если ВыборкаПоиска.НайтиСледующий(Новый Структура("Код", "001")) Тогда
            // Выводим доп. товар
        КонецЕсли;
        // После НайтиСледующий выборкаПоиска изменила состояние, 
        // но ВыборкаОсновная осталась на своем месте!
        ВыборкаПоиска.Сбросить(); 
    КонецЕсли;
КонецЦикла;

Важно помнить, что метод Сбросить() возвращает выборку в начало. В данном контексте это безопасно для ВыборкаПоиска, так как она используется только для точечных поисков внутри итерации основной выборки.

Метод 5. Особенности использования Построителя отчета в УТ 10.3

Поскольку в типовой конфигурации УТ 10.3 прайсы часто строятся на ПостроительОтчета, мы можем решить задачу через настройки компоновки. Рассмотрим подробнее: в построителе можно добавить дополнительные поля в «Доступные поля». Если добавить туда свойство номенклатуры как отдельное поле и разрешить по нему группировку, пользователь сможет самостоятельно формировать отчет так, что товары будут группироваться по логическим категориям, а не по папкам справочника.

Резюмируем: наиболее эффективным и «чистым» способом является модификация запроса через ОБЪЕДИНИТЬ ВСЕ. Это избавляет от необходимости писать сложную логику обхода в коде, исключает ошибки с позиционированием курсора выборки и позволяет использовать стандартные механизмы вывода отчетов в 1С. Если же требуется сложная программная обработка, использование ТаблицыЗначений с индексацией будет более предпочтительным вариантом, чем манипуляции с Выборка.НайтиСледующий().

← На главную