В процессе автоматизации торгового учета программисты 1С часто сталкиваются с проблемой: при формировании штрихкода EAN-13 система внезапно выдает 14 знаков. Это приводит к тому, что торговое оборудование (сканеры, принтеры этикеток) перестает корректно распознавать код, а база данных не может сопоставить товар. Рассмотрим подробнее, почему это происходит и как правильно реализовать алгоритм формирования контрольного символа.
Основная причина кроется в математическом алгоритме Modulo 10, который используется для вычисления последней цифры штрихкода. Стандартный алгоритм, который часто встречается в документации, выглядит следующим образом:
Проанализируем ситуацию, когда сумма на шаге 4 нацело делится на 10 (например, получается 90 или 100). На шаге 5 мы получаем 0. На шаге 6 мы вычитаем 0 из 10 и получаем... 10. Если программа просто добавит это число в конец штрихкода, он станет 14-значным. Выясним причину: согласно правилам GS1, если результат вычисления равен 10, то контрольная цифра должна быть 0.
Посмотрим на пример функции, которая корректно обрабатывает исключение с числом 10 и подходит для работы в современных конфигурациях. В данном коде используется коэффициент, который меняется в цикле, что позволяет эффективно обсчитывать строку штрихкода.
Функция ВычислитьКонтрольныйСимвол(Штрихкод, СимволНач = 1, СимволКон = 0) Экспорт
Если СимволКон = 0 Тогда
СимволКон = СтрДлина(Штрихкод);
КонецЕсли;
Сумма = 0;
Коэффициент = 1; // Вес позиции
// Проходим по строке штрихкода
Для Сч = СимволНач По СимволКон Цикл
КодСимв = КодСимвола(Штрихкод, Сч);
// Вычитаем 48, чтобы получить числовое значение из ASCII-кода
Сумма = Сумма + Коэффициент * (КодСимв - 48);
// Чередуем коэффициенты 1 и 3
Коэффициент = 4 - Коэффициент;
КонецЦикла;
// Ключевой момент: вычисление остатка
Сумма = 10 - Сумма % 10;
// Если получили 10, заменяем на 0
КонтрольныйСимвол = Символ(?(Сумма=10, 0, Сумма) + 48);
Возврат КонтрольныйСимвол;
КонецФункции
В этой функции мы используем тернарный оператор ?(Сумма=10, 0, Сумма), который является элегантным решением проблемы «лишнего знака». Также обратите внимание на работу с функцией КодСимвола — это позволяет избежать лишних преобразований типов внутри цикла.
Важно понимать, что для штрихкодов разной длины (EAN-8, EAN-13, ITF-14) правила «четных и нечетных» позиций могут путать разработчика. Проанализируем стандарт GS1: расчет весов всегда начинается справа налево.
Если вы примените это правило, вам не придется писать разные функции для 8-значных и 13-значных кодов. Достаточно передать строку в цикл, который идет от конца к началу.
Для тех, кто до сих пор поддерживает старые конфигурации или переносит логику из них, рассмотрим классический вариант реализации. Здесь алгоритм жестко задает количество итераций в зависимости от типа штрихкода.
Функция глКонтрольныйСимволEAN(ШтрКод, Тип) Экспорт
Четн = 0;
Нечетн = 0;
Если Тип = 13 Тогда
КолвоИтераций = 6;
ИначеЕсли Тип = 14 Тогда
КолвоИтераций = 7;
Иначе
КолвоИтераций = 4;
КонецЕсли;
Для Индекс = 1 По КолвоИтераций Цикл
Четн = Четн + Сред(ШтрКод, 2 * Индекс, 1);
Нечетн = Нечетн + Сред(ШтрКод, 2 * Индекс - 1, 1);
КонецЦикла;
Если Тип = 13 Тогда
Четн = Четн * 3;
Иначе
Нечетн = Нечетн * 3;
КонецЕсли;
КонтЦифра = 10 - (Четн + Нечетн) % 10;
Возврат ?(КонтЦифра = 10, "0", Строка(КонтЦифра));
КонецФункции
Обратите внимание, как в этом примере реализована работа с переменной КонтЦифра. Условие ?(КонтЦифра = 10, "0", Строка(КонтЦифра)) гарантирует, что функция всегда вернет ровно один символ.
Рассмотрим ситуацию, когда 1С формирует штрихкод для транспортной упаковки (ITF-14). В этом случае штрихкод изначально должен быть 14-значным. Часто программисты ошибаются, пытаясь применить логику EAN-13 к 14-значному числу без учета того, что веса позиций смещаются. Если вы добавите лидирующий ноль к обычному EAN-13, чтобы сделать его 14-значным (формат GTIN), контрольная цифра не изменится, так как ноль при умножении на любой коэффициент даст ноль. Однако расчет функций, приведенных выше, должен это учитывать.
Для кодов SSCC (18 знаков) логика остается той же (Modulo 10), но из-за большой длины данных вероятность ошибки при ручном расчете возрастает. Мы рекомендуем использовать проверенные функции из типовых библиотек (например, БСП — Библиотека Стандартных Подсистем), где расчет штрихкода уже отлажен на миллионах внедрений.
Штрихкод содержатся только цифры. Функция КодСимвола вернет некорректный результат, если в коде окажется пробел или спецсимвол.Используя приведенные примеры и понимая нюанс с «десяткой», вы сможете избежать ошибок при печати этикеток и обеспечите стабильную работу складского оборудования.