Текущая строка, выделение и подсветка в таблице управляемой формы 1С 8.3

· 9 мин

Содержание

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

Главная ловушка — путать три вещи: текущую строку (где стоит курсор), выделенные строки (подсвеченные системным цветом) и визуальную подсветку цветом по условию. Это разные механизмы с разным кодом. Примеры рассчитаны на платформу 8.3 и управляемые формы; про обычные формы — отдельный раздел.

Что значит «выделить строку» в таблице управляемой формы

На форме таблица — это элемент ТаблицаФормы. Данные лежат в реквизите формы: табличной части объекта (Объект.Товары), таблице значений, дереве или динамическом списке. Код работает с элементом, а не с данными.

У элемента таблицы есть свойства, которые отвечают за выделение:

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

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

  • 🔹 Текущая строка всегда одна. Это строка с фокусом, её подсвечивает рамка или цвет курсора.
  • 🔹 Выделенных может быть много, но только при множественном режиме. В одиночном режиме выделенная строка совпадает с текущей.
  • 🔹 Цветная подсветка по условию (например, красным — строки с нулевым количеством) к выделению не относится. Это оформление, и делается оно через условное оформление.

Свойство РежимВыделенияСтроки = Ячейка даёт «табличный» курсор по ячейкам, как в Excel. Для выделения целой строки при клике ставьте Строка.

Идентификатор строки и коллекция ВыделенныеСтроки

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

Сделать строку текущей

Пример: после подбора номенклатуры поставить курсор на строку с нужным товаром.

&НаКлиенте
Процедура ПерейтиКТовару(Номенклатура)

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

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

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

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

Выделить несколько строк

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

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

    Элементы.Товары.РежимВыделения = РежимВыделенияТаблицы.Множественный;
    Элементы.Товары.ВыделенныеСтроки.Очистить();

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

    Если ПерваяНайденная <> Неопределено Тогда
        Элементы.Товары.ТекущаяСтрока = ПерваяНайденная;
    КонецЕсли;

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

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

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

Обработка выделенного — самый частый сценарий: «удалить отмеченные», «проставить скидку выбранным». Идентификаторы — простые числа, их можно передать на сервер массивом.

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

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

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

    УстановитьСкидкуНаСервере(МассивИдентификаторов, 5);

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

&НаСервере
Процедура УстановитьСкидкуНаСервере(МассивИдентификаторов, ПроцентСкидки)

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

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

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

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

Как подсветить строку цветом: условное оформление вместо RowAppearance

Тот, кто переходит с обычных форм, ищет ОформлениеСтроки и обработчик ПриВыводеСтроки. В управляемых формах их нет: оформление строк считается на сервере заранее, по правилам. Инструмент — условное оформление формы.

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

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

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

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

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

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

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

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

  1. Поля — к каким элементам формы применить оформление. Указано имя всей таблицы, поэтому подсвечивается строка целиком. Чтобы подсветить одну колонку, укажите имя её поля, например ТоварыКоличество.
  2. Отбор — условие. Левое значение — путь к данным формы, а не имя элемента.
  3. Оформление — что поменять. Кроме ЦветФона часто используют ЦветТекста, Шрифт, Видимость, Текст.

Для динамического списка правило добавляют в собственное условное оформление списка, а путь в отборе указывают как поле запроса:

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

Условное оформление можно настроить и без кода: в конфигураторе откройте форму, вызовите палитру свойств самой формы и найдите свойство «Условное оформление». Код удобнее, когда правила зависят от настроек или правятся в расширении.

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

Переход к нужной строке: курсор, фокус, прокрутка

Установка ТекущаяСтрока сразу прокручивает таблицу к строке. Несколько сценариев навигации, которые встречаются постоянно.

Перейти к последней добавленной строке

&НаКлиенте
Процедура ДобавитьИПерейти(Команда)

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

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

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

Встать на строку при открытии формы списка

У стандартных форм списка и выбора есть параметр ТекущаяСтрока. Передайте его при открытии — и список откроется уже на нужном элементе:

ПараметрыФормы = Новый Структура("ТекущаяСтрока", Контрагент);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, Элементы.Контрагент);

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

Таблица-дерево: раскрыть ветку до строки

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

СтрокаДерева = ДеревоДанных.НайтиПоИдентификатору(Идентификатор);
Родитель = СтрокаДерева.ПолучитьРодителя();
Если Родитель <> Неопределено Тогда
    Элементы.ДеревоДанных.Развернуть(Родитель.ПолучитьИдентификатор(), Ложь);
КонецЕсли;
Элементы.ДеревоДанных.ТекущаяСтрока = Идентификатор;

Второй параметр Развернуть отвечает за раскрытие подчинённых веток: Ложь — раскрыть только этот уровень.

Динамический список: ключи вместо идентификаторов и события строки

В динамическом списке нет данных формы с идентификаторами. Строки адресуются ключом:

Что выводит списокТип ключа строки
Справочник, документ, план видов характеристикСсылка на объект
Регистр сведенийКлюч записи регистра
Произвольный запрос без основной таблицыСлужебный ключ, ссылкой не является

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

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

Перед обращением к МассивДокументов[0] проверьте, что массив не пуст.

Две особенности, о которые спотыкаются:

  • 🔸 Строка должна попадать в отбор. Если документ отфильтрован по периоду или организации, установка ключа ничего не сделает: строки в выборке нет.
  • 🔸 В выделенных бывают группировки. Если в списке включена группировка или иерархия, в ВыделенныеСтроки попадают и строки групп. Их отсекают проверкой типа:
Для Каждого Ключ Из Элементы.Список.ВыделенныеСтроки Цикл
    Если ТипЗнч(Ключ) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
        Продолжить;
    КонецЕсли;
    ОбработатьДокумент(Ключ);
КонецЦикла;

Событие ПриАктивизацииСтроки

Обработчик таблицы ПриАктивизацииСтроки срабатывает при смене текущей строки — и от клика пользователя, и при смене ТекущаяСтрока из кода. В нём обычно обновляют подчинённую таблицу или панель с деталями.

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

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)

    ОтключитьОбработчикОжидания("ОбновитьДетали");
    ПодключитьОбработчикОжидания("ОбновитьДетали", 0.2, Истина);

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

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

    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    ОбновитьДеталиНаСервере(ТекущиеДанные.Ссылка);

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

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

Другие полезные события таблицы:

  • 🔹 Выбор — двойной щелчок или Enter. Параметр ВыбраннаяСтрока содержит идентификатор или ключ строки.
  • 🔹 ПередНачаломИзменения, ПередУдалением — можно запретить действие через Отказ = Истина, например для строк, выделенных цветом как «закрытые».

Обычные формы: ТабличноеПоле и ПриВыводеСтроки

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

// Сделать строку текущей
ЭлементыФормы.ТабличноеПоле1.ТекущаяСтрока = СтрокаТЗ;

// Добавить к выделенным
ЭлементыФормы.ТабличноеПоле1.ВыделенныеСтроки.Добавить(СтрокаТЗ);

Цвет строки задаётся в обработчике ПриВыводеСтроки. Его параметр ОформлениеСтроки — это и есть тот самый RowAppearance:

Процедура ТабличноеПоле1ПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)

    Если ДанныеСтроки.Количество = 0 Тогда
        ОформлениеСтроки.ЦветФона = Новый Цвет(255, 225, 225);
    КонецЕсли;

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

Отличие от управляемых форм принципиальное:

Обычная формаУправляемая форма
Адрес строкиОбъект строкиИдентификатор или ключ
Цвет строкиПриВыводеСтроки, ОформлениеСтрокиУсловное оформление
Где работает код оформленияНа клиенте, на каждую строкуПравила задаются на сервере заранее

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

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

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

Ещё одна частая путаница — индекс и идентификатор. Объект.Товары[0] — это строка по индексу, позиция в коллекции. Идентификатор — другое число, и совпадение с индексом случайно. Код вида Элементы.Товары.ТекущаяСтрока = 0 в лучшем случае ничего не сделает, в худшем — поставит курсор не туда.

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