Как программно установить текущую строку в таблице управляемой формы 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 на управляемых формах разработчики часто сталкиваются с задачей программного позиционирования курсора на конкретной строке таблицы. Попытка напрямую присвоить номер строки свойству ТекущаяСтрока до открытия формы или передача обычного порядкового номера массива нередко приводит к тому, что курсор остается в неопределенном положении или сбрасывается на первую позицию. Разберем детально, как устроена работа со свойством ТекущаяСтрока, почему возникают ошибки и как правильно реализовать требуемое поведение.

Причины некорректного поведения и особенности свойства ТекущаяСтрока

Рассмотрим две ключевые причины, из-за которых позиционирование строки может не срабатывать:

  1. Несоответствие типов данных: Для табличных частей документов и таблиц значений на форме (коллекция ДанныеФормыКоллекция) значением свойства ТекущаяСтрока является не порядковый номер строки (НомерСтроки) и не индекс в массиве, а уникальный числовой идентификатор строки, который возвращается методом ПолучитьИдентификатор(). Если же таблица связана с динамическим списком, в ТекущаяСтрока передается ссылка на объект или КлючЗаписи.
  2. Попытка обращения к элементам неинициализированной формы: При получении формы через ПолучитьФорму() элементы интерфейса еще не отрисованы на клиенте. Если присвоить значение свойству ТекущаяСтрока до вызова метода Открыть(), то при последующей стандартной инициализации форма перезапишет текущую позицию значением по умолчанию.

Способ 1. Позиционирование после открытия формы с получением идентификатора строки

Проанализируем простейший вариант, когда форма открывается на клиенте, после чего выполняется поиск нужной строки и установка свойства ТекущаяСтрока. Для этого необходимо сначала открыть форму, получить идентификатор строки целевой строки и назначить его элементу управления.

Посмотрим на пример кода во внешней процедуре или команде:


&НаКлиенте
Процедура ОткрытьДокументИВыбратьСтроку(Команда)
    ПараметрыФормы = Новый Структура("Ключ", СсылкаНаТабель);
    ФормаДокумента = ОткрытьФорму("Документ.ТабельУчетаРабочегоВремени.ФормаОбъекта", ПараметрыФормы);
    
    // Проверяем наличие строк в табличной части документа
    Если ФормаДокумента.Объект.ДанныеОВремени.Количество() > 0 Тогда
        // Получаем идентификатор требуемой строки (например, первой с индексом 0)
        ИдентификаторСтроки = ФормаДокумента.Объект.ДанныеОВремени[0].ПолучитьИдентификатор();
        
        // Устанавливаем текущую строку и переводим фокус на таблицу
        ФормаДокумента.Элементы.ДанныеОВремени.ТекущаяСтрока = ИдентификаторСтроки;
        ФормаДокумента.ТекущийЭлемент = ФормаДокумента.Элементы.ДанныеОВремени;
    КонецЕсли;
КонецПроцедуры

Способ 2. Передача параметров позиционирования в форму (рекомендуемый подход)

В архитектуре управляемого приложения более надежным и общепринятым считается подход, при котором вызывающий код не управляет напрямую элементами чужой формы, а передает параметры открытия. Целевая форма самостоятельно обрабатывает переданные данные в обработчике ПриОткрытии.

Разберем по шагам, как настроить такую передачу:

  1. В вызывающем коде сформируем структуру параметров, указав ключ объекта и критерий выбора строки (например, номер строки или сотрудника).
  2. В модуле целевой формы в обработчике ПриОткрытии найдем нужную строку, вычислим ее идентификатор и активируем элемент интерфейса.

Пример кода вызова формы:


&НаКлиенте
Процедура ОткрытьТабельСПараметром(Команда)
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("Ключ", СсылкаНаТабель);
    ПараметрыОткрытия.Вставить("НомерСтрокиДляФокуса", 2);
    
    ОткрытьФорму("Документ.ТабельУчетаРабочегоВремени.ФормаОбъекта", ПараметрыОткрытия);
КонецПроцедуры

Пример обработки переданного параметра в модуле целевой формы документа:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если Параметры.Свойство("НомерСтрокиДляФокуса") И Параметры.НомерСтрокиДляФокуса > 0 Тогда
        Индекс = Параметры.НомерСтрокиДляФокуса - 1;
        Если Объект.ДанныеОВремени.Количество() > Индекс Тогда
            Идентификатор = Объект.ДанныеОВремени[Индекс].ПолучитьИдентификатор();
            Элементы.ДанныеОВремени.ТекущаяСтрока = Идентификатор;
            ТекущийЭлемент = Элементы.ДанныеОВремени;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Особенности передачи фокуса и асинхронная инициализация

В сложных формах с условным оформлением или динамическими списками платформа может сбросить фокус таблицы после завершения события ПриОткрытии. Чтобы гарантировать корректное отображение курсора и переход к нужной ячейке, применим следующие правила:

  1. Активация таблицы: Всегда передаем фокус таблице через ТекущийЭлемент = Элементы.ИмяТаблицы. При необходимости фокусировки на определенной колонке дополнительно устанавливаем Элементы.ИмяТаблицы.ТекущаяКолонка = Элементы.ИмяКолонки.
  2. Использование обработчика ожидания: Если форма сбрасывает фокус после открытия, подключим однократный обработчик ожидания с минимальной задержкой:
    
    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
        ПодключитьОбработчикОжидания("УстановитьФокусНаСтроку", 0.1, Истина);
    КонецПроцедуры
    
    &НаКлиенте
    Процедура УстановитьФокусНаСтроку()
        Если Объект.ДанныеОВремени.Количество() > 0 Тогда
            Элементы.ДанныеОВремени.ТекущаяСтрока = Объект.ДанныеОВремени[0].ПолучитьИдентификатор();
            ТекущийЭлемент = Элементы.ДанныеОВремени;
        КонецЕсли;
    КонецПроцедуры
    

Архитектурное предупреждение: скрытое открытие форм для выполнения расчетов

Иногда разработчики пытаются программно открыть форму, спозиционировать строку, чтобы сработали стандартные клиентские обработчики (например, пересчет времени или автозаполнение), и сразу же закрыть форму. Такой подход в управляемом приложении 1С является грубой архитектурной ошибкой.

Выясним причины, почему так делать нельзя:

  1. В управляемом интерфейсе невозможно штатно открыть форму в полностью скрытом режиме без отображения пользователю. Мелькание окон ухудшает пользовательский опыт и замедляет работу системы.
  2. Интерфейсный слой (модуль формы) предназначен исключительно для взаимодействия с пользователем. Вся прикладная бизнес-логика (расчет рабочих часов, заполнение табеля, пересчет сумм) должна быть вынесена в модуль объекта, модуль менеджера или серверный общий модуль в виде экспортных процедур.
  3. Для выполнения расчетов без участия пользователя необходимо получить объект на сервере через Ссылка.ПолучитьОбъект(), вызвать требуемую экспортную процедуру пересчета и записать изменения напрямую в базу данных, не создавая клиентский контекст формы.
← На главную