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

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

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

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

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

Рассмотрим пример типичного запроса, который вызывает сложности:


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

Решение 1: Использование функции ЕСТЬNULL и искусственного поля веса

Самый эффективный способ управлять порядком строк — сделать это еще на уровне запроса. Чтобы товары без штрихкодов всегда были вверху, мы введем специальное поле для сортировки. Выясним, как это реализовать. Мы добавим условие ВЫБОР, которое присвоит «вес» (приоритет) строке.

Проанализируем обновленный текст запроса:


ВЫБРАТЬ
    РеализацияТоваров.Номенклатура КАК Номенклатура,
    ЕСТЬNULL(Штрихкоды.Штрихкод, "") КАК Штрихкод,
    ВЫБОР
        КОГДА Штрихкоды.Штрихкод ЕСТЬ NULL ТОГДА 0
        ИНАЧЕ 1
    КОНЕЦ КАК ПорядокШК
ИЗ
    Документ.РеализацияТоваров.Товары КАК РеализацияТоваров
ЛЕВОЕ СОЕДИНЕНИЕ 
    РегистрСведений.Штрихкоды КАК Штрихкоды
ПО 
    РеализацияТоваров.Номенклатура = Штрихкоды.Владелец
УПОРЯДОЧИТЬ ПО
    Наименование,
    ПорядокШК

В данном примере мы используем ЕСТЬNULL(Штрихкоды.Штрихкод, ""), чтобы заменить пустые значения на пустую строку. Это позволяет методу Сортировать() в ТЗ или конструкции УПОРЯДОЧИТЬ ПО в запросе работать корректно. Поле ПорядокШК гарантирует, что даже если у товара есть штрихкод, первой строкой (если мы этого хотим) пойдет запись с приоритетом.

Решение 2: Обработка данных в Таблице Значений

Если данные уже получены в Таблицу Значений (ТЗ), и мы не можем или не хотим менять запрос, воспользуемся методами программного изменения ТЗ. Посмотрим на алгоритм, который позволяет «дозаполнить» и отсортировать таблицу вручную.

Разберем по шагам:

  1. Добавим в ТЗ вспомогательную колонку Приоритет типа Число.
  2. В цикле пройдем по строкам и установим значения: например, если штрихкод пустой — 0, если заполнен — 1.
  3. Выполним сортировку по нескольким колонкам.

// Добавляем колонку для управления сортировкой
ТЗРезультат.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число"));

Для Каждого СтрокаТЗ Из ТЗРезультат Цикл
    Если ПустаяСтрока(СтрокаТЗ.Штрихкод) Тогда
        СтрокаТЗ.Приоритет = 0;
    Иначе
        СтрокаТЗ.Приоритет = 1;
    КонецЕсли;
КонецЦикла;

// Сортируем сначала по наименованию, затем по нашему приоритету
ТЗРезультат.Сортировать("Наименование Возр, Приоритет Возр");

Этот метод удобен тем, что дает полный контроль над визуальным порядком строк перед выводом в макет. После сортировки вспомогательную колонку можно удалить методом ТЗРезультат.Колонки.Удалить("Приоритет").

Решение 3: Правильный вывод в печатную форму (Макет)

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

Рассмотрим подробнее, как это реализовать через ОбходРезультатаЗапроса.ПоГруппировкам. В запросе необходимо добавить ИТОГИ ПО Номенклатуре.


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

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

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

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

Если ваша задача позволяет использовать СКД, это будет самым современным решением. В СКД проблема «красивого вывода» решается настройкой иерархии группировок. Выясним преимущества этого метода:

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

Важный момент: При работе с ЛЕВЫМ СОЕДИНЕНИЕМ в запросах 1С всегда помните о возможности появления нескольких одинаковых строк номенклатуры. Всегда проверяйте, не дублируются ли количественные показатели (сумма, количество) из-за соединения со штрихкодами. Если это происходит, используйте агрегатные функции или расчет итогов.

← На главную