При доработке печатных форм в 1С:Управление торговлей 11 (УТ 11), например, для документа «Приобретение товаров и услуг», часто возникает задача заменить стандартный вывод артикула на штрихкод товара. Несмотря на кажущуюся простоту, разработчики часто сталкиваются с тем, что вместо цифр штрихкода в ячейке выводится слово «Массив» или программа выдает ошибку «Индекс находится за границами массива». В этой статье мы подробно разберем, почему это происходит, и как правильно реализовать вывод штрихкода в макет.
Проанализируем ситуацию: почему функция получения штрихкода может работать в одной печатной форме и выдавать ошибку в другой? Основная причина кроется в типе данных, которые передаются в функцию. В типовых конфигурациях 1С, таких как УТ 11, данные для печати часто собираются в сложные структуры или временные таблицы. В одном случае поле Номенклатура в выборке может быть Ссылкой (объектом), а в другом — уже готовой Строкой (наименованием товара), подготовленной для быстрого вывода в макет.
Рассмотрим стандартную функцию РаботаСНоменклатуройУТ.ПолучитьШтрихкодыПоНоменклатуре(). Она ожидает в качестве первого параметра именно Ссылку на элемент справочника Номенклатура. Если мы передадим туда строку (наименование), запрос внутри функции не найдет совпадений, так как будет сравнивать строку с уникальным идентификатором ссылки. В результате функция вернет пустой массив, и попытка обратиться к его первому элементу Штрихкод[0] приведет к аварийному завершению работы программы.
Если в вашей выборке (например, ВыборкаПоТоварам) поле Номенклатура содержит строку, нам необходимо получить ссылку. Разберем самый простой, но не самый оптимальный способ (через поиск), который поможет быстро проверить работоспособность кода:
// В цикле обхода товаров
Пока ВыборкаПоТоварам.Следующий() Цикл
// Пытаемся найти ссылку по коду, если в выборке есть код товара
СсылкаНаТовар = Справочники.Номенклатура.НайтиПоКоду(ВыборкаПоТоварам.Код);
// Если кода нет, можно попробовать найти по наименованию,
// но лучше всего добавить ссылку в сам запрос (см. ниже)
// СсылкаНаТовар = Справочники.Номенклатура.НайтиПоНаименованию(ВыборкаПоТоварам.Номенклатура);
КонецЦикла;
Важно: Использование НайтиПоКоду внутри цикла значительно замедляет формирование печатной формы, если в документе много строк. Профессиональным решением будет изменение самого текста запроса в функции СформироватьПечатнуюФорму..., чтобы поле Номенклатура изначально выбиралось как ссылка.
Функция ПолучитьШтрихкодыПоНоменклатуре возвращает Массив. Это логично, так как у одного товара в 1С может быть несколько штрихкодов (разные упаковки, характеристики или просто несколько кодов на одну единицу). Если вы просто напишете Область.Параметры.Артикул = Штрихкод, 1С выведет текстовое представление типа объекта, то есть слово "Массив". Нам же нужно получить конкретное значение из этого массива.
Проанализируем правильный алгоритм вывода:
// Получаем массив штрихкодов
// Передаем пустую ссылку на упаковку, если нужен основной штрихкод товара
МассивШК = РаботаСНоменклатуройУТ.ПолучитьШтрихкодыПоНоменклатуре(СсылкаНаТовар, Справочники.УпаковкиЕдиницыИзмерения.ПустаяСсылка);
Если МассивШК <> Неопределено И МассивШК.Количество() > 0 Тогда
// Берем первый найденный штрихкод
Область.Параметры.Артикул = МассивШК[0];
Иначе
// Обязательно очищаем параметр, чтобы не вывелось значение от предыдущей строки товара
Область.Параметры.Артикул = "";
КонецЕсли;
В конфигурации 1С:Управление торговлей 11 часто ведется учет в разрезе характеристик. Штрихкод в этом случае привязывается к комбинации Номенклатура + Характеристика. Если мы будем искать штрихкод только по номенклатуре, мы можем получить неверные данные или пустой результат. Выясним, как доработать запрос получения данных, чтобы учитывать этот разрез.
Для этого в функцию получения штрихкода (если она типовая и поддерживает это) или в свой запрос нужно передать характеристику. В случае с самописной функцией, пример которой приводился в обсуждении, запрос к регистру РегистрСведений.ШтрихкодыНоменклатуры должен выглядеть так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
|ГДЕ
| ШтрихкодыНоменклатуры.Номенклатура = &Номенклатура
| И ШтрихкодыНоменклатуры.Характеристика = &Характеристика
| И ШтрихкодыНоменклатуры.Упаковка = &Упаковка";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Характеристика", Характеристика);
Запрос.УстановитьПараметр("Упаковка", Упаковка);
Рассмотрим еще несколько важных моментов, которые помогут избежать пустых ячеек в печатной форме:
Область макета часто используются повторно в цикле. Если для товара №1 штрихкод был найден и записан в параметр Артикул, а для товара №2 штрихкода в базе нет — и вы не очистили параметр — в печатной форме для товара №2 продублируется штрихкод от товара №1. Всегда используйте ветку Иначе для очистки.Область.Параметры.Заполнить(СтруктураДанных) удобен, но опасен при работе с массивами. Если в структуре под ключом "Артикул" лежит массив, метод просто запишет тип "Массив". Для вывода конкретного значения лучше использовать прямое присваивание: Область.Параметры.Артикул = Значение.Сообщить("Тип значения: " + ТипЗнч(Штрихкод));. Это сразу покажет, работаете вы с массивом, строкой или неопределенным значением.Объединим все рекомендации в единый работоспособный блок кода, который следует разместить внутри цикла формирования строк печатной формы:
// 1. Получаем ссылку (если её нет в выборке напрямую)
ТоварСсылка = Справочники.Номенклатура.НайтиПоКоду(ВыборкаПоТоварам.Код);
// 2. Вызываем функцию получения штрихкодов
// Мы используем типовой модуль УТ 11
МассивШтрихкодов = РаботаСНоменклатуройУТ.ПолучитьШтрихкодыПоНоменклатуре(ТоварСсылка, Справочники.УпаковкиЕдиницыИзмерения.ПустаяСсылка);
// 3. Проверяем массив и выводим данные в параметр макета
Если МассивШтрихкодов <> Неопределено И МассивШтрихкодов.Количество() > 0 Тогда
// Записываем первый штрихкод в параметр "Артикул" (или "Штрихкод", если вы переименовали его в макете)
Область.Параметры.Артикул = МассивШтрихкодов[0];
Иначе
// Если штрихкода нет, можно оставить артикул или очистить поле
Область.Параметры.Артикул = "";
КонецЕсли;
Соблюдение этих правил гарантирует корректный вывод данных и отсутствие ошибок выполнения (Runtime errors) при печати документов. Помните, что отладчик — ваш лучший друг: всегда проверяйте тип переменной ВыборкаПоТоварам.Номенклатура перед тем, как передавать её в запросы или функции.