При разработке интерфейсов на обычных формах (ОФ) программисты часто сталкиваются с неочевидным поведением платформы. Типичная ситуация: пользователь выбирает значение в поле ввода табличной части, срабатывает событие ПриИзменении, данные визуально появляются в ячейке. Однако, если пользователь сразу после этого нажимает клавишу Esc, выбранное значение исчезает, и поле становится пустым. В этой статье мы подробно разберем, почему это происходит и как правильно перехватить нажатие Esc, чтобы сохранить данные.
Для начала разберем внутреннюю логику работы обычного приложения. В 1С 8.3 при работе с обычными формами редактирование в ячейке табличного поля происходит в так называемом буфере элемента управления. Пока пользователь находится в режиме редактирования строки и не перешел к другой строке или не нажал Enter, изменения считаются предварительными.
Когда вы выбираете значение из справочника, оно попадает в элемент управления (поле ввода), и даже может сработать событие ПриИзменении. Но на уровне объекта данных (строки табличной части) это изменение еще не зафиксировано окончательно. Нажатие клавиши Esc для платформы является сигналом к отмене транзакции редактирования. Система откатывает состояние ячейки к тому значению, которое было в ней до входа в режим редактирования. Если ячейка была пустой, она снова станет пустой, игнорируя факт выбора значения через форму выбора.
Рассмотрим самый эффективный способ контроля завершения ввода в табличном поле. У табличного поля есть событие ПриОкончанииРедактирования. Оно удобно тем, что предоставляет прямой доступ к результату действий пользователя через параметр Отмена.
Проанализируем параметры этого события:
Элемент — ссылка на само табличное поле.НоваяСтрока — булево значение, указывающее, создается ли сейчас новая запись.Отмена — ключевой параметр. Если пользователь нажал Esc, этот параметр будет равен Истина. Если же редактирование завершено штатно (Enter, клик мышью в другое место), параметр будет равен Ложь.Разберем пример кода для обработки этой ситуации:
Процедура ТабличнаяЧасть1ПриОкончанииРедактирования(Элемент, НоваяСтрока, Отмена)
Если Отмена Тогда
// Сюда мы попадем, если пользователь нажал Esc
Сообщить("Редактирование отменено пользователем (нажат Esc)");
// Если нам критично важно сохранить то, что было выбрано до Esc,
// здесь можно реализовать дополнительную логику.
Иначе
// Штатное завершение редактирования
КонецЕсли;
КонецПроцедуры
Выясним, можно ли заставить систему «забыть» о возможности отката. Если бизнес-логика требует, чтобы выбранное значение сохранялось мгновенно и Esc не мог его стереть, мы можем использовать метод элемента управления ЗаписатьВИсточник().
Посмотрим, как это реализовать в событии ПриИзменении конкретной колонки:
Процедура ТабличнаяЧасть1ИмяРеквизитаПриИзменении(Элемент)
// Элемент здесь — это само поле ввода (редактор ячейки)
// Принудительно записываем значение из редактора в данные строки
Элемент.ЗаписатьВИсточник();
// Теперь, даже если пользователь нажмет Esc,
// данные уже попали в объектную модель строки ТЧ.
КонецПроцедуры
Важный нюанс: использование ЗаписатьВИсточник() прерывает стандартный цикл «отката» редактирования, так как данные из буфера формы немедленно перемещаются в источник данных (строку таблицы).
Рассмотрим альтернативный вариант, когда мы полностью берем управление процессом выбора на себя. Это позволяет избежать стандартного механизма помещения значения в буфер ячейки. Мы можем открыть форму выбора модально, получить результат и сразу записать его в текущую строку.
Разберем по шагам реализацию этого метода:
Процедура ТабличнаяЧасть1Реквизит1НачалоВыбора(Элемент, СтандартнаяОбработка)
// Отключаем стандартный механизм, чтобы 1С не открывала форму сама
СтандартнаяОбработка = Ложь;
// Открываем форму выбора программно (модально для простоты в ОФ)
ВыбранноеЗначение = Справочники.Контрагенты.ВыбратьФорму().ОткрытьМодально();
// Проверяем, было ли что-то выбрано или форму закрыли крестиком/Esc
Если ВыбранноеЗначение <> Неопределено Тогда
// Напрямую записываем в данные текущей строки, минуя буфер элемента
ТекущаяСтрока = ЭлементыФормы.ТабличнаяЧасть1.ТекущиеДанные;
ТекущаяСтрока.Реквизит1 = ВыбранноеЗначение;
// Дополнительно можно обновить визуальное отображение
Элемент.Значение = ВыбранноеЗначение;
Иначе
Сообщить("Выбор был отменен пользователем в форме выбора");
КонецЕсли;
КонецПроцедуры
Важно: использование модальных окон в современном 1С не приветствуется, но для обычных форм в старых конфигурациях (например, УПП 1.3 или КА 1.1) это остается стандартным и наиболее надежным методом контроля потока выполнения кода.
Стоит отметить, что если ваше поле ввода находится не в табличной части, а просто на форме, события ПриОкончанииРедактирования у него не будет. В этом случае поведение Esc жестко зашито в платформу. Если поле связано с реквизитом формы или объекта, Esc вернет значение к исходному. Чтобы обойти это, наиболее эффективным методом остается использование события ОбработкаВыбора или НачалоВыбора, как описано в Способе 3.
Подведем итог: для надежной работы интерфейса в обычных формах рекомендуется комбинировать проверку флага Отмена в событии окончания редактирования и метод ЗаписатьВИсточник(), если необходимо гарантированное сохранение данных сразу после выбора.