Рассмотрим довольно популярную задачу, с которой часто сталкиваются разработчики в 1С: при добавлении новой строки в табличную часть на управляемой форме необходимо сделать так, чтобы фокус (текущая строка) автоматически переместился на предыдущую добавленную строку. Разберем по шагам, почему стандартные методы напрямую не работают, выясним причину частых ошибок и напишем надежный код для решения этой задачи.
Проанализируем ситуацию, с которой часто начинается попытка решить эту задачу. Разработчик пытается получить индекс текущей строки, отнять от него единицу и присвоить результат обратно элементу формы. Однако в результате вычисления метода Индекс() возвращается -1. Почему так происходит?
В управляемых формах 1С существует строгое разделение между данными (коллекцией строк) и интерфейсом (элементом формы, который эти данные отображает). Свойство ТекущаяСтрока у элемента формы (например, Элементы.АвтоработыТЧ.ТекущаяСтрока) хранит не саму строку и не ее порядковый номер (индекс), а внутренний идентификатор строки интерфейса.
При этом коллекция данных формы (например, Объект.Автоработы) ничего не знает про интерфейс. Она работает с реальными индексами (0, 1, 2 и так далее). Поэтому попытка передать идентификатор из формы напрямую в метод получения индекса коллекции всегда возвращает -1, так как система не находит объект с таким "индексом".
Разберем подробнее, как правильно получить нужную строку и активизировать ее на форме. Нам необходимо выполнить конвертацию идентификатора в индекс, вычислить предыдущую строку, а затем произвести обратную конвертацию.
ТекущаяСтрока элемента формы.Посмотрим на пример безопасного и рабочего кода, который реализует этот алгоритм:
// Получаем коллекцию данных
Автоработы = ЗаписьНаРемонт.ЗаявкаНаРемонт.Автоработы;
// Находим реальную строку данных по идентификатору из элемента формы
ТекущаяСтрокаДанных = Автоработы.НайтиПоИдентификатору(Элементы.АвтоработыТЧ.ТекущаяСтрока);
// Если строка найдена, получаем ее индекс
Если ТекущаяСтрокаДанных <> Неопределено Тогда
РеальныйИндекс = Автоработы.Индекс(ТекущаяСтрокаДанных);
// Проверяем уязвимость выхода за границы массива
// Если мы стоим на первой строке (индекс 0), мы не можем перейти на предыдущую
Если РеальныйИндекс > 0 Тогда
// Получаем предыдущую строку данных
НужнаяСтрокаТаблицы = Автоработы.Получить(РеальныйИндекс - 1);
// Получаем её идентификатор для интерфейса
ИдентификаторСтроки = НужнаяСтрокаТаблицы.ПолучитьИдентификатор();
// Устанавливаем фокус в интерфейсе
Элементы.АвтоработыТЧ.ТекущаяСтрока = ИдентификаторСтроки;
КонецЕсли;
КонецЕсли;
Важное замечание: всегда выполняйте проверку Если РеальныйИндекс > 0. Если пользователь выберет самую первую строку в табличной части (ее индекс равен 0) и выполнится код РеальныйИндекс - 1, то метод Автоработы.Получить(-1) вызовет критическую ошибку платформы (выход за границы индекса).
Определим, в каком месте конфигурации лучше всего размещать написанный код. При добавлении новой строки в табличную часть срабатывают различные клиентские события табличного поля. Рассмотрим их подробнее:
НоваяСтрока = Истина. Вы можете переопределить текущую строку именно в этот момент.Иногда недостаточно просто сделать строку "текущей" — необходимо еще и перевести курсор пользователя в определенную колонку для быстрого ввода данных. Проанализируем, как дополнить наше решение.
Для активизации конкретного элемента управления (ячейки) в 1С используется свойство формы ТекущийЭлемент. В связке с изменением строки это выглядит так:
// ... код получения ИдентификаторСтроки из примера выше ...
Элементы.АвтоработыТЧ.ТекущаяСтрока = ИдентификаторСтроки;
// Переводим фокус в нужную колонку, например, колонку "ВидРабот"
ЭтаФорма.ТекущийЭлемент = Элементы.АвтоработыТЧВидРабот;
Если перед вами стоит задача активизировать определенную строку не в момент ручного добавления, а сразу при открытии формы документа или справочника, в платформе 1С предусмотрен встроенный механизм параметров формы.
При вызове метода открытия формы из другого окна вы можете передать структуру параметров, указав нужный идентификатор:
ЗначениеИдентификатора = 5; // вычисленный ранее идентификатор
ПараметрыФормы = Новый Структура("ТекущаяСтрока", ЗначениеИдентификатора);
ОткрытьФорму("Документ.ЗаказНаряд.ФормаОбъекта", ПараметрыФормы);
В этом случае форма самостоятельно отпозиционируется на нужной строке в момент инициализации, без дополнительных усилий в обработчике ПриОткрытии.
Используйте предложенные методы и всегда помните о строгом разделении данных и интерфейса при разработке на управляемых формах 1С!