К статье
Практический материал

Разработка и Конфигурация · 12 мин

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

Как программно выделить строки табличной части в 1С: методы НайтиСтроки, ВыделенныеСтроки, работа с таблицей формы, примеры кода и типичные ошибки разработчиков.

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

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

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

Как устроено выделение строк в управляемой форме

Элемент формы «Таблица» (тип ТаблицаФормы) имеет два ключевых свойства для навигации и выделения. Свойство ТекущаяСтрока хранит идентификатор активной строки — ту, на которой стоит курсор. Свойство ВыделенныеСтроки — это коллекция идентификаторов всех выделенных строк, включая текущую, если она входит в выделение.

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

Ещё одно отличие от обычных форм: в управляемом приложении нет метода «выделить диапазон» напрямую. Множественное выделение формируется последовательным добавлением идентификаторов в коллекцию ВыделенныеСтроки. Платформа сама отрисует выделение после выполнения серверного или клиентского кода.

Как выделить одну строку табличной части

Самый простой сценарий — сделать конкретную строку текущей и выделенной. Для этого нужно найти строку в данных формы, получить её идентификатор и присвоить его свойству ТекущаяСтрока элемента таблицы.

Типовой код для формы документа, где нужно активировать строку с определённой номенклатурой:

&НаКлиенте

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

Для Каждого СтрокаТовара Из Объект.Товары Цикл

Если СтрокаТовара.Номенклатура = ИскомаяНоменклатура Тогда

Элементы.Товары.ТекущаяСтрока = СтрокаТовара.ПолучитьИдентификатор();

Прервать;

КонецЕсли;

КонецЦикла;

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

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

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

Как выделить несколько строк по условию

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

&НаКлиенте

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

Элементы.Товары.ВыделенныеСтроки.Очистить();

Для Каждого СтрокаТовара Из Объект.Товары Цикл

Если СтрокаТовара.Количество = 0

Или СтрокаТовара.Цена = 0 Тогда

Элементы.Товары.ВыделенныеСтроки.Добавить(

СтрокаТовара.ПолучитьИдентификатор());

КонецЕсли;

КонецЦикла;

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

Если строки нужно искать по точному совпадению нескольких полей, удобнее использовать метод НайтиСтроки с параметрами отбора — он возвращает массив строк данных формы:

Отбор = Новый Структура("Склад, Отменено", СкладОтгрузки, Ложь);

НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);

Элементы.Товары.ВыделенныеСтроки.Очистить();

Для Каждого СтрокаТовара Из НайденныеСтроки Цикл

Элементы.Товары.ВыделенныеСтроки.Добавить(

СтрокаТовара.ПолучитьИдентификатор());

КонецЦикла;

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

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

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

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

&НаКлиенте

Процедура ОбработатьВыделенные(Команда)

Для Каждого ИдентификаторСтроки Из Элементы.Товары.ВыделенныеСтроки Цикл

СтрокаТовара = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);

Если СтрокаТовара <> Неопределено Тогда

СтрокаТовара.СтавкаНДС = ПредопределенноеЗначение(

"Перечисление.СтавкиНДС.БезНДС");

КонецЕсли;

КонецЦикла;

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

Проверка Если СтрокаТовара <> Неопределено обязательна: идентификатор мог устареть, если данные формы обновлялись между выделением и вызовом обработчика. Метод НайтиПоИдентификатору в этом случае вернёт Неопределено, и обращение к полям строки без проверки вызовет ошибку.

При удалении выделенных строк есть тонкость: удалять строки в цикле по ВыделенныеСтроки нельзя, потому что коллекция изменится прямо во время обхода. Сначала соберите строки в массив, затем удаляйте их из табличной части методом Удалить.

Выделение строк в динамическом списке

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

Элементы.Список.ТекущаяСтрока = СсылкаНаДокумент;

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

Альтернативы выделению в динамическом списке

Условное оформление списка

Подсвечивает строки цветом по условию без выделения. Подходит для визуальной индикации ошибок и статусов

Отбор динамического списка

Оставляет в списке только нужные строки. Подходит, когда пользователю важно работать именно с подмножеством

ВыделенныеСтроки по известным ссылкам

Работает, если ключи записей известны заранее, например получены запросом на сервере

Типичные ошибки и ограничения

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

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

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

Типичные ошибки
01
Передача номера строки вместо идентификатора — выделяется не та строка или ничего не происходит
02
Установка выделения до обновления данных формы — идентификаторы пересоздаются, выделение сбрасывается
03
Удаление строк в цикле по ВыделенныеСтроки — коллекция меняется во время обхода, часть строк пропускается
04
Обращение к НайтиПоИдентификатору без проверки на Неопределено — ошибка при устаревшем идентификаторе
05
Попытка перебрать строки динамического списка на клиенте — данные списка недоступны для обхода

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

Чтобы убедиться, что выделение установлено корректно, проверьте количество элементов в коллекции ВыделенныеСтроки и значение ТекущаяСтрока. Для отладки удобно вывести идентификаторы в сообщение и сопоставить их с данными через НайтиПоИдентификатору.

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

Контрольные точки

Как проверить результат

Количество выделенных строк
Норма

ВыделенныеСтроки.Количество() равно числу найденных по условию строк

Тревожный признак

Количество равно нулю или меньше ожидаемого — проверьте условие поиска и идентификаторы

Позиционирование
Норма

Форма прокручена к первой выделенной строке, она видна пользователю

Тревожный признак

Выделенные строки за пределами видимой области — установите ТекущаяСтрока

Актуальность идентификаторов
Норма

НайтиПоИдентификатору возвращает строку для каждого идентификатора

Тревожный признак

Метод возвращает Неопределено — данные формы обновлялись после получения идентификаторов

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

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

Чем выделение строки отличается от установки текущей строки?

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

Как выделить все строки табличной части?

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

Почему после установки ТекущаяСтрока выделяется не та строка?

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

Можно ли программно выделить строки в динамическом списке по условию?

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

Как сохранить выделение после обновления данных формы?

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

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

Сначала пройдите по коллекции ВыделенныеСтроки и соберите сами строки данных через НайтиПоИдентификатору в отдельный массив. Затем удалите каждую строку методом Удалить табличной части. Удалять строки непосредственно в цикле по ВыделенныеСтроки нельзя — коллекция изменится во время обхода.

Итог

Что важно запомнить

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