Немного личного опыта прикручивания штрих-кодов к 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

 

Hosted by uCoz