При разработке печатных форм в 1С часто возникает задача вывода дополнительных данных, которые хранятся не в самом документе, а в связанных регистрах. Одной из самых распространенных задач является получение штрихкодов для списка номенклатуры. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с логическими ошибками в запросах или проблемами производительности при обработке больших табличных частей. Разберем пошагово, как правильно извлечь данные из регистра ШтрихкодыНоменклатуры, избегая типичных ловушек.
Рассмотрим ситуацию, когда при написании запроса разработчик пытается наложить отбор по всем измерениям сразу. Проанализируем типичный ошибочный код, который часто встречается на практике:
Запрос.Текст =
"ВЫБРАТЬ
| ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
|ГДЕ
| ШтрихкодыНоменклатуры.Штрихкод = &Штрихкод
| И ШтрихкодыНоменклатуры.Штрихкод = &Номенклатура
| И ШтрихкодыНоменклатуры.Штрихкод = &Характеристика";
В чем заключается главная проблема этого фрагмента? Здесь используется оператор И для сравнения одного и того же поля Штрихкод с разными сущностями. Как справедливо отмечено в обсуждении, поле «Штрихкод» (которое обычно является строкой) не может одновременно быть и строкой штрихкода, и ссылкой на справочник Номенклатура, и ссылкой на ХарактеристикиНоменклатуры. Такой запрос всегда будет возвращать пустой результат, либо данные будут «не точными», если типы данных случайно совпадут (что в 1С практически исключено для ссылок и строк).
Правильный подход заключается в том, чтобы сравнивать каждое измерение регистра с соответствующим ему параметром:
Запрос.Текст =
"ВЫБРАТЬ
| ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
|ГДЕ
| ШтрихкодыНоменклатуры.Номенклатура = &Номенклатура
| И ШтрихкодыНоменклатуры.Характеристика = &Характеристика";
Часто программисты сталкиваются с тем, что даже при визуальном наличии штрихкода в базе, запрос возвращает пустое значение. Выясним причину этого поведения. В системе 1С характеристики номенклатуры могут использоваться не для всех позиций. Если учет по характеристикам для конкретного товара не ведется, то в регистре сведений в поле Характеристика записывается ПустаяСсылка соответствующего типа.
Если в параметр запроса &Характеристика передать значение Неопределено или пустую ссылку другого типа, условие ШтрихкодыНоменклатуры.Характеристика = &Характеристика не выполнится. Для решения этой проблемы рекомендуется:
СтрокаЗапасы.Характеристика — это ссылка, а не другой тип данных.В представленном коде из сообщения №15 видна критическая ошибка производительности: создание объекта Новый Запрос и его выполнение внутри цикла Для каждого СтрокаЗапасы Из Шапка.ТаблицаЗапасы Цикл. Если в заказе покупателя будет 100 строк, система сделает 100 отдельных обращений к базе данных, что существенно замедлит формирование печатной формы.
Проанализируем, как сделать это правильно с помощью пакетного запроса или левого соединения. Рассмотрим алгоритм эффективного получения данных:
ШтрихкодыНоменклатуры по полям Номенклатура и Характеристика.Пример оптимизированного запроса для интеграции в общую схему печати:
// В основном запросе печати добавляем соединение:
"ВЫБРАТЬ
| ЗаказЗапасы.Номенклатура КАК Номенклатура,
| ЗаказЗапасы.Характеристика КАК Характеристика,
| ЕСТЬNULL(Штрихкоды.Штрихкод, """") КАК Штрихкод
|ИЗ
| Документ.ЗаказПокупателя.Запасы КАК ЗаказЗапасы
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
| ПО ЗаказЗапасы.Номенклатура = Штрихкоды.Номенклатура
| И ЗаказЗапасы.Характеристика = Штрихкоды.Характеристика
|ГДЕ
| ЗаказЗапасы.Ссылка В(&МассивОбъектов)"
В 1С у одной номенклатуры может быть зарегистрировано несколько штрихкодов (например, EAN13 и внутренний код). Если использовать простое соединение, в результат запроса попадет столько строк, сколько штрихкодов найдено в регистре, что приведет к дублированию строк в печатной форме.
Разберем способы решения этой проблемы:
МАКСИМУМ(Штрихкод) в группировке.EAN13.Рассмотрим пример с использованием группировки для исключения дублей:
"ВЫБРАТЬ
| Штрихкоды.Номенклатура КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| МАКСИМУМ(Штрихкоды.Штрихкод) КАК Штрихкод
|ПОМЕСТИТЬ ВТ_Штрихкоды
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
|ГДЕ
| Штрихкоды.Номенклатура В (ВЫБРАТЬ РАЗЛИЧНЫЕ Номенклатура ИЗ ВТ_ТоварыДокумента)
|СГРУППИРОВАТЬ ПО
| Штрихкоды.Номенклатура,
| Штрихкоды.Характеристика"
Важный совет: Если вы работаете в современной конфигурации на базе БСП (например, УНФ, УТ 11 или ERP), прежде чем писать свой запрос, проверьте наличие общего модуля ШтрихкодированиеНоменклатуры или аналогичного. Зачастую там уже реализованы функции типа ПолучитьШтрихкодНоменклатуры(), которые учитывают и характеристики, и единицы измерения, и даже упаковки товара, что избавит вас от необходимости изобретать велосипед.