Решение задач 1С:Предприятие 8 на примерах

Штрихкод в 1С: контрольная цифра EAN-13, генерация, поиск и печать

АлгоритмыОпубликовано

Штрихкод связывает товар на полке с карточкой в базе. В статье — как рассчитать контрольную цифру EAN-13 и EAN-8 своей функцией, выдать уникальный штрихкод номенклатуре, найти товар по считанному коду запросом, вывести штрихкод в печатную форму и принять данные со сканера. Коротко рассмотрены и другие типы кодов: Code 128, QR, DataMatrix.

Задача: работать со штрихкодами в 1С программно

Штрих код 1С нужен в трёх типичных ситуациях: присвоить товару собственный штрихкод, найти номенклатуру по значению, считанному сканером, и вывести штрихкод на печатную форму — ценник, этикетку, накладную. Встроенных функций платформы для расчёта контрольной цифры нет, поэтому её считают своим кодом или берут из библиотеки стандартных подсистем.

Ниже — расчёт контрольной цифры EAN-13 и EAN-8 с кодом, генерация уникального внутреннего штрихкода, поиск по штрихкоду запросом, вывод картинки в табличный документ, обработка сканера и краткий обзор типов кодов.

Контрольная цифра EAN-13 и EAN-8

Штрихкод EAN-13 состоит из 12 информационных цифр и одной контрольной. EAN-8 — из 7 информационных и одной контрольной. Алгоритм расчёта у них общий: цифры берут справа налево, начиная с младшей информационной; цифры на нечётных позициях умножают на 3, на чётных — на 1; сумму округляют вверх до десятков, и разница даёт контрольную цифру.

// Возвращает контрольную цифру для кода без неё (12 цифр для EAN-13, 7 для EAN-8)
Функция КонтрольнаяЦифраEAN(КодБезКонтрольной) Экспорт

    Сумма = 0;
    Длина = СтрДлина(КодБезКонтрольной);

    Для Позиция = 1 По Длина Цикл
        Цифра = Число(Сред(КодБезКонтрольной, Длина - Позиция + 1, 1));
        Вес = ?(Позиция % 2 = 1, 3, 1);
        Сумма = Сумма + Цифра * Вес;
    КонецЦикла;

    Возврат (10 - Сумма % 10) % 10;

КонецФункции

Проверка на известных кодах: для 400638133393 функция вернёт 1 (получится EAN-13 4006381333931), для 7351353 — 7 (EAN-8 73513537). Проверку корректности целого кода делают на основе той же функции. Перед расчётом убедитесь, что в строке только цифры, иначе Число() вызовет исключение:

Функция ШтрихкодКорректен(Штрихкод) Экспорт

    Длина = СтрДлина(Штрихкод);
    Если Длина <> 13 И Длина <> 8 Тогда
        Возврат Ложь;
    КонецЕсли;

    Для Позиция = 1 По Длина Цикл
        Если СтрНайти("0123456789", Сред(Штрихкод, Позиция, 1)) = 0 Тогда
            Возврат Ложь;
        КонецЕсли;
    КонецЦикла;

    Ожидаемая = Формат(КонтрольнаяЦифраEAN(Лев(Штрихкод, Длина - 1)), "ЧГ=0");
    Возврат Прав(Штрихкод, 1) = Ожидаемая;

КонецФункции

Штрихкод всегда хранят и передают как строку. Если записать его в числовой реквизит, пропадут ведущие нули, а при выводе числа могут появиться разделители групп разрядов.

Генерация уникального штрихкода для номенклатуры

Для товаров без заводского штрихкода используют внутренний код. Стандарт GS1 резервирует префиксы 20–29 для внутреннего использования (в рамках одной торговой организации), поэтому код вида «20 + порядковый номер + контрольная цифра» не пересечётся с заводскими. Главное — получать порядковый номер так, чтобы два пользователя не получили одинаковый: счётчик хранят в константе и читают под блокировкой.

Функция НовыйВнутреннийШтрихкод() Экспорт

    НачатьТранзакцию();
    Попытка
        Блокировка = Новый БлокировкаДанных;
        Блокировка.Добавить("Константа.ПоследнийНомерШтрихкода");
        Блокировка.Заблокировать();

        Номер = Константы.ПоследнийНомерШтрихкода.Получить() + 1;
        Константы.ПоследнийНомерШтрихкода.Установить(Номер);

        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;

    Основа = "20" + Формат(Номер, "ЧЦ=10; ЧВН=; ЧГ=0");  // 12 цифр
    Возврат Основа + Формат(КонтрольнаяЦифраEAN(Основа), "ЧГ=0");

КонецФункции

Полученный штрихкод записывают в регистр сведений с измерением штрихкода и ссылкой на номенклатуру (в типовых торговых конфигурациях он называется «Штрихкоды», в вашей может называться иначе). Сама запись подробно разобрана в статье Запись в регистр сведений программно. Перед записью проверьте, не занят ли код: уникальность значения в регистре гарантируется только уникальностью ключа измерений.

Поиск номенклатуры по штрихкоду

Обычный сценарий — пользователь отсканировал код, и нужно найти товар. Если штрихкоды хранятся в регистре сведений, поиск выглядит так:

&НаСервереБезКонтекста
Функция НайтиНоменклатуруПоШтрихкоду(Штрихкод)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Штрихкоды.Номенклатура КАК Номенклатура,
    |    Штрихкоды.Характеристика КАК Характеристика
    |ИЗ
    |    РегистрСведений.Штрихкоды КАК Штрихкоды
    |ГДЕ
    |    Штрихкоды.Штрихкод = &Штрихкод";
    Запрос.УстановитьПараметр("Штрихкод", СокрЛП(Штрихкод));

    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Новый Структура("Номенклатура, Характеристика", Выборка.Номенклатура, Выборка.Характеристика);
    КонецЕсли;

    Возврат Неопределено;

КонецФункции

Условие по равенству использует индекс по измерению, поэтому поиск работает быстро даже на сотнях тысяч штрихкодов. Условие «ПОДОБНО» для полного штрихкода не нужно. Параметры запроса и обход результата описаны в статье Запросы в 1С.

Проверка на дубли и несколько штрихкодов у товара

У одного товара может быть несколько штрихкодов: для штуки, для упаковки, для разных поставщиков. Поэтому штрихкод — измерение регистра, а номенклатура и характеристика — ресурсы или дополнительные измерения. Чтобы не дать присвоить один код двум товарам, перед записью ищут его в регистре:

&НаСервереБезКонтекста
Функция ШтрихкодЗанят(Штрихкод, ТекущаяНоменклатура)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    Штрихкоды.Номенклатура КАК Номенклатура
    |ИЗ
    |    РегистрСведений.Штрихкоды КАК Штрихкоды
    |ГДЕ
    |    Штрихкоды.Штрихкод = &Штрихкод
    |    И Штрихкоды.Номенклатура <> &Номенклатура";
    Запрос.УстановитьПараметр("Штрихкод", Штрихкод);
    Запрос.УстановитьПараметр("Номенклатура", ТекущаяНоменклатура);

    Возврат Не Запрос.Выполнить().Пустой();

КонецФункции

Такую проверку вызывают из обработчика формы при вводе штрихкода и повторяют в модуле набора записей: пользователь мог обойти форму загрузкой данных. Если одна из ваших задач — массовая загрузка штрихкодов из файла, сначала загрузите их во временную таблицу и проверьте дубли одним запросом.

Печать штрихкода в печатной форме

Обычно картинку штрихкода формирует внешнее средство, а затем её размещают в табличном документе. В конфигурациях на современной библиотеке стандартных подсистем для этого есть готовая генерация: общий модуль ГенерацияШтрихкода (в разных версиях БСП имя и состав могут отличаться) с функциями ПараметрыГенерацииШтрихкода() и ИзображениеШтрихкода(). Функция возвращает структуру с двоичными данными и готовой картинкой. Тип штрихкода и размеры задаются параметрами; числовые коды типов смотрите в описании модуля вашей версии БСП.

Функция КартинкаШтрихкода(Штрихкод)

    Параметры = ГенерацияШтрихкода.ПараметрыГенерацииШтрихкода();
    Параметры.Штрихкод = Штрихкод;
    Параметры.Ширина = 200;
    Параметры.Высота = 80;
    Параметры.ОтображатьТекст = Истина;
    // Параметры.ТипКода — числовой код типа штрихкода из описания модуля

    Результат = ГенерацияШтрихкода.ИзображениеШтрихкода(Параметры);
    Если Результат.Результат Тогда
        Возврат Результат.Картинка;
    КонецЕсли;
    Возврат Неопределено;

КонецФункции

Полученную картинку добавляют в табличный документ как рисунок и позиционируют вручную:

Картинка = КартинкаШтрихкода(Штрихкод);
Если Картинка <> Неопределено Тогда
    Рисунок = ТабДокумент.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
    Рисунок.Картинка = Картинка;
    Рисунок.Лево = 10;
    Рисунок.Верх = 5;
    Рисунок.Ширина = 60;
    Рисунок.Высота = 20;
КонецЕсли;

Если картинка должна быть в конкретном месте макета, в макете создают именованный рисунок (например «Штрихкод»), а в коде подставляют картинку в его свойство. Для готовых решений с оборудованием существует подсистема «Подключаемое оборудование» и внешняя компонента печати штрихкодов: через неё формируют EAN-13, EAN-8, Code128 и QR. Без БСП придётся подключать такую компоненту самостоятельно или рисовать код специальным шрифтом, что для боевых этикеток не рекомендуется — шрифт легко даёт нечитаемый результат.

Сканер штрихкода в форме

Большинство сканеров работают как клавиатура: после считывания они вводят цифры штрихкода и нажимают Enter. В этом случае достаточно поля ввода с обработчиком ПриИзменении — как и любой ввод с клавиатуры, значение попадёт в реквизит формы, а дальше вызывается поиск по коду. Сканеры, подключённые через драйвер оборудования, присылают событие в обработчик ВнешнееСобытие формы:

&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)

    Если Событие = "ScanData" Тогда
        Штрихкод = Данные;  // точный вид данных зависит от драйвера
        ОбработатьШтрихкод(Штрихкод);
    КонецЕсли;

КонецПроцедуры

Имена событий и формат данных определяются драйвером сканера. В конфигурациях с подсистемой «Подключаемое оборудование» события обрабатываются общим способом через модули менеджера оборудования, и писать разбор в каждой форме не нужно.

Типы штрихкодов

ТипЧто кодируетОсобенности
EAN-1312 цифр и контрольнаяОсновной код розничных товаров, у него есть префикс страны/компании
EAN-87 цифр и контрольнаяДля небольшой упаковки
Code 128Цифры, буквы, символыДля внутренних учётных меток, логистики и складов
QR-кодПроизвольный текст, ссылкиПлатёжные документы, ссылки, чеки
DataMatrixДанные с идентификаторами GS1Маркировка товаров, используется для кодов маркировки

С кодами маркировки в формате DataMatrix есть особенность: внутри строки используется разделитель групп (символ с кодом 29), и сканер может выдавать его по-разному. В 1С его получают как Символ(29); при разборе сырой строки учитывайте и этот символ, и возможное отсутствие первого служебного префикса.

Типичные ошибки

  • Хранение штрихкода в числовом реквизите: теряются ведущие нули, появляются пробелы в разрядах.
  • Неправильный порядок весов при расчёте контрольной цифры: вес 3 всегда у младшей информационной цифры, а не у первой слева.
  • Сканер, настроенный на раскладку с другим языком, вводит вместо цифр буквы. Проверьте режим «эмуляция клавиатуры».
  • Лишние пробелы и символ перевода строки в конце считанной строки: применяйте СокрЛП() до поиска.
  • Выдача одинаковых внутренних кодов при одновременной работе — счётчик без блокировки.
  • Принять заводской UPC-A (12 цифр) за EAN-13: для запроса к регистру обе формы приводят к одной длине, добавляя ведущий ноль.

Актуальность для новых версий

Расчёт контрольной цифры и поиск по регистру не зависят от версии платформы и работают в любом релизе 8.3. Готовая генерация изображения штрихкода есть в библиотеке стандартных подсистем (в 3.1 и новее), но имена общих модулей и параметров в разных версиях БСП отличаются, поэтому перед использованием сверьтесь с составом модуля в вашей конфигурации. Состав подсистемы «Подключаемое оборудование» и поддерживаемые драйверы сканеров также зависят от конфигурации.

Частые вопросы

Как рассчитать контрольную цифру EAN-13 в 1С?

Возьмите 12 цифр справа налево, умножайте цифры на нечётных позициях на 3, на чётных на 1, сложите. Контрольная цифра равна (10 минус остаток суммы от деления на 10) по модулю 10. Готовая функция приведена в статье.

Какой префикс использовать для внутреннего штрихкода?

Для внутреннего использования внутри организации стандарт GS1 резервирует префиксы 20–29. Код вида «20» плюс порядковый номер и контрольная цифра не пересекается с заводскими кодами.

Как найти номенклатуру по штрихкоду?

Выполните запрос к регистру сведений со штрихкодами с условием равенства по значению штрихкода и параметром запроса. Штрихкод передавайте как строку, предварительно обрезав пробелы.

Как вывести штрихкод на печатную форму?

Получите картинку штрихкода из БСП или внешней компоненты печати и добавьте её в табличный документ как рисунок или подставьте в именованный рисунок макета.

Процедуры и функции в 1С: синтаксис, параметры, экспорт и общие модули

Алгоритмы

Разбор процедур и функций встроенного языка 1С: отличия, параметры, возврат нескольких значений, экспортные методы, флаги общих модулей, рекурсия и динамическое выполнение кода.

Конфигуратор 1С для программиста: как зайти, полезные функции и горячие клавиши

Алгоритмы

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

Регистры в 1С: виды регистров и движения документа по регистру накопления

Алгоритмы

Разбор видов регистров 1С и того, какой из них выбрать для задачи, с примерами кода: как документ делает движения по регистру накопления, как контролировать остатки и читать данные виртуальными таблицами.

Расширение конфигурации 1С: создание, установка и перехват методов

Алгоритмы

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