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

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

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

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

Суть проблемы: Индекс против Идентификатора

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

В управляемых формах свойство элемента формы Элементы.ИмяТаблицы.ТекущаяСтрока ожидает получить Идентификатор строки (числовое значение, уникальное в рамках этой формы), а не её порядковый номер (индекс 0, 1, 2...).

Рассмотрим, почему простой код вида:


// ЭТО НЕПРАВИЛЬНО
Элементы.МояТаблица.ТекущаяСтрока = 1; 

...не работает или вызывает ошибку. Платформа ожидает специальный ID, который она сама присвоила строке при создании формы.

Разбор ошибок из практики

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

Ошибка 1: "Метод объекта не обнаружен (ПолучитьИдентификатор)"

Автор пытался выполнить код:


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

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

Ошибка 2: Ошибка передачи данных XDTO

При попытке передать контекст формы на сервер:


// Ошибка
Процедура ОпределитьЭтапМаршрута(ЭтотОбъект)

Возникает ошибка Отсутствует отображение для типа 'ФормаКлиентскогоПриложения'. Важно запомнить: нельзя передавать объект управляемой формы целиком с клиента на сервер в качестве параметра. В серверных процедурах контекст формы доступен через свойство ЭтаФорма (или просто обращение к реквизитам), передавать его явно не нужно и невозможно.

Правильное решение: Получение идентификатора

Чтобы установить курсор, нам нужно выполнить три шага:

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

Способ 1. Если известна строка (объект данных формы)

Если вы только что добавили строку программно, метод добавления обычно возвращает саму строку. У неё сразу можно взять ID.


&НаКлиенте
Процедура ДобавитьИВыделить()
    НоваяСтрока = Объект.Товары.Добавить();
    // Заполняем данные...
    НоваяСтрока.Номенклатура = НекийТовар;
    
    // Устанавливаем курсор
    Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецПроцедуры

Способ 2. Поиск строки по индексу (номеру)

Если вам нужно выделить, например, вторую строку (индекс 1, так как нумерация с нуля), используем метод Получить() коллекции данных формы.


&НаСервере
Процедура ВыделитьВторуюСтрокуНаСервере()
    // Получаем строку по индексу 1 (это вторая строка визуально)
    // Важно обращаться именно к коллекции данных формы
    ИскомаяСтрока = Объект.Товары.Получить(1); 
    
    // Присваиваем ID текущей строке элемента формы
    Элементы.Товары.ТекущаяСтрока = ИскомаяСтрока.ПолучитьИдентификатор();
КонецПроцедуры

Важно: Этот код будет работать корректно, если Объект.Товары является типом ДанныеФормыКоллекция.

Сложный случай: Вложенные таблицы и обходные пути

В теме обсуждалась ситуация, когда таблица на форме отображает данные не напрямую из текущего объекта, а "через точку" (например, табличная часть реквизита-справочника). В таких случаях прямая адресация может не сработать.

Рассмотрим решение, к которому пришли в обсуждении. Если прямые методы не работают из-за сложности структуры данных, можно использовать выгрузку в промежуточную структуру для поиска соответствия или работать через реквизит формы.

Рабочий вариант для сложных случаев (адаптировано из обсуждения):


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

Если же данные на форме отображаются только для чтения (через путь к данным), то самый надежный способ — искать строку не по индексу, а по ключевым полям.

Рекомендация по поиску строки

Чтобы код был надежным и не зависел от сортировки строк пользователем, лучше искать строку не по номеру, а по значению ключевой колонки (например, по ссылке на этап маршрута).


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

КонецПроцедуры

Резюме

← На главную