Как выделить строки таблицы формы из кода: ВыделенныеСтроки, ТекущаяСтрока и пометки

· 9 мин

Содержание

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

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

Как устроено выделение в таблице формы

У элемента формы «Таблица», связанного с табличной частью, за выделение отвечают три свойства:

СвойствоЧто хранитЧтение / запись
ВыделенныеСтрокиМассив идентификаторов выделенных строкЧтение и изменение
ТекущаяСтрокаИдентификатор строки под курсоромЧтение и запись
ТекущиеДанныеДанные текущей строки (колонки как свойства)Только на клиенте
РежимВыделенияОдиночный или МножественныйЗадаётся в свойствах элемента или кодом

Главное отличие от работы с самими данными: в управляемой форме таблица оперирует идентификаторами, а не строками. Идентификатор — целое число, его возвращает метод ПолучитьИдентификатор() у строки коллекции ДанныеФормыКоллекция. Обратное преобразование — Объект.Товары.НайтиПоИдентификатору(Ид).

Идентификатор не равен номеру строки. Строка с НомерСтроки = 3 может иметь идентификатор 17, если до этого строки добавлялись и удалялись.

Есть ли метод «ВыделитьСтроку»

В управляемой форме отдельного метода с таким именем у таблицы нет. Его роль выполняет обычный массив: ВыделенныеСтроки.Добавить(Ид) выделяет строку, Удалить(Индекс) снимает выделение, Очистить() сбрасывает всё. Так проще: с выделением работают теми же приёмами, что и с любым массивом.

Если нужно выделить несколько строк, проверьте свойство РежимВыделения. В одиночном режиме пользователь и код получат максимум одну выделенную строку. Переключить можно в конфигураторе или кодом: Элементы.Товары.РежимВыделения = РежимВыделенияТаблицы.Множественный;.

Как программно выделить строки табличной части: базовый пример

Типичная задача — по кнопке выделить все строки, где не заполнено количество. Код размещают в модуле формы на клиенте:

&НаКлиенте
Процедура ВыделитьНезаполненные(Команда)

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

	Если Найденные.Количество() = 0 Тогда
		ПоказатьПредупреждение(, "Строк с нулевым количеством нет.");
		Возврат;
	КонецЕсли;

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

	ЭлементТаблицы.ВыделенныеСтроки.Очистить();
	Для Каждого СтрокаТЧ Из Найденные Цикл
		ЭлементТаблицы.ВыделенныеСтроки.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
	КонецЦикла;

	ТекущийЭлемент = ЭлементТаблицы;

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

Что здесь происходит:

  1. НайтиСтроки возвращает массив строк, подходящих под отбор. Отбор — структура «имя колонки → значение».
  2. Текущую строку задаём первой. Курсор переходит на неё, таблица прокручивается.
  3. Очищаем старое выделение и добавляем идентификаторы найденных строк.
  4. ТекущийЭлемент = ЭлементТаблицы переводит фокус на таблицу, чтобы выделение было видно сразу.

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

Выделение по сложному условию

НайтиСтроки умеет только точное равенство. Для условий «сумма больше 10 000» или «цена ниже закупочной» перебирайте строки вручную:

&НаКлиенте
Процедура ВыделитьКрупные(Команда)
	Элементы.Товары.ВыделенныеСтроки.Очистить();
	Для Каждого СтрокаТЧ Из Объект.Товары Цикл
		Если СтрокаТЧ.Сумма > 10000 Тогда
			Элементы.Товары.ВыделенныеСтроки.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

На таблице в 300–500 строк такой цикл на клиенте выполняется незаметно. Если строк тысячи, а условие требует данных из базы (остатки, цены поставщика), вычислите список идентификаторов на сервере, верните массив и уже на клиенте добавьте его в ВыделенныеСтроки.

Как прочитать, что выделил пользователь

Обратная задача — обработать строки, которые пользователь выделил мышью или через Shift/Ctrl:

&НаКлиенте
Процедура ОбнулитьСкидку(Команда)

	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(Ид);
		Если СтрокаТЧ <> Неопределено Тогда
			СтрокаТЧ.ПроцентСкидки = 0;
		КонецЕсли;
	КонецЦикла;

	Модифицированность = Истина;

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

Если обработка тяжёлая и должна идти на сервере, передайте туда копию массива идентификаторов. На сервере НайтиПоИдентификатору тоже работает:

&НаКлиенте
Процедура ПересчитатьВыделенные(Команда)
	Идентификаторы = Новый Массив;
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		Идентификаторы.Добавить(Ид);
	КонецЦикла;
	ПересчитатьВыделенныеНаСервере(Идентификаторы);
КонецПроцедуры

&НаСервере
Процедура ПересчитатьВыделенныеНаСервере(Идентификаторы)
	Для Каждого Ид Из Идентификаторы Цикл
		СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(Ид);
		СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
	КонецЦикла;
КонецПроцедуры

Текущая строка: курсор, прокрутка и фокус

Текущая строка и выделение — разные вещи. Выделенных строк может быть десять, текущая всегда одна: это строка с рамкой курсора, с которой работает ТекущиеДанные.

Три частых сценария:

  • ➕ После добавления строки поставить на неё курсор: Новая = Объект.Товары.Добавить(); Элементы.Товары.ТекущаяСтрока = Новая.ПолучитьИдентификатор();
  • 🔍 Найти товар и перейти к нему — НайтиСтроки по реквизиту Номенклатура, затем ТекущаяСтрока на первую найденную.
  • ✏️ Сразу открыть ячейку на редактирование — после установки текущей строки задать колонку Элементы.Товары.ТекущийЭлемент = Элементы.ТоварыКоличество; и вызвать Элементы.Товары.ИзменитьСтроку();.

Событие ПриАктивизацииСтроки срабатывает и при программной смене текущей строки. Если в нём есть серверный вызов, при массовом переборе строк форма начнёт тормозить. Обычный приём — в обработчике только подключать отложенный обработчик через ПодключитьОбработчикОжидания("ОбработатьСменуСтроки", 0.1, Истина), а тяжёлую работу делать в нём.

Пометка-флаг вместо выделения: когда отметка должна сохраниться

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

Удобно связать оба механизма: выделил строки мышью — нажал кнопку — у них встали флажки.

&НаКлиенте
Процедура ОтметитьВыделенные(Команда)
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		Объект.Товары.НайтиПоИдентификатору(Ид).Пометка = Истина;
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура СнятьВсеОтметки(Команда)
	Для Каждого СтрокаТЧ Из Объект.Товары Цикл
		СтрокаТЧ.Пометка = Ложь;
	КонецЦикла;
КонецПроцедуры

Пользователю удобно видеть, сколько строк отмечено. Посчитайте их в обработчике ПриИзменении колонки флажка и выведите в заголовок группы или надпись:

&НаКлиенте
Процедура ТоварыПометкаПриИзменении(Элемент)
	Отмечено = Объект.Товары.НайтиСтроки(Новый Структура("Пометка", Истина)).Количество();
	Элементы.ГруппаТовары.Заголовок = СтрШаблон("Товары (отмечено: %1)", Формат(Отмечено, "ЧН=0; ЧГ=0"));
КонецПроцедуры

Тот же пересчёт вызывайте в конце команд «Отметить выделенные» и «Снять все отметки», иначе счётчик отстанет от флажков.

Обратное направление — выделить все отмеченные строки — делается тем же НайтиСтроки(Новый Структура("Пометка", Истина)) из базового примера.

МеханизмГде живётПереживает закрытие формыКогда брать
ВыделенныеСтрокиЭлемент формыНетРазовая операция «здесь и сейчас»
Реквизит ПометкаДанные объекта или реквизит формыДа, если реквизит записываетсяОтбор строк для последующей обработки
Условное оформлениеНастройки формыПересчитывается самоВизуальный акцент без действий

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

Флаг «Активность» — это не выделение

В наборах записей регистров у каждой записи есть стандартный реквизит Активность. Он определяет, участвует ли запись в итогах регистра, и к выделению в интерфейсе отношения не имеет. Снятая активность меняет учётные данные. Не используйте Активность как пометку для выбора строк — это исказит остатки и обороты.

Как сохранить выделение строк при изменении данных

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

Выделение слетает, когда таблицу перезаполняют целиком: Очистить() и заполнение заново, Загрузить() из таблицы значений, ЗначениеВДанныеФормы. Новые строки получают новые идентификаторы, и старые значения в ВыделенныеСтроки указывают в никуда.

Решение — запомнить не идентификаторы, а смысловой ключ строки (номенклатура, характеристика, код), и после перезаполнения выделить заново:

&НаКлиенте
Процедура ПерезаполнитьСохраняяВыделение(Команда)

	Ключи = Новый Массив;
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		Ключи.Добавить(Объект.Товары.НайтиПоИдентификатору(Ид).Номенклатура);
	КонецЦикла;

	ПерезаполнитьНаСервере();

	Элементы.Товары.ВыделенныеСтроки.Очистить();
	Для Каждого Номенклатура Из Ключи Цикл
		Найденные = Объект.Товары.НайтиСтроки(Новый Структура("Номенклатура", Номенклатура));
		Для Каждого СтрокаТЧ Из Найденные Цикл
			Элементы.Товары.ВыделенныеСтроки.Добавить(СтрокаТЧ.ПолучитьИдентификатор());
		КонецЦикла;
	КонецЦикла;

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

Если одна номенклатура встречается в нескольких строках, восстановятся все. Нужна точность до строки — используйте составной ключ: номенклатура плюс характеристика или плюс склад.

Номер строки как ключ годится, только если после перезаполнения порядок гарантированно тот же. После сортировки или свёртки он не подходит.

Подсветка строк условным оформлением

Иногда «выделить» означает не выбрать строки, а покрасить их: просроченные — красным, без цены — жёлтым. Для этого выделение не нужно. Работает условное оформление формы, и оно пересчитывается само при изменении данных.

Оформление задают в ПриСозданииНаСервере:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	ЭлементУО = УсловноеОформление.Элементы.Добавить();

	ПолеУО = ЭлементУО.Поля.Элементы.Добавить();
	ПолеУО.Поле = Новый ПолеКомпоновкиДанных(Элементы.ТоварыНоменклатура.Имя);
	ПолеУО = ЭлементУО.Поля.Элементы.Добавить();
	ПолеУО.Поле = Новый ПолеКомпоновкиДанных(Элементы.ТоварыЦена.Имя);

	Отбор = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Цена");
	Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	Отбор.ПравоеЗначение = 0;

	ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 235, 200));

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

Тонкости:

  • 🎯 В Поля указывают имена элементов формы (колонок таблицы), а в отборе — путь к данным Объект.Товары.Цена. Путаница между ними — главная причина «оформление не применяется».
  • 🎨 Чтобы закрасить строку целиком, добавьте в Поля все колонки таблицы.
  • 🔤 Кроме ЦветФона часто используют ЦветТекста, Шрифт и Видимость.

Условное оформление не меняет ВыделенныеСтроки. Если нужно и подсветить, и выделить — делайте оба шага отдельно.

Обычные формы и динамические списки

Табличное поле обычной формы

В обычных формах (толстый клиент) логика та же, но объекты другие. Таблица — это ТабличноеПоле, а в коллекции выделения лежат сами строки, а не идентификаторы:

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

Подсветку в обычной форме делают в событии табличного поля ПриВыводеСтроки через параметр ОформлениеСтроки: например, ОформлениеСтроки.ЦветФона = Новый Цвет(255, 235, 200); по условию на ДанныеСтроки.

Динамический список

Для списка справочника или документа ВыделенныеСтроки содержит не числа, а ключи строк — для ссылочных объектов это ссылки. Чтобы поставить курсор на нужный элемент, присвойте ссылку: Элементы.Список.ТекущаяСтрока = НужнаяСсылка;. Выделение задаётся так же: Элементы.Список.ВыделенныеСтроки.Добавить(Ссылка).

Список подгружается порциями, поэтому курсор на элемент, который сейчас не попадает под отбор, не встанет.

Почему выделение не срабатывает: разбор ошибок

Диагностика: выберите симптом

Пример корректного удаления выделенных строк:

&НаКлиенте
Процедура УдалитьВыделенные(Команда)
	Идентификаторы = Новый Массив;
	Для Каждого Ид Из Элементы.Товары.ВыделенныеСтроки Цикл
		Идентификаторы.Добавить(Ид);
	КонецЦикла;
	Для Каждого Ид Из Идентификаторы Цикл
		Объект.Товары.Удалить(Объект.Товары.НайтиПоИдентификатору(Ид));
	КонецЦикла;
КонецПроцедуры

Идентификаторы оставшихся строк при удалении соседних не меняются, поэтому поиск по копии массива надёжен.

Частые вопросы

Можно ли выделить строки табличной части до открытия формы?
В ПриСозданииНаСервере строки уже доступны, но надёжнее выделять в ПриОткрытии на клиенте, когда таблица выведена на экран.
Сохранится ли выделение, если пользователь закроет и откроет документ?
Нет. Выделение — свойство элемента формы. Для сохранения нужен реквизит-пометка, который записывается вместе с объектом.
Как выделить все строки табличной части кодом?
Очистите ВыделенныеСтроки и в цикле по Объект.Товары добавьте идентификатор каждой строки. Пользователю то же даёт стандартная команда выделения всех строк (Ctrl+A).
Как узнать, сколько строк выделено?
Элементы.Товары.ВыделенныеСтроки.Количество(). Число удобно выводить в заголовок команды или в надпись над таблицей.
Работает ли этот код в веб-клиенте?
Да. ВыделенныеСтроки, ТекущаяСтрока и НайтиПоИдентификатору одинаково работают в тонком и веб-клиенте.