При автоматизации ввода данных, например, при работе со сканером штрихкодов, часто возникает задача ускорить процесс. Стандартное поведение платформы 1С — переход на следующую ячейку в той же строке после ввода значения. Однако для потокового ввода требуется, чтобы после заполнения ключевой ячейки (например, штрихкода) система автоматически создавала новую строку и делала ее активной для следующего сканирования. Рассмотрим пошагово, как реализовать такой механизм в управляемых формах.
Проанализируем ситуацию: у нас есть документ с табличной частью. При сканировании штрихкода в первую колонку нужно, чтобы курсор автоматически переместился на новую, только что созданную строку, в ту же самую колонку, готовую к вводу следующего штрихкода.
Первоначальная попытка: добавление строки
Первая мысль — в обработчике события ПриИзменении для поля со штрихкодом добавить новую строку в табличную часть. Также можно добавить дополнительную логику, например, заполнить некоторые поля данными из предыдущей строки или найти номенклатуру по штрихкоду.
Посмотрим на первоначальный код:
&НаКлиенте
Процедура ТаблицаШтрихкодовШтрихкодПриИзменении(Элемент)
// Получаем текущую строку данных
Строка = Элементы.ТаблицаШтрихкодов.ТекущиеДанные;
// Копируем склад из предыдущей строки для удобства
Если Строка.НомерСтроки > 1 Тогда
Строка.Склад = Объект.ТаблицаШтрихкодов[Элементы.ТаблицаШтрихкодов.ТекущиеДанные.НомерСтроки-2].Склад;
КонецЕсли;
// Заполняем данные по штрихкоду
Строка.Номенклатура = ПолучитьНоменклатуру(Строка.Штрихкод);
Строка.Количество = 1;
// Добавляем новую пустую строку
НоваяСтрока = Объект.ТаблицаШтрихкодов.Добавить();
КонецПроцедуры
Проблема: Этот код успешно добавляет новую строку, но курсор после нажатия Enter переходит на следующую ячейку в текущей, уже заполненной строке, а не на новую.
Второй шаг: позиционирование на новой строке
Чтобы переместить курсор на последнюю добавленную строку, нужно программно установить ее как текущую для элемента формы. Для этого можно использовать свойство ТекущаяСтрока элемента таблицы. Так как мы только что добавили строку, ее индекс будет равен Количество() - 1.
Создадим для этого отдельную процедуру и вызовем ее после добавления строки.
&НаКлиенте
Процедура УстановитьПоследнююТекущуюСтроку()
// Получаем количество строк. Если строк нет, текущей будет 0 (неопределено).
// Иначе - последняя строка с индексом Количество-1.
Элементы.ТаблицаШтрихкодов.ТекущаяСтрока = ?(Объект.ТаблицаШтрихкодов.Количество() = 0, Неопределено, Объект.ТаблицаШтрихкодов[Объект.ТаблицаШтрихкодов.Количество()-1].ПолучитьИдентификатор());
КонецПроцедуры
Теперь вызовем эту процедуру в основном обработчике:
&НаКлиенте
Процедура ТаблицаШтрихкодовШтрихкодПриИзменении(Элемент)
// ... (код заполнения текущей строки) ...
НоваяСтрока = Объект.ТаблицаШтрихкодов.Добавить();
// Устанавливаем курсор на новую строку
УстановитьПоследнююТекущуюСтроку();
КонецПроцедуры
Проблема: Стало лучше! Теперь новая строка выделяется, но ячейка в ней не активна для редактирования. Пользователю все равно нужно сделать дополнительный клик или нажать Enter, чтобы начать ввод, что нарушает автоматизацию.
Третий шаг: активация ячейки для редактирования
Чтобы перевести ячейку в режим редактирования, можно сэмулировать нажатие клавиши Enter. Для этого используется COM-объект WScript.Shell. Важно: этот код должен выполняться строго на клиенте, так как он взаимодействует с интерфейсом операционной системы пользователя. Попытка выполнить его на сервере приведет к ошибке.
Создадим процедуру для эмуляции нажатия:
&НаКлиенте
Процедура ОткрытьЯчейкуДляРедактирования()
Shell = Новый COMОбъект("Wscript.Shell");
Shell.SendKeys("{ENTER}");
КонецПроцедуры
Теперь у нас есть все компоненты. Однако возникает вопрос: в какой момент их вызывать?
Четвертый шаг: выбор правильного события
Событие ПриИзменении срабатывает после того, как ввод в ячейке завершен (например, по нажатию Enter или потере фокуса). Для нашей задачи, особенно если штрихкод имеет фиксированную длину и вводится без суффикса Enter, нужно отслеживать сам процесс ввода. Для этого идеально подходит событие поля ввода ИзменениеТекстаРедактирования.
Это событие срабатывает при каждом изменении текста в поле ввода и позволяет анализировать введенный текст в реальном времени.
Итоговое решение: собираем все вместе
Объединим все наработки в обработчике события ИзменениеТекстаРедактирования для колонки "Штрихкод". Предположим, что длина нашего штрихкода — 11 символов. Как только длина введенного текста превысит 10, мы запускаем наш механизм.
&НаКлиенте
Процедура ТаблицаШтрихкодовШтрихкодИзменениеТекстаРедактирования(Элемент, Текст, СтандартнаяОбработка)
// Проверяем, достигла ли длина текста нужного значения (например, 11 символов)
Если СтрДлина(Текст) > 10 Тогда
// Сначала нужно завершить редактирование текущей ячейки,
// чтобы значение записалось. Можно это сделать, передав фокус другому элементу,
// но в данном случае логика добавления новой строки и так прервет редактирование.
// Добавляем новую строку в данные формы
НоваяСтрока = Объект.ТаблицаШтрихкодов.Добавить();
// Устанавливаем фокус на эту новую строку в элементе формы
УстановитьПоследнююТекущуюСтроку();
// Эмулируем нажатие Enter, чтобы активировать ячейку для редактирования
ОткрытьЯчейкуДляРедактирования();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура УстановитьПоследнююТекущуюСтроку()
Элементы.ТаблицаШтрихкодов.ТекущаяСтрока = Объект.ТаблицаШтрихкодов[Объект.ТаблицаШтрихкодов.Количество()-1].ПолучитьИдентификатор();
КонецПроцедуры
&НаКлиенте
Процедура ОткрытьЯчейкуДляРедактирования()
Shell = Новый COMОбъект("Wscript.Shell");
Shell.SendKeys("{ENTER}");
КонецПроцедуры
Примечание: Логику по заполнению данных (поиск номенклатуры, установка количества) следует перенести из события ПриИзменении в событие ИзменениеТекстаРедактирования и выполнять ее до добавления новой строки. Таким образом, весь цикл — ввод, обработка, переход — будет выполняться в одном месте.
Хотя решение с WScript.Shell работает, оно имеет недостатки: зависимость от ОС Windows и потенциальные проблемы с фокусом ввода. Существуют более современные и надежные методы. Для перехвата ввода с клавиатуры и точной работы с таймерами подойдёт многофункциональная компонента для 1С.
Это предпочтительный способ при работе с торговым оборудованием. Если сканер штрихкодов подключен через драйвер, соответствующий стандарту "1С:Совместимо", он не эмулирует клавиатурный ввод, а генерирует системное внешнее событие. Его можно перехватить в модуле формы процедурой ОбработкаВнешнегоСобытия. Этот метод избавляет от необходимости эмулировать нажатия клавиш и проверять длину строки. Для обработки событий сканирования на мобильной платформе можно использовать компоненту перехвата сообщений сканера ШК.
Вместо эмуляции нажатия Enter можно попробовать более "чистые" программные методы:
Элементы.ИмяТаблицы.ТекущаяКолонка = Элементы.ИмяТаблицы.ПодчиненныеЭлементы.ИмяКолонки; — этот код программно устанавливает активную колонку.ТекущийЭлемент = Элементы.ИмяТаблицы; — установка фокуса на саму таблицу часто помогает корректно отработать последующим действиям.Иногда ячейка не активируется сразу, потому что интерфейс формы не успевает "перерисоваться" после добавления строки. В таких случаях помогает ПодключитьОбработчикОжидания. Он выполняет указанную процедуру через небольшой промежуток времени, давая форме возможность обновиться.
Посмотрим на пример:
&НаКлиенте
Процедура ТаблицаШтрихкодовШтрихкодПриИзменении(Элемент)
// ... код добавления строки ...
// Вызываем процедуру активации с небольшой задержкой (0.1 секунды), однократно
ПодключитьОбработчикОжидания("АктивироватьЯчейкуНовойСтроки", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура АктивироватьЯчейкуНовойСтроки()
// Устанавливаем текущую строку
Элементы.ТаблицаШтрихкодов.ТекущаяСтрока = Объект.ТаблицаШтрихкодов[Объект.ТаблицаШтрихкодов.Количество() - 1].ПолучитьИдентификатор();
// Устанавливаем текущую колонку для активации
Элементы.ТаблицаШтрихкодов.ТекущаяКолонка = Элементы.ТаблицаШтрихкодов.ПодчиненныеЭлементы.ТаблицаШтрихкодовШтрихкод;
// Можно дополнительно попробовать активировать элемент
ТекущийЭлемент = Элементы.ТаблицаШтрихкодов;
КонецПроцедуры
Этот подход более стабилен, чем эмуляция нажатий клавиш, и работает независимо от операционной системы (включая веб-клиент, где COM-объекты недоступны).