Как организовать скоростную печать этикеток в 1С без потери данных при сканировании?

Программист 1С v8.3 (Управляемые формы) Промышленность, строительство и АПК
← На главную

В условиях реального производства часто возникает ситуация, которую можно назвать режимом «автомата Калашникова»: оператор стоит на линии и непрерывно сканирует штрихкоды, ожидая мгновенного выхода этикетки. Однако стандартные механизмы 1С часто не справляются с таким темпом. Проблема заключается в том, что формирование макета этикетки — процесс ресурсоемкий. Пока система занята рендерингом одного штрихкода, событие от COM-порта или сканера может быть проигнорировано, и «пики» уходят в пустоту. Разберем, как построить надежную архитектуру печати, которая не теряет ни одного задания.

Анализ проблемы: почему 1С «пропускает» сканирование

Когда мы работаем напрямую через событие ВнешнееСобытие, 1С выполняет код последовательно. Если обработка одного сканирования (запрос к базе, формирование табличного документа, отправка на принтер) занимает 1–2 секунды, а оператор «пикает» три штрихкода за это же время, драйвер оборудования может не успеть передать данные в занятый поток 1С. Результат — пропуски в печати и недовольство персонала.

Решение 1: Асинхронная очередь через регистр сведений

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

  1. Создадим РегистрСведений.ОчередьПечатиЭтикеток.
  2. В процедуре ВнешнееСобытие пропишем только одну быструю операцию — запись полученного штрихкода в этот регистр.
  3. Создадим РегламентныеЗадания, которые будут периодически опрашивать регистр и отправлять данные на печать.

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


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

Важный момент: использование объекта БлокировкаДанных гарантирует, что второе фоновое задание не прочитает те же записи, пока первое их не пометит. Выбирая записи небольшими порциями (ВЫБРАТЬ ПЕРВЫЕ 10), мы обеспечиваем параллелизм и высокую скорость реакции системы.

Решение 2: Оптимизация формирования макета (ZPL/EPL)

Одной из главных причин тормозов является формирование ТабличныйДокумент. 1С тратит время на расчет шрифтов, отступов и генерацию графики. Промышленные принтеры этикеток (Zebra, TSC, Datamax) «понимают» специализированные языки разметки, такие как ZPL или TSPL.

Вместо передачи картинки, мы можем отправить в порт принтера простую текстовую строку. Выясним преимущества этого метода:

Пример формирования команды ZPL в коде 1С:


ТекстКоманды = "^XA
               |^FO50,50^A0N,36,36^FDТовар: " + НаименованиеТовара + "^FS
               |^FO50,100^BY3^BCN,100,Y,N,N^FD" + Штрихкод + "^FS
               |^XZ";
// Отправка ТекстКоманды напрямую в COM-порт или через драйвер

Решение 3: Пакетная печать

Проанализируем еще один подход — объединение заданий. Если технологический процесс позволяет небольшую задержку (например, 5–10 секунд), можно накапливать отсканированные коды и печатать их не по одному, а одним общим документом. Это существенно снижает накладные расходы на инициализацию принтера и обращение к спулеру печати Windows. Как было отмечено в обсуждении, «плюнуть разом 50 этикеток» гораздо эффективнее, чем 50 раз по одной.

Решение 4: Аппаратный принт-сервер (MOXA)

Если принтеров несколько, а физические COM-порты на сервере ограничены или работают нестабильно, целесообразно использовать преобразователи интерфейсов типа MOXA NPort. Это устройство позволяет вынести принтер в любую точку локальной сети и обращаться к нему по IP-адресу.

С точки зрения 1С, такой принтер все равно выглядит как COM-порт или сетевое устройство, но использование MOXA позволяет:

Итоговые рекомендации

Для создания действительно надежной системы в режиме «нон-стоп» рекомендуем совместить подходы:

  1. Использовать РегистрСведений как буфер для мгновенного приема данных от сканера.
  2. Внедрить ФоновыеЗадания для обработки этого буфера, используя БлокировкаДанных для исключения дублей.
  3. Перейти от тяжелых макетов 1С к прямой отправке команд на языке принтера (ZPL/TSPL).
  4. При больших объемах использовать сетевые принт-серверы для стабилизации связи с оборудованием.

Такая архитектура позволит вашим сотрудникам работать максимально быстро, не оглядываясь на «задумчивость» системы 1С.

← На главную