Немного личного опыта
прикручивания штрих-кодов к 1С.
В начале немного теории:
Любой одномерный
штрих-код, это распечатка специальным, полосатым шрифтом информации, закодированной по
правилам принятым для данного
штрих-кода (бар-код). Этот полосатый шрифт представляет каждый символ в виде 8
вертикальных, черных или белых полосок, которые могут сливаться. Коды всех
десятичных цифр составлены так, что в результате слияния черных или белых
полосок, в каждом из них число видимых элементов всегда составляет 4.
Например, если рассмотреть цифру "4" в виде штрих-кода, то одним из
вариантов ее кодированного отображения будет выглядеть как "0100111"
Самый используемый в
торговле штрих-код, это конечно EAN/UPC.
13 – означает число
символов, которое содержит код.
EAN – это название
добровольной некоммерческой международной организации, состоящей из
Национальных организаций в более чем 100 странах мира. За каждой страной в коде
закреплен префикс из трех первых цифр. Для России это пространство 460-469.
UPC – это
подмножество кодировки EAN-13, где первое число всегда 0.
Популярность кода
объясняется тем, что он надежен и универсален:
- его можно сканировать повернутым на 180 градусов или инвертированным, сканер все
равно вернет верный код.
- если изображение не
удается считать сканером, код можно ввести врукопашную, причем ввести его
неправильно мало шансов – последнее число в коде, это функция от первых 12
чисел.
Устойчивость кода к ротации
и ошибкам при вводе, объясняется его хитрой структурой.
Чтобы понять, как работает
кодирование в EAN-13 лучше всего рассмотреть
конкретный пример:
Например,
нужно распечатать штрих-код в EAN-13 следующий код: 120000003105.
Складываются все нечетные
цифры 1+0+0+0+3+0=4,
затем четные 2+0+0+0+1+5=8 и умножаем на 8*3=24
Складываем два результата: 24+4=28
Контрольное число есть разница между ближайшим числом, кратным
10 и полученным выше результатом. Короче говоря, из 10 вычесть младшее число из
последнего результата, в нашем случае 10-8=2.
Часть хитрости заключатся
в особом представлении данных шрифтом EAN-13.
Обо всем по порядку:
Во первых, всякий код EAN-13 разбит на части служебными
символами - двойными полосками. Они нужны сканеру для определения начала,
середины и конца штрих-кода:
Левый LGP и правый RGP символ (!), средний CGP это тире (-):
(важное замечание: некоторые ортодоксальные
служители культа утверждают, что штрих-код содержит нехорошее число 666. Все из-за того, что число 6 кодируется
в виде двух тонких полосок, так же как и разделительные символы. Получается,
что 3 служебных символа это плохо замаскированные
шестерки. Бе видети се зело страшно…)
Если взять и просто записать шрифтом EAN-13 наш бар-код со служебными
символами 1!200000-031052!, то получим
такую картину:
Вроде все правильно, и циферки под полосками соответствуют коду.
Можно даже распечатать этот код и попробовать считать сканером,
но скорей всего ничего не получится.
Дело в том, что все устроено немного сложнее.
13 цифр кода разбиты на две части: 7 цифр до разделительного
символа (левое) и 6 после (правое). При этом для
сканера код является симметричным. Первое число в коде не имеет полосок.
Получается, что сканер считывает только 12 символов.
Как формируется съедобный для сканера код, и как он
восстанавливает недостающий символ подробно описано чуть ниже.
Вторая часть
хитрости:
В зависимости от того, где стоит число, оно кодируется по одному
из трех правил: A,
B и C
Таблица правил кодирования:
|
set A |
set B |
set С |
0 |
001101 |
100111 |
1110010 |
1 |
011001 |
110011 |
1100110 |
2 |
010011 |
011011 |
1101100 |
3 |
111101 |
100001 |
1000010 |
4 |
100011 |
011101 |
1011100 |
5 |
110001 |
111001 |
1001110 |
6 |
101111 |
000101 |
1010000 |
7 |
111011 |
010001 |
1000100 |
8 |
110111 |
001001 |
1001000 |
9 |
001011 |
010111 |
1110100 |
Если смотреть на символы
соответствующие кодам это таблицы, то будет видно, что все символы левой части
выводятся в верхнем регистре, правой в нижнем.
·
Правая
часть (использует set C)
Все просто: числа превращаются в
символы в нижнем регистре 0-a, 1-b,
2-c, 3-d и т.д.
Было 031052 - стало adbafc.
·
Левая
часть (использует set A и set B)
Лирическое отступление: Изначально, кодировка UPC, на которой построен
EAN была 12-ти символьной. Для расширения
кодировки, при сохранении совместимости, применен метод кодирования 13-того
символа (коде он первый по счету) с помощью комбинаций правил set A и set B, для первых шести символов от LGP до CGP.
Вот таблица, по которой кодируется 13-тый (первый по счету)
символ:
Доп. символ |
1-я цифра |
2-я цифра |
3-я цифра |
4-я цифра |
5-я цифра |
6-я цифра |
0 |
A |
A |
A |
A |
A |
A |
1 |
A |
A |
B |
A |
B |
B |
2 |
A |
A |
B |
B |
A |
B |
3 |
A |
B |
B |
B |
B |
A |
4 |
A |
B |
A |
A |
B |
B |
5 |
A |
B |
B |
A |
A |
B |
6 |
A |
B |
B |
B |
A |
A |
7 |
A |
B |
A |
B |
A |
B |
8 |
A |
B |
A |
B |
B |
A |
9 |
A |
B |
B |
A |
B |
A |
Если посмотреть на любой штрих-код то видно, что полосок над ним нет. Сканер
восстанавливает его на основании той же таблицы, и на выходе выдает полный 13ти
значный код.
Применив правила преобразования для
левой и правой части кода получаем:
(левая часть)1200000 = $20A0AA (правая часть)031052 = adbafc.
Дополняем служебными символами: (LGP)(левая часть)(CGP)(правая часть)(RGP) и бар-код готов к распечатке:
Небольшое замечание, если для левой части кода усложнить правила
кодирования, как для правой (например А+С), то можно
будет закодировать еще один 14-тый символ. При этом сохранится совместимость с
существующей кодировкой.
Про формирование EAN-13 в 1С.
Научить 1С
формировать штрих-коды для
последующей их распечатки, не просто, а очень просто. Если под рукой есть
Интернет. Вот испытанная функция, которая осуществляет преобразование кода в
пригодный для печати вид:
Функция глСформироватьБарКодEAN13(код) Экспорт
ПервыйФлаг
= Число(Сред(код,1,1));
левстр = Сред(код,2,6);
правстр = Сред(код,8,6);
правкод = "";
Для Поз = 1 По 6
Цикл
правкод
= правкод + ЦифрыВБуквыНижнегоРегистра(Сред(правстр,Поз,1));
КонецЦикла;
// Формируем левую часть
кода в зависимости от значения ПервыйФлаг
Если ПервыйФлаг = 0
Тогда //••• 0 ••• AAAAA •••
левкод
= "#!"+Лев(левстр,1)+Сред(левстр,2,1)+Сред(левстр,3,1)+Сред(левстр,4,1)+Сред(левстр,5,1)+
Сред(левстр,6,1);
ИначеЕсли ПервыйФлаг = 1
Тогда //••• 1 ••• AABABB •••
левкод
= "$!"+Лев(левстр,1)+Сред(левстр,2,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+
Сред(левстр,4,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,5,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,6,1));
ИначеЕсли ПервыйФлаг = 2
Тогда //••• 2 ••• AABBAB •••
левкод
= "%!"+Лев(левстр,1)+Сред(левстр,2,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,4,1))+Сред(левстр,5,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,6,1));
ИначеЕсли ПервыйФлаг = 3
Тогда //••• 3 ••• AABBBA •••
левкод
= "&!"+Лев(левстр,1)+Сред(левстр,2,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,4,1))+ЦифрыВБуквыВерхнегоРегистра(Сред
(левстр,5,1))+Сред(левстр,6,1);
ИначеЕсли ПервыйФлаг = 4
Тогда //••• 4 ••• ABAABB •••
левкод
= "'!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+Сред(левстр,3,1)+
Сред(левстр,4,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,5,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,6,1));
ИначеЕсли ПервыйФлаг = 5
Тогда //••• 5 ••• ABBAAB •••
левкод
= "(!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+Сред(левстр,4,1)+Сред(левстр,5,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,6,1));
ИначеЕсли ПервыйФлаг = 6
Тогда //••• 6 ••• ABBBAA •••
левкод =
")!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+ЦифрыВБуквыВерхнегоРегистра(Сред
(левстр,4,1))+Сред(левстр,5,1)+Сред(левстр,6,1);
ИначеЕсли ПервыйФлаг = 7
Тогда //••• 7 ••• ABABAB •••
левкод
= "*!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+Сред(левстр,3,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,4,1))+Сред(левстр,5,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,6,1));
ИначеЕсли ПервыйФлаг = 8
Тогда //••• 8 ••• ABABBA •••
левкод
= "+!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+Сред(левстр,3,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,4,1))+ЦифрыВБуквыВерхнегоРегистра(Сред
(левстр,5,1))+Сред(левстр,6,1);
ИначеЕсли ПервыйФлаг = 9
Тогда //••• 9 ••• ABBABA •••
левкод
= ",!"+Лев(левстр,1)+ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,2,1))+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,3,1))+Сред(левстр,4,1)+
ЦифрыВБуквыВерхнегоРегистра(Сред(левстр,5,1))+Сред(левстр,6,1);
КонецЕсли;
// Возвращаем результат
кодстр = левкод + "-" + правкод + "!";
Возврат кодстр;
КонецФункции
Про сканирование.
В 1С 7.7 в меню сервис есть
закладка “Торговое оборудование” где настраиваются сканеры и прочая торговая ерунда.
Причем для работы предлагаемых в списке девайсов,
требуются соответствующие внешние компоненты, которых в комплексной поставке
нет.
Т.е. имеет смысл сделать
свой обработчик и свою компоненту.
К счастью, сейчас писать с
нуля ничего не надо, все уже написано до нас. В Интернете полно компонент для
работы с различными сканерами.
Одна из популярных компонент
для работы со сканером через COM порт под
1С: это vk_rs232.dll.
Написана на Делфях, работет отлично, но имеет, пожалуй, всего один недостаток:
если отсутствует указанный порт, в 1С вместо ошибки порта, выдает файловую
ошибку (чем сбивает с толку). При работе через USB эмулятор СОМ порта это немного напрягает, т.к.
номера портов имеют свойство меняться при подключении.
Работает все это так:
При запуске глобальник как обычно отрабатывает предопределенную
процедуру
Процедура ПриНачалеРаботыСистемы()
которая помимо своих обычных дел пытается загрузить внешнюю
компоненту
глЗагрузитьВнешнююКомпоненту("vk_rs232")
и если файл существует и
компонента зарегистрирована в реестре, для нее создается объект. (Если бы 1С не
умела бы работать с внешними компонентами, интересно как бы к ней тогда
прикручивали сканер?)
rs232=СоздатьОбъект("AddIn.vk_rs232");
через этот объект отдаются
команды внешней компоненте на открытие порта (а еще в порт можно записывать
строку и закрывать порт).
rs232.ОткрытьПорт("COM3");
rs232.КонецСтроки=Симв(13);
Конец строки
нужен для определения конца штрих-кода, у разных сканеров может быть свой код
окончания строки (обычно это символ перевода каретки – (13)).
Указанный порт
оживает со стандартными настройками, которые впрочем, тоже можно подкрутить из прямо из 1С, и начинает слушать сканер.
Сканер прочтя штрих-код восстанавливает первое
число в коде, проверяет его, и передает компоненте строку из 13 чисел.
Компонента, в свою очередь, вызывает обработчик внешних событий 1С.
Процедура ОбработкаВнешнегоСобытия(Источник,Событие,Данные)
Где Источник=vk_rs232 Событие=BarCodeValue Данные=13ти значный
код
Что делать в 1С
с полученными данными, зависит от конкретной задачи.
Если планируется
задействовать штрих-коды во внутреннем учете, то следует учесть что первое
число в коде должно быть 0 или 1, если мы не хотим вторгаться в пространство
кодов, зарегистрированных в EAN за различными странами. Цифру 2, которая по идее и должна
использоваться для внутреннего кодирования, я бы использовать не стал, т.к.
часто используется в торговле.
На картинке
изображен набросок внутреннего кодирования Документов и Справочников на
предприятии:
Итак, осталось написать
обработку, которая по заданным полям будет определять, что отсканировано,
находить его по коду и что-то с ним делать.
Вот пример того, как по
чертежу детали можно быстро найти ее (деталь) в справочнике, чтобы узнать на
каких складах она наличествует и в каком количестве:
Окно вызванной обработки:
В обработку можно добавить
списание или приходование, открытие файла, ну или
чего там нужно в зависимости от конкретной задачи. Короче непаханое поле для
автоматизации.
Работа кладовщика, при
внедрении штрих-кодирования становится похожей на
работу кассира в супермаркете. Т.е. чисто теоретически, скорость списания должна
возрасти на порядок, а ошибки сократиться до нуля.
Выгода от внедрения штрих-кодирования в производстве очевидна – это устранение
ошибок в вводе данных, при ускорении ввода этих
данных.
Стоимость лазерного сканера
~100$, принтер для печати наклеек штрих-кодов ~500$.
Затраты на внедрение = расчетная сумма*n. Где n-функция
от времени (чем дольше тем больше).
Тестовая БД, которая умеет
формировать бар-код для элементов справочника Номенклатура, а также считывать
этот код обратно и делать запрос по остаткам, лежит тут: 1C77_RS232.rar
Шрифт EAN: EanBwrP36Tt_Normal.rar