Как правильно рассчитать контрольную цифру штрихкода в 1С и избежать появления лишних знаков?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе автоматизации торгового учета программисты 1С часто сталкиваются с проблемой: при формировании штрихкода EAN-13 система внезапно выдает 14 знаков. Это приводит к тому, что торговое оборудование (сканеры, принтеры этикеток) перестает корректно распознавать код, а база данных не может сопоставить товар. Рассмотрим подробнее, почему это происходит и как правильно реализовать алгоритм формирования контрольного символа.

Разбор проблемы: откуда берется 14-й знак?

Основная причина кроется в математическом алгоритме Modulo 10, который используется для вычисления последней цифры штрихкода. Стандартный алгоритм, который часто встречается в документации, выглядит следующим образом:

  1. Складываются цифры, стоящие на четных позициях.
  2. Полученная сумма умножается на 3.
  3. Складываются цифры, стоящие на нечетных позициях (кроме последней).
  4. Результаты шагов 2 и 3 суммируются.
  5. От полученного числа берется остаток от деления на 10.
  6. Остаток вычитается из 10 — это и есть контрольная цифра.

Проанализируем ситуацию, когда сумма на шаге 4 нацело делится на 10 (например, получается 90 или 100). На шаге 5 мы получаем 0. На шаге 6 мы вычитаем 0 из 10 и получаем... 10. Если программа просто добавит это число в конец штрихкода, он станет 14-значным. Выясним причину: согласно правилам GS1, если результат вычисления равен 10, то контрольная цифра должна быть 0.

Решение для 1С:Предприятие 8.х (универсальный подход)

Посмотрим на пример функции, которая корректно обрабатывает исключение с числом 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-значных кодов. Достаточно передать строку в цикл, который идет от конца к началу.

Решение для 1С 7.7 (классический алгоритм)

Для тех, кто до сих пор поддерживает старые конфигурации или переносит логику из них, рассмотрим классический вариант реализации. Здесь алгоритм жестко задает количество итераций в зависимости от типа штрихкода.


Функция глКонтрольныйСимволEAN(ШтрКод, Тип) Экспорт
    Четн = 0;
    Нечетн = 0;
    
    Если Тип = 13 Тогда
        КолвоИтераций = 6;
    ИначеЕсли Тип = 14 Тогда
        КолвоИтераций = 7;
    Иначе
        КолвоИтераций = 4;
    КонецЕсли;
    
    Для Индекс = 1 По КолвоИтераций Цикл
        Четн = Четн + Сред(ШтрКод, 2 * Индекс, 1);
        Нечетн = Нечетн + Сред(ШтрКод, 2 * Индекс - 1, 1);
    КонецЦикла;
    
    Если Тип = 13 Тогда
        Четн = Четн * 3;
    Иначе
        Нечетн = Нечетн * 3;
    КонецЕсли;
    
    КонтЦифра = 10 - (Четн + Нечетн) % 10;
    
    Возврат ?(КонтЦифра = 10, "0", Строка(КонтЦифра));
КонецФункции

Обратите внимание, как в этом примере реализована работа с переменной КонтЦифра. Условие ?(КонтЦифра = 10, "0", Строка(КонтЦифра)) гарантирует, что функция всегда вернет ровно один символ.

Особенности работы с GTIN-14 и SSCC

Рассмотрим ситуацию, когда 1С формирует штрихкод для транспортной упаковки (ITF-14). В этом случае штрихкод изначально должен быть 14-значным. Часто программисты ошибаются, пытаясь применить логику EAN-13 к 14-значному числу без учета того, что веса позиций смещаются. Если вы добавите лидирующий ноль к обычному EAN-13, чтобы сделать его 14-значным (формат GTIN), контрольная цифра не изменится, так как ноль при умножении на любой коэффициент даст ноль. Однако расчет функций, приведенных выше, должен это учитывать.

Для кодов SSCC (18 знаков) логика остается той же (Modulo 10), но из-за большой длины данных вероятность ошибки при ручном расчете возрастает. Мы рекомендуем использовать проверенные функции из типовых библиотек (например, БСП — Библиотека Стандартных Подсистем), где расчет штрихкода уже отлажен на миллионах внедрений.

Практические советы

  1. Проверяйте входные данные: перед вычислением контрольного числа убедитесь, что в строке Штрихкод содержатся только цифры. Функция КодСимвола вернет некорректный результат, если в коде окажется пробел или спецсимвол.
  2. Типизация: всегда явно преобразуйте результат в строку, если планируете «склеивать» его с основной частью штрихкода.
  3. Тестирование: возьмите любой брендовый товар под рукой и проверьте его штрихкод через вашу функцию. Если расчет совпал с цифрой на упаковке — алгоритм верен.

Используя приведенные примеры и понимая нюанс с «десяткой», вы сможете избежать ошибок при печати этикеток и обеспечите стабильную работу складского оборудования.

← На главную