При внедрении складского штрихкодирования на автозапчастях или в логистических центрах ИТ-специалисты часто сталкиваются со следующей проблемой: при сканировании оригинального заводского кода детали к основному номеру добавляются несколько пробелов и суффикс (например, " 001"). Если попытаться записать этот штрихкод в карточку номенклатуры в 1С «как есть» и затем распечатать этикетку на принтере, то распечатанный штрихкод перестает считываться сканером. При этом обычные потребительские штрихкоды типа EAN-13 сканируются, печатаются и находятся в системе без каких-либо сложностей.
В этой статье мы подробно проанализируем физические и логические причины такого поведения оборудования, разберем особенности промышленного стандарта штрихкодирования GS1-128, настроим сканер и принтер этикеток, а также разработаем программный алгоритм для очистки входящих штрихкодов и их корректного поиска в базе данных 1С.
Оригинальные штрихкоды на коробках автозапчастей (особенно оригинальных деталей брендов Hyundai, Kia, VAG, Toyota) практически никогда не шифруются в простом формате EAN-13. В логистической сфере повсеместно применяется стандарт GS1-128 (ранее известный как UCC/EAN-128), базирующийся на линейном коде Code 128.
Этот стандарт позволяет кодировать в одной графической области не только артикул товара, но и сопутствующие данные: партию, дату производства, серийный номер, вес, а также количество единиц товара в упаковке. Для разделения этих данных используются специальные идентификаторы применения (Application Identifiers — AI), которые берутся в круглые скобки в текстовом представлении под штрихкодом.
В рассматриваемой нами ситуации штрихкод имеет структуру: КодДетали + Разделитель + КоличествоВУпаковке. Когда сканер считывает оригинальный код "2630035505 001", цифры "2630035505" означают каталожный номер (артикул) запчасти, а суффикс "001" указывает на то, что в данной упаковке находится ровно одна штука детали. Между ними стоит специальный непечатный символ-разделитель.
В стандарте GS1-128 для отделения полей переменной длины применяется управляющий символ группового разделителя GS (Group Separator, соответствующий ASCII-коду 29). По умолчанию большинство ручных сканеров (включая популярную модель Honeywell MS5145 Eclipse) из коробки подключены по интерфейсу USB в режиме эмуляции клавиатуры (USB Keyboard Emulation / HID).
Поскольку символ с ASCII-кодом 29 не имеет физической клавиши на клавиатуре, драйвер сканера при передаче данных в операционную систему пытается его интерпретировать. В зависимости от прошивки и настроек сканера этот управляющий символ заменяется на серию пробелов (от 1 до 5) или символ табуляции. В итоге в текстовое поле поиска 1С или в Блокнот попадает искаженная строка вида "2630035505 001".
Если записать штрихкод в карточку товара вместе с пробелами и суффиксом "2630035505 001" и отправить на печать, внешняя компонента «1С:Печать штрихкодов» попытается сформировать стандартный Code 128. Однако при генерации обычного Code 128 система не встраивает обязательные для GS1-128 маркеры (такие как служебный символ FNC1 и стартовые/стоповые знаки структуры данных). В результате получается некорректная последовательность черных и белых полос, которую сканеры распознать не могут.
Дополнительно накладывается техническая проблема качества печати этикеток:
Чтобы сканер корректно передавал данные в 1С без искажения управляющих символов разделителей GS1, крайне рекомендуется перевести его из режима эмуляции клавиатуры в режим эмуляции COM-порта (Virtual COM Port). В этом режиме сканер передает чистый поток байтов, который перехватывается специализированным драйвером торгового оборудования 1С.
Проанализируем шаги настройки сканера Honeywell 5145:
Recall Defaults.Enable Uni-Directional USB Serial Emulation Mode.COM3) назначился сканеру.Если переключение на COM-порт по какой-то причине невозможно, найдите в руководстве Honeywell раздел настройки форматирования UCC/EAN-128 и считайте управляющий штрихкод Enable UCC/EAN-128 Formatting. Это позволит сканеру корректно отрабатывать суффиксы и префиксы в режиме HID клавиатуры.
Выясним, как добиться стопроцентной читаемости распечатанных штрихкодов со сложных этикеток. Рассмотрим правила подготовки макета к печати:
GS1-128 (если позволяет компонента) либо генерируйте чистый Code 128 без лишних знаков разметки, содержащий только код детали.Самое эффективное и гибкое решение проблемы на складе — это программная отсечка хвостовой части штрихкода (пробелов и количества 001) непосредственно в кодовой базе 1С при приеме данных от сканера. Это избавит вас от необходимости перепечатывать заводские этикетки и забивать базу данных дублирующимися штрихкодами с суффиксами.
Рассмотрим по шагам реализацию этой логики. Нам потребуется написать функцию очистки строки штрихкода от суффиксов количества и доработать процедуру поиска номенклатуры.
Для начала создадим вспомогательную функцию проверки, является ли переданная строка числом, так как количество деталей в конце кода всегда выражено цифрами:
Функция СтрокаЯвляетсяЧислом(Знач ПроверяемаяСтрока) Экспорт
ПроверяемаяСтрока = СокрЛП(ПроверяемаяСтрока);
Если ПустаяСтрока(ПроверяемаяСтрока) Тогда
Возврат Ложь;
КонецЕсли;
// Пытаемся преобразовать строку в числовой тип данных
Попытка
ЧисловоеЗначение = Число(ПроверяемаяСтрока);
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Теперь разработаем основную функцию очистки входящего штрихкода от лишних пробелов и суффикса количества. Функция будет анализировать штрихкод на наличие разделителей и удалять правую часть, если она соответствует логистическому суффиксу количества товара в упаковке (например, " 001", " 010"):
Функция ОчиститьШтрихкодОтСуффиксаКоличества(Знач ВходящийШтрихкод) Экспорт
// Очищаем от концевых пробелов
ВходящийШтрихкод = СокрЛП(ВходящийШтрихкод);
// Заменяем неразрывные пробелы ASCII 160 на стандартные ASCII 32
ВходящийШтрихкод = СтрЗаменить(ВходящийШтрихкод, Символ(160), " ");
ДлинаКода = СтрДлина(ВходящийШтрихкод);
ПозицияРазделителя = 0;
// Ищем последний пробел в строке справа налево
Для СимволИндекс = 1 По ДлинаКода Цикл
ТекущийСимвол = Сред(ВходящийШтрихкод, СимволИндекс, 1);
Если ТекущийСимвол = " " Тогда
ПозицияРазделителя = СимволИндекс;
КонецЕсли;
КонецЦикла;
// Если пробел-разделитель найден, анализируем правую часть
Если ПозицияРазделителя > 0 Тогда
ЛеваяЧасть = СокрЛП(Лев(ВходящийШтрихкод, ПозицияРазделителя - 1));
ПраваяЧасть = СокрЛП(Сред(ВходящийШтрихкод, ПозицияРазделителя + 1));
// Если справа находится числовой суффикс количества (длиной от 1 до 4 символов)
Если СтрокаЯвляетсяЧислом(ПраваяЧасть) И СтрДлина(ПраваяЧасть) <= 4 Тогда
// Возвращаем чистый код детали без суффикса количества
Возврат ЛеваяЧасть;
КонецЕсли;
КонецЕсли;
// Если структура не похожа на GS1-128, возвращаем исходный код
Возврат ВходящийШтрихкод;
КонецФункции
Проанализируем интеграцию разработанного алгоритма в типовой механизм обработки сигналов торгового оборудования 1С. В модуле формы документа или в общем модуле работы с подключаемым оборудованием найдем предопределенную процедуру ВнешнееСобытие и внедрим туда вызов нашей функции очистки.
Процедура ОбработатьСканирование(ДанныеШтрихкода)
// Проводим предварительную очистку штрихкода от суффиксов GS1-128
ЧистыйШтрихкод = ОчиститьШтрихкодОтСуффиксаКоличества(ДанныеШтрихкода);
// Выполняем поиск по регистру сведений "Штрихкоды номенклатуры"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегШтрихкоды.Номенклатура КАК Номенклатура,
| РегШтрихкоды.ХарактеристикаНоменклатуры КАК Характеристика,
| РегШтрихкоды.ЕдиницаИзмерения КАК ЕдиницаИзмерения
|ИЗ
| РегистрСведений.Штрихкоды КАК РегШтрихкоды
|ГДЕ
| РегШтрихкоды.Штрихкод = &Штрихкод";
Запрос.УстановитьПараметр("Штрихкод", ЧистыйШтрихкод);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Добавляем найденную номенклатуру в табличную часть документа
ДобавитьНоменклатуруВТабличнуюЧасть(Выборка.Номенклатура, Выборка.Характеристика, Выборка.ЕдиницаИзмерения);
Сообщить("Товар успешно добавлен по штрихкоду: " + ЧистыйШтрихкод);
Иначе
// Дополнительный поиск по артикулу (каталожному номеру), если штрихкод не найден напрямую
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", ЧистыйШтрихкод);
Если ЗначениеЗаполнено(НайденнаяСсылка) Тогда
ДобавитьНоменклатуруВТабличнуюЧасть(НайденнаяСсылка);
Сообщить("Товар найден по каталожному номеру (артикулу): " + ЧистыйШтрихкод);
Иначе
Сообщить("Штрихкод или артикул " + ДанныеШтрихкода + " не зарегистрирован в системе!", СтатусСообщения.Важное);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Для надежного построения системы адресного хранения и штрихкодирования автозапчастей рекомендуем придерживаться следующих правил:
001) — тупиковый путь. Это приведет к лавинообразному росту дублей штрихкодов в регистре при смене логистической партии или изменении упаковки производителем. Очищайте штрихкоды программно при вводе в систему.