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

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

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

1. Организация хранения штрихкодов в базе данных

Перед написанием логики обработки необходимо определиться со структурой метаданных для хранения штрихкодов. Выделим два основных подхода:

  1. Реквизит справочника Номенклатура: подходит для предельно простых учетных систем, где каждому элементу номенклатуры строго соответствует только один штрихкод, и учет по характеристикам или упаковкам отсутствует. В этом случае у реквизита Штрихкод (тип Строка) обязательно следует установить свойство Индексировать (или Индексировать с доп. упорядочиванием) для быстрого поиска запросом без полного сканирования таблицы.
  2. Регистр сведений «Штрихкоды»: стандартный и универсальный подход. Измерением регистра выступает Штрихкод (тип Строка), а ресурсами — Номенклатура, Характеристика и Упаковка. Регистр автоматически индексирует измерения и позволяет привязывать к одной позиции номенклатуры множество различных кодов (например, разные партии, фасовки или коды производителей).

2. Режимы работы сканера: эмуляция клавиатуры против COM-порта

При подключении сканера через USB существует два принципиально разных сценария работы оборудования:

Режим клавиатуры (HID / разрыв клавиатуры): сканер определяется операционной системой как обычная клавиатура и передает считанную последовательность символов в текущий активный элемент интерфейса.

Проанализируем подводные камни этого режима:

  1. Зависимость от раскладки: если штрихкод содержит буквы (Code 128) или сканируется маркировка, а на компьютере включена русская раскладка, данные будут искажены кириллическими символами.
  2. Случайная порча данных: если перед считыванием фокус ввода находился в реквизите Количество или Сумма, считанный штрихкод будет напечатан прямо в это поле.
  3. Проблемы при работе по RDP: при нестабильном сетевом канале символы могут «проглатываться» или приходить с задержкой.
  4. Невозможность работы с маркировкой («Честный Знак»): в кодах DataMatrix используется непечатаемый разделитель групп GS (ASCII 29), который драйвер клавиатуры чаще всего отсекает.

Режим эмуляции COM-порта (USB-COM / Virtual Serial Port / Native API): сканер переключается сервисным штрихкодом в режим виртуального последовательного порта. При считывании штрихкода данные перехватываются драйвером или компонентой и генерируют в форме событие ВнешнееСобытие независимо от того, где находится курсор.

3. Программная реализация: быстрый поиск без сложных драйверов

Если требуется реализовать ввод штрихкода в режиме клавиатуры без подключения «Библиотеки подключаемого оборудования» (БПО), наиболее стабильным решением является использование горячей клавиши и диалога ввода строки. В сканере программируется префикс (например, клавиша F7) и суффикс (Enter). При нажатии горячей клавиши открывается окно ввода, куда сканер сразу же вставляет код и подтверждает ввод.

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

На стороне клиента вызываем диалог ввода:


&НаКлиенте
Процедура ПоискПоШтрихкоду(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеВводаШтрихкода", ЭтотОбъект);
    ПоказатьВводСтроки(Оповещение, "", НСтр("ru = 'Отсканируйте или введите штрихкод'"));
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаШтрихкода(Результат, ДополнительныеПараметры) Экспорт
    
    // Если пользователь отменил ввод или строка пустая
    Если Не ЗначениеЗаполнено(Результат) Тогда
        Возврат;
    КонецЕсли;
    
    ШтрихкодОчищенный = СокрЛП(Результат);
    
    // Вызываем серверную функцию для поиска номенклатуры
    ДанныеНоменклатуры = НайтиНоменклатуруПоШК(ШтрихкодОчищенный);
    
    Если ДанныеНоменклатуры = Неопределено Тогда
        ПоказатьПредупреждение(, НСтр("ru = 'Товар со штрихкодом '") + ШтрихкодОчищенный + НСтр("ru = ' не найден!'"));
        Возврат;
    КонецЕсли;
    
    // Добавляем или обновляем строку в табличной части
    СтрокаТовара = Объект.Товары.Добавить();
    СтрокаТовара.Номенклатура = ДанныеНоменклатуры.Ссылка;
    СтрокаТовара.Количество = 1;
    СтрокаТовара.Цена = ДанныеНоменклатуры.Цена;
    СтрокаТовара.Сумма = СтрокаТовара.Количество * СтрокаТовара.Цена;
    
КонецПроцедуры

Опишем серверную функцию поиска. Выполним запрос к справочнику Номенклатура (или к регистру сведений, если штрихкоды вынесены в отдельную таблицу):


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

4. Подключение через ВнешнееСобытие и Native API

Если для работы выбран режим эмуляции COM-порта с драйвером подключаемого оборудования, обработка сигнала сканера на управляемой форме строится через предопределенный обработчик ВнешнееСобытие:


&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
    
    // Проверяем тип события от сканера штрихкода
    Если Событие = "BarCodeValue" Или Событие = "Штрихкод" Тогда
        СчитанныйШтрихкод = СокрЛП(Данные);
        // Передаем штрихкод в процедуру добавления позиции
        ОбработатьСчитанныйШтрихкод(СчитанныйШтрихкод);
    КонецЕсли;
    
КонецПроцедуры

Важно помнить о технических особенностях работы внешних компонент:

  1. Разрядность платформы: разрядность библиотеки драйвера (32 или 64 бита) должна в точности совпадать с разрядностью запущенного клиента 1С.
  2. Освобождение порта: при использовании прямого подключения к COM-порту соединение необходимо корректно закрывать при закрытии формы (обработчик ПриЗакрытии), иначе порт останется заблокированным для других окон и приложений.
← На главную