Активная и выделенная строка таблицы формы: код для 1С 8.3
Содержание
Чтобы программно выделить строку в табличной части 1С 8.3 на управляемой форме, присвойте свойству ТекущаяСтрока элемента таблицы идентификатор строки: Элементы.Товары.ТекущаяСтрока = Объект.Товары[0].ПолучитьИдентификатор();. Таблица сама прокрутится к строке, курсор встанет на неё.
Частая ловушка: в ТекущаяСтрока передают саму строку или её номер. Платформа ждёт число-идентификатор, а не НомерСтроки. Ниже код для типовых задач: первая, последняя, найденная по значению строка, выделение при открытии формы и выделение нескольких строк сразу.
Как устроены активная и выделенные строки табличной части
У таблицы на форме два разных состояния строки, и их легко спутать.
- 🎯 Активная (текущая) строка — та, на которой стоит курсор. Она одна. Свойство
ТекущаяСтрока, данные —ТекущиеДанные. - ✅ Выделенные строки — подсвеченные строки при множественном выделении (Shift или Ctrl + щелчок). Их может быть много. Свойство
ВыделенныеСтроки. - 🖱️ Текущая колонка — свойство
ТекущийЭлементу самой таблицы. Им ставят курсор в нужное поле строки.
В управляемой форме табличная часть документа — это реквизит Объект.Товары типа ДанныеФормыКоллекция. А на экране её показывает элемент Элементы.Товары типа ТаблицаФормы. Данные меняют через Объект, а положение курсора — через Элементы.
| Задача | Управляемая форма | Обычная форма |
|---|---|---|
| Сделать строку активной | Элементы.Товары.ТекущаяСтрока = Ид | ЭлементыФормы.Товары.ТекущаяСтрока = СтрокаТЧ |
| Прочитать активную строку | Элементы.Товары.ТекущиеДанные | ЭлементыФормы.Товары.ТекущиеДанные |
| Выделить несколько строк | Элементы.Товары.ВыделенныеСтроки.Добавить(Ид) | ЭлементыФормы.Товары.ВыделенныеСтроки.Добавить(СтрокаТЧ) |
| Что передаётся | идентификатор (число) | сама строка табличной части |
В английском синтаксисе встроенного языка это CurrentRow, CurrentData и SelectedRows. Методов SetCurrentRow или ActiveRow у таблицы формы нет — если встретили их в примерах из интернета, это не код 1С.
Установка активной строки через ТекущаяСтрока
Идентификатор строки получают методом ПолучитьИдентификатор() у элемента коллекции. Он доступен и на клиенте, и на сервере.
Первая и последняя строка
&НаКлиенте
Процедура ПерейтиНаПервуюСтроку(Команда)
Если Объект.Товары.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Элементы.Товары.ТекущаяСтрока = Объект.Товары[0].ПолучитьИдентификатор();
КонецПроцедуры
&НаКлиенте
Процедура ПерейтиНаПоследнююСтроку(Команда)
Количество = Объект.Товары.Количество();
Если Количество = 0 Тогда
Возврат;
КонецЕсли;
Элементы.Товары.ТекущаяСтрока = Объект.Товары[Количество - 1].ПолучитьИдентификатор();
КонецПроцедуры
Индексы коллекции начинаются с нуля, а НомерСтроки — с единицы. Строка с номером 5 — это Объект.Товары[4].
Строка по номеру
&НаКлиенте
Процедура ПерейтиНаСтрокуПоНомеру(НомерСтроки)
Индекс = НомерСтроки - 1;
Если Индекс < 0 Или Индекс >= Объект.Товары.Количество() Тогда
Сообщить(СтрШаблон("Строки с номером %1 нет", Формат(НомерСтроки, "ЧГ=0")));
Возврат;
КонецЕсли;
Элементы.Товары.ТекущаяСтрока = Объект.Товары[Индекс].ПолучитьИдентификатор();
КонецПроцедуры
Новая строка сразу после добавления
После Добавить() курсор остаётся на старом месте. Чтобы пользователь сразу видел новую строку, переставьте его явно:
&НаКлиенте
Процедура ДобавитьИПерейти(Команда)
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Количество = 1;
Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецПроцедуры
Переход на строку и фокус: ТекущийЭлемент и ИзменитьСтроку
ТекущаяСтрока двигает курсор внутри таблицы, но не переводит фокус на неё. Если до этого пользователь стоял в поле «Контрагент», ввод с клавиатуры пойдёт туда же. Три приёма, которые доводят навигацию до конца:
- Фокус на таблицу:
ТекущийЭлемент = Элементы.Товары;— свойство самой формы. - Нужная колонка:
Элементы.Товары.ТекущийЭлемент = Элементы.ТоварыКоличество;— курсор встанет в поле «Количество» активной строки. Имя элемента колонки смотрите в дереве элементов формы. - Режим редактирования:
Элементы.Товары.ИзменитьСтроку();— открывает активную строку для ввода, как если бы пользователь нажал F2 или Enter.
&НаКлиенте
Процедура ВвестиКоличествоВСтроке(Идентификатор)
ТекущийЭлемент = Элементы.Товары;
Элементы.Товары.ТекущаяСтрока = Идентификатор;
Элементы.Товары.ТекущийЭлемент = Элементы.ТоварыКоличество;
Элементы.Товары.ИзменитьСтроку();
КонецПроцедуры
Так делают, например, после подбора: товар добавлен, курсор сразу в количестве, пользователь печатает цифру и жмёт Enter.
Выделение строки при открытии формы
Здесь два разных сценария: форма объекта (документ с табличной частью) и форма списка.
Форма документа
Ставьте строку в обработчике ПриОткрытии. К этому моменту данные объекта уже на клиенте, элементы созданы.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Встаём на первую строку с нулевым количеством
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Количество = 0 Тогда
Элементы.Товары.ТекущаяСтрока = Строка.ПолучитьИдентификатор();
ТекущийЭлемент = Элементы.Товары;
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Нужную строку можно вычислить и на сервере в ПриСозданииНаСервере: сохранить идентификатор в реквизит формы, а в ПриОткрытии только присвоить его. Это удобно, когда условие поиска требует запроса к базе.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// ИдСтрокиДляПерехода — реквизит формы типа Число; -1 означает «не задано»
ИдСтрокиДляПерехода = -1;
Если Параметры.Свойство("НомерСтроки") И Параметры.НомерСтроки > 0
И Параметры.НомерСтроки <= Объект.Товары.Количество() Тогда
ИдСтрокиДляПерехода = Объект.Товары[Параметры.НомерСтроки - 1].ПолучитьИдентификатор();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ИдСтрокиДляПерехода >= 0 Тогда
Элементы.Товары.ТекущаяСтрока = ИдСтрокиДляПерехода;
КонецЕсли;
КонецПроцедуры
Значение -1 вместо проверки ЗначениеЗаполнено() выбрано намеренно: идентификатор строки — число, и ноль для него допустимое значение. Проверка на заполненность приняла бы такую строку за «пустую».
Открыть документ сразу на нужной строке тогда можно так: ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", Новый Структура("Ключ, НомерСтроки", Ссылка, 7));. Параметр НомерСтроки добавьте в параметры формы, иначе он не придёт.
Форма списка
У динамического списка ТекущаяСтрока — это не идентификатор, а ссылка на элемент (для регистров — ключ записи). Стандартные формы списка и выбора принимают параметр ТекущаяСтрока:
ПараметрыФормы = Новый Структура("ТекущаяСтрока", СсылкаНаНоменклатуру);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, ЭтотОбъект);
Список откроется с курсором на переданном элементе. Внутри уже открытой формы списка то же самое делает Элементы.Список.ТекущаяСтрока = Ссылка;.
Отличия управляемых и обычных форм
В обычных формах (толстый клиент) всё проще с типами: свойство ТекущаяСтрока принимает саму строку табличной части.
// Обычная форма документа
Процедура ПриОткрытии()
Если Товары.Количество() > 0 Тогда
ЭлементыФормы.Товары.ТекущаяСтрока = Товары[Товары.Количество() - 1];
КонецЕсли;
КонецПроцедуры
Главные отличия, которые ломают перенос кода:
- 🔢 Тип значения. В обычной форме — строка табличной части, в управляемой — идентификатор. Код
Элементы.Товары.ТекущаяСтрока = Объект.Товары[0]в управляемой форме работать не будет. - 🖥️ Клиент и сервер. В управляемой форме данные строк есть на клиенте в виде данных формы. Ссылочные поля доступны, но обращаться через точку к реквизитам этих ссылок (
Строка.Номенклатура.Артикул) на клиенте нельзя — нужен вызов сервера. - 🧭 Имена.
ЭлементыФормыв обычной форме иЭлементыв управляемой. Реквизит табличной части —ТоварыиОбъект.Товары. - ⏱️ Событие
ПриАктивизацииСтроки. В управляемой форме оно вызывается с небольшой задержкой, а не мгновенно. Если в нём тяжёлая логика, программная смена строки покажет результат не сразу.
Если нужно не поставить курсор, а подсветить строку цветом по условию, это другая задача — её решают условным оформлением формы, а не свойством ТекущаяСтрока.
Ошибки при программном выделении строки
Отдельно про ТекущиеДанные: при пустой таблице или при снятом курсоре свойство возвращает Неопределено. Проверяйте это до обращения к полям, иначе получите ошибку на клиенте.
ТекДанные = Элементы.Товары.ТекущиеДанные;
Если ТекДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Множественное выделение и поиск строки по значению
Найти строку и встать на неё
Для поиска по значению поля в коллекции данных формы есть НайтиСтроки(). Метод принимает структуру отбора и возвращает массив найденных строк.
&НаКлиенте
Процедура НайтиТовар(Номенклатура)
Отбор = Новый Структура("Номенклатура", Номенклатура);
Найденные = Объект.Товары.НайтиСтроки(Отбор);
Если Найденные.Количество() = 0 Тогда
Сообщить("Товар в табличной части не найден");
Возврат;
КонецЕсли;
ТекущийЭлемент = Элементы.Товары;
Элементы.Товары.ТекущаяСтрока = Найденные[0].ПолучитьИдентификатор();
КонецПроцедуры
Выделить все найденные строки
Сначала включите множественное выделение — в свойствах элемента таблицы в конфигураторе или кодом. Затем очистите старое выделение и добавьте идентификаторы.
&НаКлиенте
Процедура ВыделитьСтрокиБезЦены(Команда)
Элементы.Товары.РежимВыделения = РежимВыделенияТаблицы.Множественный;
Элементы.Товары.ВыделенныеСтроки.Очистить();
ПерваяНайдена = Ложь;
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Цена = 0 Тогда
Ид = Строка.ПолучитьИдентификатор();
Элементы.Товары.ВыделенныеСтроки.Добавить(Ид);
Если Не ПерваяНайдена Тогда
Элементы.Товары.ТекущаяСтрока = Ид;
ПерваяНайдена = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Активную строку ставим на первую найденную, чтобы таблица прокрутилась к выделению. Иначе выделенные строки могут оказаться за пределами видимой области.
Обработать то, что выделил пользователь
Обратная задача — пройти по выделенным строкам. В ВыделенныеСтроки лежат идентификаторы, строки по ним достают через НайтиПоИдентификатору():
&НаКлиенте
Процедура ОбнулитьСкидкуВВыделенных(Команда)
Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
Строка = Объект.Товары.НайтиПоИдентификатору(Ид);
Если Строка <> Неопределено Тогда
Строка.ПроцентСкидки = 0;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если обработка удаляет выделенные строки, сначала соберите идентификаторы в отдельный массив, а удаляйте уже по нему. Удаление прямо в цикле по ВыделенныеСтроки меняет коллекцию, по которой вы идёте.
Выделение в динамическом списке
В форме списка справочника или журнала документов ВыделенныеСтроки хранит не идентификаторы, а ссылки. Поэтому и добавлять в выделение нужно ссылки:
&НаКлиенте
Процедура ВыделитьЭлементы(МассивСсылок)
Элементы.Список.ВыделенныеСтроки.Очистить();
Для Каждого Ссылка Из МассивСсылок Цикл
Элементы.Список.ВыделенныеСтроки.Добавить(Ссылка);
КонецЦикла;
Если МассивСсылок.Количество() > 0 Тогда
Элементы.Список.ТекущаяСтрока = МассивСсылок[0];
КонецЕсли;
КонецПроцедуры
Строка попадёт в выделение, только если она проходит текущий отбор списка. Элемент, скрытый отбором или находящийся в свёрнутой группе иерархического списка, подсвечен не будет.
Реакция на программную смену строки
Обработчик ПриАктивизацииСтроки срабатывает и тогда, когда строку меняет код, а не пользователь. Если в нём заполняются зависимые поля или вызывается сервер, программное выделение в цикле запустит его много раз подряд.
Два способа этого избежать:
- 🚦 поставить флаг в реквизите формы перед массовым выделением и проверять его в начале
ПриАктивизацииСтроки; - ⏳ в самом обработчике не делать работу сразу, а подключить обработчик ожидания через
ПодключитьОбработчикОжидания("ОбновитьПодвал", 0.1, Истина)— тогда отработает только последняя активизация.
Поиск на сервере по сложному условию
Когда условие требует данных из базы (например, «товары, у которых нет остатка»), ищите на сервере и возвращайте на клиент массив идентификаторов. Идентификаторы одинаковы на клиенте и сервере в пределах одной формы, поэтому их можно безопасно передавать через серверный вызов.
&НаСервере
Функция ИдентификаторыСтрокПоУсловию()
Результат = Новый Массив;
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Номенклатура.ПометкаУдаления Тогда
Результат.Добавить(Строка.ПолучитьИдентификатор());
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
На клиенте результат раскладывается в ВыделенныеСтроки тем же циклом, что и выше. Для больших табличных частей обращение через точку к реквизиту ссылки в цикле лучше заменить одним запросом по списку номенклатуры.
Частые вопросы
Можно ли снять выделение и убрать курсор со всех строк?
Элементы.Товары.ВыделенныеСтроки.Очистить(). Активная строка в непустой таблице остаётся всегда — её можно только переставить.Как программно выделить строку в табличной части дерева значений на форме?
ТекущаяСтрока и идентификатор. Элементы дерева берут через ПолучитьЭлементы() на каждом уровне, идентификатор — методом ПолучитьИдентификатор() найденного элемента.Работает ли этот код в веб-клиенте и мобильном клиенте?
ТекущаяСтрока, ВыделенныеСтроки и ТекущийЭлемент — свойства управляемой формы, они не зависят от вида клиента.Сохраняется ли идентификатор строки между открытиями формы?
Как выделить строку в табличной части обработки, а не документа?
Объект, элемент таблицы — в Элементы. Для таблицы значений в реквизите формы (не табличной части) работает такой же подход с ПолучитьИдентификатор().