При интеграции торгового оборудования, в частности сканеров штрихкодов, разработчики часто сталкиваются с задачей разделения логики: если пользователь вручную редактирует поле строки табличной части, отсканированный штрихкод должен записаться в это поле; если же редактирование не ведется, сканирование должно инициировать поиск номенклатуры или позиционирование на нужной строке.
Разберем ограничения платформы 1С, возможные программные способы фиксации состояния редактирования и наиболее надежные архитектурные решения этой задачи.
Проанализируем, почему нельзя напрямую узнать состояние внутреннего текстового редактора ячейки:
ТекущийЭлемент указывает лишь на таблицу в целом (ТабличноеПоле или ТаблицаФормы).ТекущиеДанные (или ТекущаяСтрока) и ТекущаяКолонка показывают исключительно позицию фокуса, но не статус активного ввода текста пользователем.Рассмотрим вариант, предложенный в обсуждении: установка пользовательского флага состояния формы в момент входа в режим редактирования строки и сброс этого флага при выходе.
Разберем по шагам реализацию данного механизма:
ВРежимеРедактированияСтроки) и переменную для хранения имени текущей редактируемой колонки.ПередНачаломИзменения / ПриНачалеРедактирования) устанавливаем флаг в значение Истина.ПриОкончанииРедактирования) сбрасываем флаг в Ложь.ОбработкаВнешнегоСобытия проверяем состояние флага.Посмотрим на пример реализации в коде формы:
Перем ВРежимеРедактированияСтроки;
Перем РедактируемаяКолонка;
&НаКлиенте
Процедура ТоварыПередНачаломИзменения(Элемент, Отказ)
ВРежимеРедактированияСтроки = Истина;
РедактируемаяКолонка = Элемент.ТекущаяКолонка.Имя;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыПриОкончанииРедактирования(Элемент, ОтменаРедактирования)
ВРежимеРедактированияСтроки = Ложь;
РедактируемаяКолонка = "";
КонецПроцедуры
&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
Если Событие = "BarCodeValue" Тогда
Штрихкод = СокрЛП(Данные);
Если ВРежимеРедактированияСтроки И РедактируемаяКолонка = "Штрихкод" Тогда
// Проставляем штрихкод в редактируемую строку
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
ТекущиеДанные.Штрихкод = Штрихкод;
КонецЕсли;
Иначе
// Выполняем стандартный поиск и позиционирование
НайтиИВыбратьСтрокуПоШтрихкоду(Штрихкод);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важные риски метода:
Esc, переключении на другое окно операционной системы или потере фокуса мыши флаг может рассинхронизироваться.Как справедливо отмечено в обсуждении, необходимость двойного клика перед сканированием усложняет пользовательский сценарий (workflow). Рассмотрим более надежные архитектурные подходы:
SendKeys) не требуется.ВнешнееСобытие, сканирование должно обрабатывать бизнес-логику документа независимо от фокуса (поиск позиции, добавление строки, инкремент количества).