Как объединить номенклатуру и несколько её штрихкодов в одну строку

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

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

Способ 1. Использование системы компоновки данных (СКД)

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

Шаг 1. Создание набора данных

Проанализируем текст запроса. Нам необходимо выбрать всю номенклатуру и соединить её с регистром сведений штрихкодов. Важно использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы товары без штрихкодов также попали в список.


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

Шаг 2. Настройка ресурсов

Перейдем на вкладку Ресурсы в конструкторе схемы компоновки данных. Здесь кроется основной секрет решения:

  1. Выберем поле Штрихкод в колонку «Поле».
  2. В колонке «Выражение» напишем: СоединитьСтроки(Массив(Различные Штрихкод), ", ").
  3. В колонке «Рассчитывать по» укажем Ссылка (или Номенклатура).

Функция Массив() соберет все значения штрихкодов в одну коллекцию, а СоединитьСтроки() превратит этот массив в строку с разделителем «запятая + пробел». Использование ключевого слова Различные внутри массива поможет избежать дублирования одинаковых штрихкодов, если они ошибочно заведены в базе.

Способ 2. Программная обработка через ИТОГИ в запросе

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

Проанализируем ситуацию: нам нужно сгруппировать данные по номенклатуре. Для этого в запросе следует использовать секцию ИТОГИ.


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

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

ТЗ_Результат = Новый ТаблицаЗначений;
ТЗ_Результат.Колонки.Добавить("Номенклатура");
ТЗ_Результат.Колонки.Добавить("ВсеШтрихкоды");

Пока ВыборкаТовар.Следующий() Цикл
    
    МассивШК = Новый Массив;
    ВыборкаШК = ВыборкаТовар.Выбрать();
    
    Пока ВыборкаШК.Следующий() Цикл
        Если ЗначениеЗаполнено(ВыборкаШК.Штрихкод) Тогда
            МассивШК.Добавить(Строка(ВыборкаШК.Штрихкод));
        КонецЕсли;
    КонецЦикла;
    
    НоваяСтрока = ТЗ_Результат.Добавить();
    НоваяСтрока.Номенклатура = ВыборкаТовар.Товар;
    НоваяСтрока.ВсеШтрихкоды = СтрСоединить(МассивШК, ", ");
    
КонецЦикла;

В данном примере мы используем двухуровневый обход. Верхний уровень (ПоГруппировкам) дает нам уникальную номенклатуру, а вложенный цикл собирает все связанные штрихкоды в массив. Функция СтрСоединить() — это быстрый и эффективный способ объединения элементов массива в одну строку.

Оптимизация и важные нюансы

При работе с реальными базами данных важно учитывать несколько критических моментов, которые могут повлиять на производительность и корректность данных:

  1. Учет характеристик: В типовых конфигурациях (УТ 11, ERP, КА 2) штрихкод часто привязан не только к номенклатуре, но и к Характеристике или Упаковке. Если ваша задача требует разделения штрихкодов по характеристикам, добавьте это поле в группировку.
  2. Временные таблицы: Если в справочнике Номенклатура десятки тысяч записей, а вам нужны штрихкоды только по определенной группе или списку, сначала выгрузите нужные товары во Временную Таблицу. Затем соединяйте эту временную таблицу с регистром штрихкодов. Это значительно ускорит выполнение запроса.
  3. Проверка на пустые значения: При левом соединении для товаров без штрихкода в поле Штрихкод придет значение NULL. В коде 1С или в выражении СКД обязательно предусматривайте обработку таких случаев (например, через ЕСТЬNULL(Штрихкод, "") в запросе или проверку ЗначениеЗаполнено() в коде), чтобы избежать ошибок или лишних запятых в итоговой строке.
  4. Индексы: Убедитесь, что в регистре сведений штрихкодов поле Номенклатура является ведущим или индексированным. В типовых решениях это обычно так и есть, но в самописных регистрах отсутствие индекса на поле связи приведет к крайне медленной работе соединения.

Выгрузка результата СКД в таблицу значений

Выясним, как реализовать пожелание автора темы из сообщения №21 — получить результат с объединенными строками именно в виде таблицы значений, используя мощь СКД. Это позволяет не писать циклы обхода вручную.


// Создаем схему, настраиваем ресурсы как описано в Способе 1
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

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

// Теперь в ТаблицаРезультат лежат колонки "Ссылка" и "Штрихкод" (соединенный через запятую)

Этот метод объединяет в себе простоту настройки визуального конструктора и гибкость программного интерфейса. Мы рекомендуем использовать именно СКД, так как это наиболее универсальный механизм в 1С 8.3, который автоматически обрабатывает многие сложности, такие как права доступа (RLS) и типы данных.

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

← На главную