В этой статье разберем задачу, с которой часто сталкиваются разработчики при работе с маркировкой: как программно добавить коды маркировки (штрихкоды), полученные из внешней системы, в документ "Реализация товаров и услуг" в 1С:ERP — для этого подойдёт удобная панель маркировки для ERP, КА и УТ. Подобные задачи часто возникают, когда требуется внедрить решение для Честного Знака или автоматизировать массовую обработку данных. Проанализируем типичные ошибки начинающих и пошагово придем к правильному решению.
Основная проблема заключается в двух этапах:
Рассмотрим оба этапа подробно.
Часто первая интуитивная попытка — это создать новый элемент справочника и напрямую записать в него строковое значение штрихкода. Проанализируем исходный код, который приводит к ошибке, и исправим его.
Неправильный подход: попытка записи строки в ссылочный реквизит
Изначальная логика может выглядеть так: создаем "родительский" штрихкод для упаковки и в его табличную часть ВложенныеШтрихкоды пытаемся добавить строковые значения кодов.
// Исходный, неверный код
Для Каждого Товар Из Товары["Марк"] Цикл
// ... получение данных товара ...
НовыеШтрихкоды = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
// ... заполнение реквизитов НовыеШтрихкоды ...
Для Каждого Код Из Товар["Коды"] Цикл
НовыйШтрихкод = НовыеШтрихкоды.ВложенныеШтрихкоды.Добавить();
// ОШИБКА: Попытка записать строку в реквизит с типом "СправочникСсылка"
НовыйШтрихкод.Штрихкод = Код;
КонецЦикла;
НовыеШтрихкоды.Записать();
КонецЦикла;
Такой код не будет работать, потому что реквизит Штрихкод в табличной части ВложенныеШтрихкоды имеет тип СправочникСсылка.ШтрихкодыУпаковокТоваров. В него нельзя просто присвоить строку. Система ожидает ссылку на уже существующий или новый элемент справочника.
Следующая ошибка — попытка присвоить реквизиту не ссылку, а объект, полученный после СоздатьЭлемент().
// Неверный код, вариант 2
ВложеныйШтрихкод = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
// ... заполнение реквизитов объекта ВложеныйШтрихкод ...
НовыйШтрихкод = НовыеШтрихкоды.ВложенныеШтрихкоды.Добавить();
// ОШИБКА: Попытка присвоить объект вместо ссылки
НовыйШтрихкод.Штрихкод = ВложеныйШтрихкод;
Этот код также не сработает. В табличную часть нужно помещать не объект (СправочникОбъект), а ссылку на него (СправочникСсылка), которую можно получить только после записи объекта. Это особенно важно, если вам необходимо обрабатывать коды маркировки заказа на эмиссию с полным составом данных — в этом поможет готовый модуль интеграции с Честным Знаком.
Правильный подход: создание и запись каждого кода
Чтобы все работало корректно, необходимо для каждого вложенного кода маркировки создать свой элемент в справочнике ШтрихкодыУпаковокТоваров, записать его и только потом добавить ссылку на него в табличную часть родительской упаковки. Разберем по шагам:
СоздатьЭлемент().ТипУпаковки (например, МаркированныйТовар), ТипШтрихкода, ЗначениеШтрихкода (само строковое представление кода), Номенклатура, Характеристика и т.д.Записать(). Именно после этого у него появляется уникальная ссылка.ВложенныеШтрихкоды родительской упаковки.Штрихкод новой строки присваиваем ссылку на записанный элемент.Посмотрим на исправленный и полный пример кода для создания одного штрихкода. Обратите внимание на использование блока Попытка-Исключение для надежной обработки ошибок записи.
// Функция для создания и записи одного кода маркировки
Функция СоздатьШтрихкод(Знач ДанныеШК, Знач Номенклатура, Знач Характеристика, Знач Упаковка)
НовыйЭлемент = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
НовыйЭлемент.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
НовыйЭлемент.ТипШтрихкода = Перечисления.ТипыШтрихкодов.GS1_DataMatrix;
НовыйЭлемент.ЗначениеШтрихкода = ДанныеШК; // Строка с кодом
НовыйЭлемент.Номенклатура = Номенклатура;
НовыйЭлемент.Характеристика = Характеристика;
НовыйЭлемент.Упаковка = Упаковка; // Обычно "Единица хранения" или базовая ед. изм.
НовыйЭлемент.Количество = 1;
// В реальных задачах также важно рассчитывать и записывать хеш-сумму
// НовыйЭлемент.ХешСуммаЗначенияШтрихкода = ...;
Попытка
НовыйЭлемент.Записать();
Возврат НовыйЭлемент.Ссылка;
Исключение
Сообщить("Ошибка записи кода маркировки " + СокрЛП(ДанныеШК) + ": " + ОписаниеОшибки(), СтатусСообщения.Важное);
Возврат Неопределено;
КонецПопытки;
КонецФункции
// Пример использования в цикле
Для Каждого Товар Из Товары["Марк"] Цикл
// ...
// Создаем родительскую упаковку, если нужно
РодительскаяУпаковка = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
// ... заполняем ее реквизиты ...
Для Каждого Код Из Товар["Коды"] Цикл
// Создаем и записываем вложенный штрихкод
СсылкаНаВложенныйШК = СоздатьШтрихкод(Код, НоменклатураТовара, ХарактеристикаТовара, УпаковкаТовара);
Если ЗначениеЗаполнено(СсылкаНаВложенныйШК) Тогда
// Добавляем ссылку в табличную часть родителя
СтрокаВложенныеШтрихкоды = РодительскаяУпаковка.ВложенныеШтрихкоды.Добавить();
СтрокаВложенныеШтрихкоды.Штрихкод = СсылкаНаВложенныйШК;
КонецЕсли;
КонецЦикла;
РодительскаяУпаковка.Записать();
КонецЦикла;
После того как мы научились создавать записи о штрихкодах в справочнике, возникает главный вопрос: как показать в документе, что для конкретной строки товара подобраны именно эти коды? В некоторых случаях бывает полезно использовать дубликатор кодов маркировки, чтобы оперативно подготовить копии КИЗ для отгрузки.
Для хранения подобранных кодов маркировки в документе "Реализация товаров и услуг" используется специальная табличная часть — ШтрихкодыУпаковок. Именно ее нам и нужно заполнить.
Алгоритм привязки кодов к строке документа
Объект.Товары.ИдентификаторСтроки.Объект.ШтрихкодыУпаковок.Пример кода для привязки:
// Предполагается, что у нас есть ДокументОбъект и СтруктураКодов
Для Каждого КлючЗначение Из СтруктураКодов Цикл
ИдентификаторСтрокиТовара = КлючЗначение.Ключ;
МассивСсылокНаШК = КлючЗначение.Значение;
НайденныеСтроки = ДокументОбъект.Товары.НайтиСтроки(Новый Структура("ИдентификаторСтроки", ИдентификаторСтрокиТовара));
Если НайденныеСтроки.Количество() = 0 Тогда
Продолжить;
КонецЕсли;
СтрокаТовара = НайденныеСтроки[0];
Для Каждого СсылкаНаШК Из МассивСсылокНаШК Цикл
НоваяСтрокаШК = ДокументОбъект.ШтрихкодыУпаковок.Добавить();
НоваяСтрокаШК.Штрихкод = СсылкаНаВложенныйШК;
НоваяСтрокаШК.Номенклатура = СтрокаТовара.Номенклатура;
НоваяСтрокаШК.Характеристика = СтрокаТовара.Характеристика;
НоваяСтрокаШК.Серия = СтрокаТовара.Серия;
НоваяСтрокаШК.Количество = 1;
НоваяСтрокаШК.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
НоваяСтрокаШК.ИдентификаторСтроки = ИдентификаторСтрокиТовара;
КонецЦикла;
КонецЦикла;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Важное замечание: в типовых конфигурациях настоятельно рекомендуется использовать экспортные процедуры из общих модулей. Также помните, что для бесперебойной работы обмена данными критически важно настроить автоматическое обновление токенов Честного Знака, чтобы избежать остановки отгрузок из-за просроченной авторизации. Если вы внедряете масштабные изменения, изучите практический опыт маркировки остатков на складе, это поможет избежать типичных ошибок при работе с большим объемом данных — для этого есть готовое решение для маркировки остатков товаров.