Как в 1С выбрать номенклатуру с несколькими штрихкодами и вывести без дублирования строк?

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

При решении задач интеграции, сверки справочников или инвентаризации нередко возникает необходимость найти в базе 1С товары, за которыми закреплено более одного штрихкода. Если просто связать справочник Номенклатура и регистр сведений ШтрихкодыНоменклатуры, в итоговой таблице наименование товара продублируется столько раз, сколько кодов зарегистрировано для позиции. Разберем, как правильно составить запрос к базе данных, отфильтровать позиции с несколькими кодами и красиво вывести информацию в отчет или табличный документ без лишних повторов.

Ограничения языка запросов 1С и суть проблемы

В языке запросов платформы 1С:Предприятие отсутствует прямой аналог SQL-функций агрегации строк (таких как GROUP_CONCAT или STRING_AGG). Мы не можем средствами одного простого плоского запроса объединить штрихкоды в одну строку через запятую. Если позиция имеет два штрихкода, в выборке всегда будет сформировано две записи детальных данных.

Для решения этой проблемы применяются два основных подхода:

  1. Запрос с временной таблицей и итогами: на первом шаге мы отбираем только те товары, у которых количество кодов строго больше единицы, затем соединяем их с регистром и обходим выборку по группировкам через встроенный язык.
  2. Система компоновки данных (СКД): использование возможностей языка выражений СКД для склеивания кодов в одну ячейку или автоматического построения иерархического табличного документа.

Вариант 1. Запрос с секцией ИМЕЮЩИЕ и временной таблицей

Проанализируем структуру эффективного запроса. Чтобы отобрать номенклатуру, у которой зарегистрировано больше одного кода, необходимо сгруппировать записи регистра и применить условие к результату агрегатной функции в секции ИМЕЮЩИЕ.

Посмотрим на практический пример запроса. Чтобы избежать падения производительности на больших объемах данных, поместим отобранные товары во временную таблицу, а затем выполним ВНУТРЕННЕЕ СОЕДИНЕНИЕ с исходным регистром сведений:


ВЫБРАТЬ
    ШтрихкодыНоменклатуры.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВтНоменклатураСНесколькимиШК
ИЗ
    РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
ГДЕ
    ШтрихкодыНоменклатуры.Штрихкод <> ""
СГРУППИРОВАТЬ ПО
    ШтрихкодыНоменклатуры.Номенклатура
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ШтрихкодыНоменклатуры.Штрихкод) > 1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ШтрихкодыНоменклатуры.Номенклатура КАК Номенклатура,
    ШтрихкодыНоменклатуры.Номенклатура.Код КАК Код,
    ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод
ИЗ
    ВтНоменклатураСНесколькимиШК КАК ВтТовары
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
        ПО ВтТовары.Номенклатура = ШтрихкодыНоменклатуры.Номенклатура
ГДЕ
    ШтрихкодыНоменклатуры.Штрихкод <> ""
ИТОГИ ПО
    Номенклатура
АВТОУПОРЯДОЧИВАНИЕ

Обратим внимание на важные детали реализации:

  1. Условие на пустые строки: проверка ШтрихкодыНоменклатуры.Штрихкод <> "" защищает выборку от ошибочных или незаполненных записей в базе.
  2. Использование РАЗЛИЧНЫЕ: конструкция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ШтрихкодыНоменклатуры.Штрихкод) гарантирует, что мы считаем именно уникальные штрихкоды, а не возможные задвоения по характеристикам или сериям.
  3. Секция ИТОГИ ПО: ключевое слово ИТОГИ ПО Номенклатура формирует иерархию данных, которая позволяет на уровне встроенного языка 1С обходить сначала сам товар, а затем список подчиненных ему кодов.

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

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

Для этого используем метод выборки с параметром ОбходРезультатаЗапроса.ПоГруппировкам:


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

Пока ВыборкаНоменклатура.Следующий() Цикл
    // Выводим строку заголовка с номенклатурой
    ОбластьНоменклатура.Параметры.Заполнить(ВыборкаНоменклатура);
    ТабДок.Вывести(ОбластьНоменклатура);

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

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

Вариант 2. Реализация через Систему компоновки данных (СКД)

Если задачу требуется решить без написания программного кода вывода макета, воспользуемся возможностями СКД. В схеме компоновки данных есть специальные инструменты для подобных отчетов.

Способ А. Склеивание кодов в одну ячейку через выражение ресурса

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

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

Способ Б. Иерархическая структура колонок в СКД

Если штрихкоды должны выводиться отдельными строками, в структуре отчета создаем родительскую группировку по полю Номенклатура, а внутри нее подчиненную ветку Детальные записи. В детальных записях выводим только поле Штрихкод. В таком виде СКД автоматически выведет товар единожды в шапке группы, а под ним разместит список кодов с отступом, исключая задвоение наименований.

Учет разрезов регистра: упаковки и характеристики

Выясним частую причину ошибок при подсчете штрихкодов в типовых конфигурациях (1С:УТ, 1С:КА, 1С:ERP). В типовом регистре ШтрихкодыНоменклатуры записи хранятся не только в разрезе товаров, но и с учетом реквизитов Упаковка, Характеристика и Серия.

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


ГДЕ
    ШтрихкодыНоменклатуры.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка)
    И ШтрихкодыНоменклатуры.Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)

Такой фильтр позволит избежать ложных срабатываний и отобразит только те позиции, где действительно накопились дублирующие коды базовой единицы.

← На главную