Как правильно выбрать штрихкод из регистра и вывести его в печатную форму без дублирования данных?

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

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

В чем причина «залипания» параметров в печатной форме?

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

Проанализируем типичную ошибку в коде:


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

Для Каждого Запись Из НаборЗаписей Цикл
    ОбластьМакета.Параметры.ШтрихКод = Запись.ШтрихКод;
КонецЦикла;

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

Решение №1: Принудительная очистка параметров

Самый простой и быстрый способ исправить проблему — добавить блок Иначе или проверку количества записей в наборе. Нам нужно гарантировать, что если данных нет, параметр будет очищен. Рассмотрим исправленный вариант кода:


// ... код установки отборов ...
НаборЗаписей.Прочитать();

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

ТабДок.Вывести(ОбластьМакета);

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

Решение №2: Пересоздание области макета (Лучшая практика)

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

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


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

Решение №3: Оптимизация через запрос (Профессиональный подход)

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

  1. Сначала выгрузим все товары документа во временную таблицу или сформируем массив ссылок номенклатуры и характеристик.
  2. Одним запросом выберем все штрихкоды для этого списка товаров.
  3. Свяжем данные штрихкодов с данными товаров.

Пример запроса, который сразу вернет товары со штрихкодами нужного типа:


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

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

Особенности работы с регистром штрихкодов в УТП

Работая с типовыми конфигурациями (УТП, УПП, УТ 10.3), важно помнить о структуре измерений регистра Штрихкоды. Ошибка автора темы часто заключается в недостаточном отборе. Выясним, на что нужно обратить внимание:

Подведем итоги

Чтобы ваша печатная форма работала корректно, следуйте этим правилам: во-первых, всегда очищайте параметры области, если данные не найдены; во-вторых, старайтесь получать область макета внутри цикла; в-третьих, по возможности откажитесь от запросов в цикле в пользу одного общего запроса ко всем данным документа. Это не только избавит вас от ошибок вывода, но и значительно ускорит работу программы.

← На главную