При разработке в среде 1С:Предприятие 8.3 на управляемых формах программисты часто сталкиваются с ситуацией, когда стандартного добавления строки в табличную часть недостаточно. Задача кажется простой: добавить строку и сразу перевести на нее курсор, чтобы пользователь мог продолжить ввод без лишних кликов мышью. Однако на практике платформа может вести себя неочевидно: строка добавляется в «фоновом» режиме, а фокус остается на старом элементе или пропадает вовсе. Разберем подробно, почему так происходит и какие методы позволяют гарантированно активировать новую строку.
Для начала проанализируем фундаментальную причину сложности. В управляемом приложении 1С существует четкое разделение между данными (объект Объект.Товары) и элементами интерфейса (Элементы.Товары). Когда мы используем метод Объект.Товары.Добавить(), мы работаем непосредственно с данными. Платформа синхронизирует интерфейс, отображая новую строку, но она «не знает», что вы хотите немедленно начать ее редактировать. Для управления поведением формы нужно использовать методы именно элементов формы.
Самый простой и правильный способ сымитировать интерактивное нажатие кнопки «Добавить» — это вызвать метод у самого элемента таблицы. Рассмотрим пример кода:
&НаКлиенте
Процедура ДобавитьИПерейти(Команда)
// Мы обращаемся не к данным объекта, а к элементу формы
Элементы.Товары.ДобавитьСтроку();
КонецПроцедуры
Этот метод не просто добавляет запись в коллекцию, он инициирует стандартное платформенное действие. В большинстве случаев этого достаточно, чтобы курсор переместился в первую доступную для редактирования колонку новой строки.
Бывают ситуации, когда строку нужно сначала заполнить какими-то данными на сервере, а затем уже показать пользователю. В этом случае мы сначала добавляем строку в данные, а потом программно назначаем ее текущей в интерфейсе. Здесь важно помнить про идентификатор строки. Рассмотрим, как это реализовать правильно:
&НаКлиенте
Процедура ДобавитьИЗаполнить()
// 1. Добавляем строку в данные
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Количество = 1;
// 2. Устанавливаем фокус.
// Важно: ТекущаяСтрока принимает идентификатор строки, а не саму строку
Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецПроцедуры
Обратите внимание на метод ПолучитьИдентификатор(). Если вы попытаетесь присвоить свойству ТекущаяСтрока саму переменную НоваяСтрока, платформа может не отработать переход корректно, так как ей нужен уникальный внутренний индекс элемента в таблице формы.
Даже если строка стала текущей, курсор может просто подсветить ее, но не войти в режим ввода текста. Чтобы пользователь сразу мог начать печатать, нам нужно указать ТекущийЭлемент для всей формы и, при необходимости, вызвать метод ИзменитьСтроку(). Проанализируем расширенный пример:
&НаКлиенте
Процедура ДобавитьСАктивациейКолонки()
НоваяСтрока = Объект.Товары.Добавить();
Идентификатор = НоваяСтрока.ПолучитьИдентификатор();
// Устанавливаем строку
Элементы.Товары.ТекущаяСтрока = Идентификатор;
// Переводим фокус на конкретное поле ввода (например, Номенклатура)
Элементы.ТекущийЭлемент = Элементы.ТоварыНоменклатура;
// Принудительно открываем ячейку для редактирования
Элементы.Товары.ИзменитьСтроку();
КонецПроцедуры
Такой подход гарантирует, что пользователю не придется нажимать Enter или F2 для начала ввода данных.
Выясним причину, по которой иногда даже вышеописанные методы не срабатывают. В 1С события формы (например, ПриОкончанииРедактирования или ПриИзменении) выполняются внутри определенного цикла обработки сообщений. Если в этом цикле платформа сама планирует переключить фокус обратно, ваши программные установки могут быть «затерты» стандартным поведением системы.
Решением является использование метода ПодключитьОбработчикОжидания(). Это позволяет выполнить код установки фокуса сразу после того, как платформа завершит свои текущие визуальные обновления. Рассмотрим, как это реализовать:
&НаКлиенте
Процедура ТоварыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
// Если это была новая строка и мы хотим добавить еще одну автоматически
Если НоваяСтрока Тогда
// Вызываем процедуру установки фокуса через 0.1 секунды
ПодключитьОбработчикОжидания("УстановитьФокусНаНовуюСтроку", 0.1, Истина);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура УстановитьФокусНаНовуюСтроку()
// Теперь, когда платформа закончила обработку предыдущей строки, добавляем новую
Элементы.Товары.ДобавитьСтроку();
КонецПроцедуры
Параметр Истина в методе ПодключитьОбработчикОжидания означает, что процедура выполнится всего один раз. Это самый надежный способ «победить» платформенные алгоритмы перехвата фокуса.
Иногда программный код абсолютно верен, но фокус все равно «проскакивает» нужную колонку. Проанализируем свойства элементов формы, которые на это влияют:
Нет (или флажок был снят).ИзменитьСтроку() или ДобавитьСтроку() не сможет активировать режим редактирования.ТекущийЭлемент, обязательно должен быть видимым на форме в данный момент.В некоторых старых советах можно встретить использование COM-объекта WScript.Shell для имитации нажатия клавиши Insert. Мы настоятельно не рекомендуем использовать этот метод по следующим причинам:
SendKeys отправляет нажатие в активное окно ОС. Если в момент выполнения кода пользователь переключится на другое приложение, команда уйдет туда.Подведем итог. Для качественной реализации добавления строки используйте сочетание ДобавитьСтроку() или ТекущаяСтрока вместе с ТекущийЭлемент. Если же платформа сопротивляется — используйте небольшую задержку через обработчик ожидания. Это сделает интерфейс вашего решения профессиональным и удобным для конечного пользователя.