Как правильно получить и заполнить штрихкод для строки табличной части в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Анализ типичных ошибок в коде

Проанализируем исходный фрагмент кода, вызывающий проблемы:


СТЧ = ЭлементыФормы.Товары.ТекущиеДанные;     
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Штрихкоды.Штрихкод,
|    Штрихкоды.Владелец.Ссылка КАК Товар,
|    Штрихкоды.ХарактеристикаНоменклатуры
|ИЗ
|    РегистрСведений.Штрихкоды КАК Штрихкоды";
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();

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

В этом коде допущено сразу несколько грубых архитектурных и логических ошибок:

  1. Работа с одной текущей строкой вместо обхода: Переменная СТЧ получает значение ЭлементыФормы.Товары.ТекущиеДанные. Это ссылка только на одну активную строку, на которой установлен фокус пользователя. Цикл сравнивает записи всего регистра только с этой одной строкой, поэтому обработка всей таблицы не происходит. Кроме того, если фокус в таблице не установлен, ТекущиеДанные вернет Неопределено, что приведет к исключению «Поле объекта не обнаружено».
  2. Добавление строк вместо изменения: Метод Товары.Добавить() создает новую дублирующую строку при каждом найденном штрихкоде, вместо того чтобы записать штрихкод в существующую строку.
  3. Чтение всей таблицы регистра сведений: Выборка данных без секции ГДЕ заставляет СУБД считывать все записи регистра в память. При росте базы данных этот запрос вызовет резкое падение производительности.
  4. Избыточное разыменование: Конструкция Штрихкоды.Владелец.Ссылка содержит лишнее обращение через точку к реквизиту Ссылка, так как поле Владелец само по себе уже содержит ссылку на справочник номенклатуры.

Вариант 1. Получение штрихкода для одной текущей строки

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

Разберем по шагам правильный алгоритм:


СТЧ = ЭлементыФормы.Товары.ТекущиеДанные;

// Проверяем, что строка действительно выбрана
Если СТЧ <> Неопределено Тогда
    Отбор = Новый Структура;
    Отбор.Вставить("Владелец", СТЧ.Номенклатура);
    Отбор.Вставить("ХарактеристикаНоменклатуры", СТЧ.ХарактеристикаНоменклатуры);
    
    ДанныеЗаписи = РегистрыСведений.Штрихкоды.Получить(Отбор);
    СТЧ.Штрихкод = ДанныеЗаписи.Штрихкод;
КонецЕсли;

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


СТЧ = ЭлементыФормы.Товары.ТекущиеДанные;

Если СТЧ <> Неопределено Тогда
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Штрихкоды.Штрихкод КАК Штрихкод
    |ИЗ
    |    РегистрСведений.Штрихкоды КАК Штрихкоды
    |ГДЕ
    |    Штрихкоды.Владелец = &Номенклатура
    |    И Штрихкоды.ХарактеристикаНоменклатуры = &Характеристика";
    
    Запрос.УстановитьПараметр("Номенклатура", СТЧ.Номенклатура);
    Запрос.УстановитьПараметр("Характеристика", СТЧ.ХарактеристикаНоменклатуры);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        СТЧ.Штрихкод = Выборка.Штрихкод;
    КонецЕсли;
КонецЕсли;

Вариант 2. Пакетное заполнение штрихкодов для всей табличной части

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

Рассмотрим реализацию массового заполнения:


// Создаем менеджер временных таблиц
МВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;

// Передаем табличную часть в запрос
Запрос.Текст = 
"ВЫБРАТЬ
|    ТабЧасть.НомерСтроки КАК НомерСтроки,
|    ТабЧасть.Номенклатура КАК Номенклатура,
|    ТабЧасть.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
|    &ТабличнаяЧасть КАК ТабЧасть;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|    ВТ_Товары.НомерСтроки КАК НомерСтроки,
|    ЕСТЬNULL(Штрихкоды.Штрихкод, """") КАК Штрихкод
|ИЗ
|    ВТ_Товары КАК ВТ_Товары
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Штрихкоды КАК Штрихкоды
|        ПО ВТ_Товары.Номенклатура = Штрихкоды.Владелец
|        И ВТ_Товары.ХарактеристикаНоменклатуры = Штрихкоды.ХарактеристикаНоменклатуры";

Запрос.УстановитьПараметр("ТабличнаяЧасть", Товары.Выгрузить());

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

// Заполняем штрихкоды в исходной табличной части по номеру строки
Пока Выборка.Следующий() Цикл
    СтрокаТЧ = Товары[Выборка.НомерСтроки - 1];
    СтрокаТЧ.Штрихкод = Выборка.Штрихкод;
КонецЦикла;

Важные рекомендации при работе с регистрами штрихкодов

  1. Контроль типов характеристик: Если по номенклатуре не ведется учет по характеристикам, в табличную часть попадает пустая ссылка типа СправочникСсылка.ХарактеристикиНоменклатуры. Убедитесь, что отбор не передает значение Неопределено вместо пустой ссылки, иначе условие равенства не сработает.
  2. Множественность штрихкодов: У одной позиции номенклатуры с одной и той же характеристикой может быть зарегистрировано несколько штрихкодов (например, на разные упаковки или штучные единицы). В запросах рекомендуется добавлять фильтрацию по единице измерения или упаковке либо использовать конструкцию ВЫБРАТЬ ПЕРВЫЕ 1.
← На главную