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

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

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

Разница между индексом строки и идентификатором

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

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

Универсальное решение: метод ПолучитьИдентификатор()

Чтобы корректно установить фокус на нужную строку, мы должны получить её внутренний идентификатор. Для этого у объекта строки данных формы существует метод ПолучитьИдентификатор(). Рассмотрим правильный алгоритм работы на примере обработки сканирования товара:


// Находим строку в коллекции данных объекта
ПараметрыОтбора = Новый Структура("Номенклатура", НайденныйТовар);
НайденныеСтроки = Объект.Товары.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() > 0 Тогда
    // Берем последнюю найденную строку
    СтрокаДокумента = НайденныеСтроки[НайденныеСтроки.Количество() - 1];
Иначе
    // Добавляем новую строку, если товар не найден
    СтрокаДокумента = Объект.Товары.Добавить();
    СтрокаДокумента.Номенклатура = НайденныйТовар;
КонецЕсли;

// Увеличиваем количество
СтрокаДокумента.Количество = СтрокаДокумента.Количество + 1;

// КЛЮЧЕВОЙ МОМЕНТ: Устанавливаем текущую строку через идентификатор
Элементы.Товары.ТекущаяСтрока = СтрокаДокумента.ПолучитьИдентификатор();

Этот код будет работать стабильно, даже если строки перемещались, удалялись или сортировались, так как метод ПолучитьИдентификатор() возвращает именно то значение, которое понимает элемент управления Таблица.

Как найти строку, зная только идентификатор?

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

Рассмотрим пример получения номера строки из текущего выделения:


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

Программная прокрутка и фокус (активизация)

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

  1. Устанавливаем идентификатор в свойство ТекущаяСтрока.
  2. Принудительно назначаем таблицу текущим элементом формы с помощью ЭтаФорма.ТекущийЭлемент.

Посмотрим на пример кода:


// Устанавливаем строку
Элементы.Товары.ТекущаяСтрока = НужныйИдентификатор;
// Переносим фокус на таблицу, чтобы строка выделилась синим цветом и стала активной
ЭтаФорма.ТекущийЭлемент = Элементы.Товары;

Особенности при копировании и сортировке

Выясним причину, по которой курсор может «прыгать» при копировании строк или после выполнения сортировки на сервере. При копировании строки методом Копировать() создается новый объект данных, и ему присваивается новый уникальный идентификатор. Если вы скопировали строку, но не обновили ТекущаяСтрока, фокус останется на старом месте или сбросится.

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

Пример обработки перед началом добавления (копирования):


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

Важные нюансы и ограничения

Проанализируем еще несколько важных моментов, которые помогут избежать ошибок:

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

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

← На главную