Сегодня сложно представить автоматизацию продаж без сканера штрихкода. Сканеры бывают разных видов. Самый простой из них – клавиатурный. При чтении штрихкода клавиатурный сканер эмулирует нажатие клавиш на клавиатуре. В этой видимой простоте понимания его работы кроется искушение его купить, ведь для подключения такого сканера не требуется драйвер, и если вспомнить, что к кнопкам на форме в 1С можно привязывать клавиши, то вырисовывается возможность использовать единый программный модуль и для работы пользователя со сканером, и с клавиатурой. Достаточно поместить на форму кнопки с цифрами и привязать к ним обработчик нажатия.
Но возникает два вопроса, первый – как определить, что работает сканер, а не пользователь мышкой нажимает кнопки? Второй связан с первым: как отследить окончания ввода данных со сканера?
Клавиатурный сканер – веселое устройство, особенно, если он дешевый, такой как Chiperlab 1000. Программы вроде 1С вообще не отличают сигналы от него и от клавиш на клавиатуре. При этом бывают чисто клавиатурные сканеры, и бывают usb-сканеров с возможностью подключения в разрыв клавиатуры. Со вторыми более-менее проще: достаточно поставить эмулятор com-порта, и за работу сканера начинает отвечать драйвер. Но чисто клавиатурный сканер такого сделать не позволяет, и для того, чтобы понять, откуда пришли данные, со сканера или с клавиатуры, и требуется бубен.
Будем исходить из того, что данные от сканера приходят пакетом, а промежуток между нажатием клавиш с клавиатуры вручную достаточно большой. Таким образом, мы можем допустить, если пользователь вводит цифры с интервалом менее 300 миллисекунд, то скорее всего он читает штрихкод сканером. Таким образом, нам достаточно отслеживать промежуток между «нажатием» кнопок на нашей форме, чтобы определить, что делает пользователь: вводит ли он данные мышьй, с клавиатуры, или пользуется сканером. Пока данные поступают с малым интервалом, будем записывать их в стек, а впоследствии обрабатывать.
Нам потребуется аналог функции «ТекущаяДата», с точностью до миллисекунды. В 1С такой функции нет, но есть возможность использования скриптов.
Перем JScript; … Процедура ПриОткрытии() Попытка JScript = Новый COMОбъект("MSScriptControl.ScriptControl"); Исключение JScript = Неопределено; КонецПопытки; Если JScript<>Неопределено Тогда JScript.Language="JScript"; JScript.AddCode("
|function CurrentDate()
|{
| d = new Date()
| return d.getTime();
|}
|"); КонецЕсли; КонецПроцедуры Функция ПолучитьТекущееВремя(Интервал) Если JScript = Неопределено Тогда Интервал =2; Возврат ТекущаяДата(); КонецЕсли; Интервал =300; // 300 мс. паузы считаются окончание ввода и инициируют обработку стека Возврат JScript.run("CurrentDate"); КонецФункции
Теперь повесим простой обработчик нажатия кнопки с цифрами:
Перем Стек; Перем ДлинаСтека; Перем ВремяСтека; … Процедура НажатСимвол(Элемент) Если Стек.Количество()=ДлинаСтека Тогда Стек.Добавить(Элемент.Заголовок); Иначе Стек[ДлинаСтека]=Элемент.Заголовок; КонецЕсли; ДлинаСтека=ДлинаСтека+1; ВремяСтека=ПолучитьТекущееВремя(); КонецПроцедуры … ДлинаСтека=0; Стек=Новый Массив; ВремяСтека=Неопределено;
Осталось назначить на таймер некий обработчик, который определяет, завершился ли ввод, и если завершился, обрабатывает стек.
Процедура ОбработатьСтек() Если ДлинаСтека=0 Тогда Возврат; КонецЕсли; Слово=""; Для К=0 По ДлинаСтека-1 Цикл Слово = Слово +Стек[К]; КонецЦикла; Если ДлинаСтека = 13 Тогда ОбработатьВведенныйШтрихкод(Слово); Иначе ОбработатьВведенноеЧисло(Слово); КонецЕсли; КонецПроцедуры Процедура ПриОжидании() Перем Интервал; Если ВремяСтека = Неопределено Тогда Возврат; КонецЕсли; ТекВремя=ПолучитьТекущееВремя(Интервал); Если (ТекВремя-ВремяСтека)> Интервал Тогда ВремяСтека=Неопределено; ОбработатьСтек(); КонецЕсли; ПодключитьОбработчикОжидания("ПриОжидании",0.1,Истина); КонецПроцедуры Процедура ПриОткрытии() … ПодключитьОбработчикОжидания("ПриОжидании",0.1,Истина); КонецПроцедуры
Вот и вся теория. Как видите, ничего сложного. Но бубен нам пока убирать рано, потому что на практике приведенный метод работать скорее всего не будет по весьма банальной причине: 1С просто не успевает отрабатывать поток цифр, поступающий от сканера. Решается эта проблема «замедлением» работы сканера, благо – с помощью настроечных штрихкодов можно установить его скорость. И вот тут и проявляется вся забавность клавиатурного сканера в связке с 1С: для того, чтобы 1С не проглатывало все введенные с него цифры, сканер должен работать достаточно медленно. И вряд ли вашим клиентам понравится, что штрихкод в 13 символов вводится в течение нескольких секунд. (1С версии 7.7 допускало более быструю скорость работы). И это – только первая проблема. В какой-то момент пользователи, увидев на форме кнопочки, так напоминающие дополнительную цифровую клавиатуру, захотят воспользоваться ей, и вам придется использовать не цифровые клавиши, а те, которые начинаются с Num. Это в свою очередь вновь потребует программирования сканера. Но самое неприятное даже не все это. Если на вашей форме расположена таблица значений или поле ввода, то однажды этот элемент формы может стать активным, и тогда сканер весь поток цифр направит в него…
И в результате мы приходим к простому выводу: при работе с клавиатурным сканером в 1С лучше всего использовать модальный режим и обычное поле ввода. А лучше вообще не использовать дешевые «чиперы».
Конечно, я бы мог написать этот вывод в самом начале, но тогда бы вы мне не поверили, да и статьи бы не было :)