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

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

В процессе разработки интерфейсов на управляемых формах «1С:Предприятия 8» программисты часто сталкиваются с задачей программного позиционирования на определенной строке таблицы. Например, после заполнения табличной части, после закрытия вспомогательной формы выбора или при переходе по какому-либо событию нам необходимо, чтобы курсор автоматически встал на нужную строку.

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

В чем главная ошибка: Разница между строкой ТЧ и элементом формы

Давайте проанализируем ситуацию, описанную в первом сообщении темы. Автор пытается выполнить следующий код:


ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("ДеньНедели", Параметр);
НужнаяСтрока = Объект.ДниНедели.НайтиСтроки(ПараметрыОтбора);
Элементы.ДниНедели.ТекущаяСтрока = НужнаяСтрока;

Этот код не работает по двум ключевым причинам:

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

Для успешного решения задачи нам необходимо получить уникальный числовой идентификатор найденной строки с помощью метода ПолучитьИдентификатор().

Решение по шагам: Безопасный и правильный способ позиционирования

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


СтрокаКоллекции = Объект.ДниНедели.НайтиСтроки(ПараметрыОтбора)[0];
Элементы.ДниНедели.ТекущаяСтрока = СтрокаКоллекции.ПолучитьИдентификатор();

Внимание! Данный вариант содержит критическую уязвимость. Если поиск по параметрам отбора не даст результатов (например, если нужный день недели отсутствует в табличной части), метод НайтиСтроки() вернет пустой массив. Попытка обратиться к его первому элементу через индекс [0] вызовет аварийное завершение работы программы с ошибкой «Индекс находится за пределами границы».

Чтобы избежать этой ошибки, мы всегда должны делать проверку на количество найденных элементов. Разберем безопасный и правильный вариант реализации алгоритма:


// 1. Создаем структуру для поиска нужной строки
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("ДеньНедели", Параметр);

// 2. Выполняем поиск строк в табличной части
НайденныеСтроки = Объект.ДниНедели.НайтиСтроки(ПараметрыОтбора);

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

Оптимизация: Более простой поиск через метод Найти()

Если поиск строки на форме выполняется по одному ключевому полю (как в нашем примере с реквизитом «ДеньНедели»), использовать метод НайтиСтроки() с предварительным созданием структуры избыточно. Это приводит к лишним операциям выделения памяти под объект структуры и массив результатов.

Гораздо проще, быстрее и лаконичнее использовать метод Найти(). Он осуществляет поиск первого совпадения по указанной колонке и сразу возвращает либо целевую строку таблицы, либо значение Неопределено, если совпадений не найдено. Посмотрим на пример реализации:


// Ищем строку напрямую по значению в нужной колонке
СтрокаКоллекции = Объект.ДниНедели.Найти(Параметр, "ДеньНедели");

// Если строка успешно найдена, позиционируемся на ней
Если СтрокаКоллекции <> Неопределено Тогда
    Элементы.ДниНедели.ТекущаяСтрока = СтрокаКоллекции.ПолучитьИдентификатор();
КонецЕсли;

Этот способ экономит ресурсы сервера и делает ваш код гораздо более читаемым и профессиональным.

Фокусировка на элементе: Перенос курсора

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

Чтобы пользователь мог сразу же начать работать с выделенной строкой (например, листать строки стрелками клавиатуры вверх и вниз), нам необходимо принудительно перенести фокус на саму таблицу. Для этого активизируем элемент формы:


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

Важная разница: Работа с Динамическими списками

Рассмотренный выше метод ПолучитьИдентификатор() применим исключительно к классическим коллекциям данных управляемой формы, таким как табличные части документов/справочников (тип ДанныеФормыКоллекция) и программно созданные таблицы значений (тип ДанныеФормыКоллекция).

Если на вашей управляемой форме отображается Динамический список (например, список документов, справочник контрагентов или произвольный SQL-запрос к базе данных), логика позиционирования будет совершенно иной:

Пример позиционирования в динамическом списке справочника «Контрагенты» по известной ссылке:


// СсылкаНаКонтрагент - это полученная ранее СправочникСсылка.Контрагенты
Элементы.СписокКонтрагентов.ТекущаяСтрока = СсылкаНаКонтрагент;
ЭтаФорма.ТекущийЭлемент = Элементы.СписокКонтрагентов;

Особенности позиционирования в Дереве значений

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

Чтобы гарантировать видимость строки для пользователя, ветку дерева, в которой находится найденная строка, необходимо предварительно развернуть с помощью метода Развернуть() элемента формы:


СтрокаДерева = Объект.ДеревоЗадач.Найти(ИскомыйИД, "ИдентификаторЗадачи");
Если СтрокаДерева <> Неопределено Тогда
    ИдентификаторСтроки = СтрокаДерева.ПолучитьИдентификатор();
    
    // Позиционируем фокус на нужной строке дерева
    Элементы.ДеревоЗадач.ТекущаяСтрока = ИдентификаторСтроки;
    
    // Разворачиваем узел дерева, чтобы строка стала видимой на экране
    Элементы.ДеревоЗадач.Развернуть(ИдентификаторСтроки, Истина);
КонецЕсли;

Понятийный аппарат: ТекущиеДанные против ТекущаяСтрока

Для закрепления материала важно навсегда запомнить концептуальное различие между двумя похожими свойствами табличного элемента формы:

Используя предложенные в этой статье безопасные методы поиска и позиционирования, вы сможете писать надежный, быстрый и устойчивый к ошибкам код для любых интерфейсов управляемого приложения «1С:Предприятие 8».

← На главную