Подсветка и выделение строк табличной части: код и настройка формы

· 9 мин

Содержание

Строку табличной части в управляемой форме красят через условное оформление: в форме открываете «Условное оформление», задаёте поле, условие отбора и цвет фона. Если строку надо сделать текущей из кода, пишете Элементы.Товары.ТекущаяСтрока = Идентификатор. Это два разных действия, и путают их постоянно.

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

Что такое выделение строки: курсор, выбор и оформление

Под словом «выделить» подразумевают три разные вещи. Выбор способа зависит от того, какую из них вам надо.

ЗадачаЧто использоватьГде работает
Покрасить строки по условиюУсловное оформлениеКлиент, без кода или из модуля
Поставить курсор на нужную строкуТекущаяСтрокаКлиентский код
Узнать, что выбрал пользовательТекущиеДанные, ВыделенныеСтрокиКлиентский код
Подсветить строку с ошибкойУсловное оформление + служебная колонкаФорма целиком

Важно помнить устройство управляемой формы. Табличная часть на форме это реквизит Объект.Товары, а на экране её показывает элемент формы «Товары». Элемент знает про курсор и выделение, реквизит хранит данные. Цвет, видимость и доступность задаются у элемента, а не у данных.

Условное оформление выполняется на сервере при отрисовке формы, а курсором управляет клиент. Поэтому «покрасить» и «встать на строку» всегда живут в разных процедурах.

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

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

  1. Откройте форму документа в конфигураторе и перейдите на закладку «Условное оформление» в свойствах формы.
  2. Нажмите «Добавить» и в поле «Оформляемые поля» укажите колонки таблицы. Если нужна вся строка, добавьте все колонки.
  3. В «Условии» создайте отбор: например, Количество «Равно» 0.
  4. В «Оформлении» выберите «Цвет фона» и задайте мягкий цвет, например светло-жёлтый.
  5. Сохраните, обновите конфигурацию базы данных и откройте документ.

Цвет на всю строку, а не на одну ячейку

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

Несколько правил и порядок срабатывания

Правила применяются по порядку. Если два правила красят одну ячейку, победит нижнее. Держите общие правила выше, а исключения ниже. Включённый флажок «Использование» отключает правило без удаления, удобно при отладке.

Выделение строки из кода: условное оформление программно

Когда условие зависит от настроек или вычисляется, оформление добавляют в модуле формы. Делают это на сервере, в ПриСозданииНаСервере.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	УстановитьОформлениеСтрок();
КонецПроцедуры

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

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

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

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

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

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

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

Имя поля оформления составляется из имени элемента формы: если таблица называется Товары, а колонка Количество, то поле ТоварыКоличество. В условии используется путь к данным: Объект.Товары.Количество. Это самая частая точка путаницы, поэтому проверяйте оба имени в дереве элементов формы.

Если вы вызываете этот код повторно (например, при каждом изменении настроек), старые правила не удаляются сами. Они копятся. Перед добавлением очистите коллекцию: УсловноеОформление.Элементы.Очистить();

Оформление не только цветом

Через УстановитьЗначениеПараметра задаются и другие параметры. Чаще всего берут такие:

  • 🎨 ЦветФона и ЦветТекста — заливка и шрифт;
  • 🔠 Шрифт — жирный или зачёркнутый (например, для отменённых позиций);
  • 👁 Видимость — скрыть колонку по условию;
  • 🔒 Доступность — запретить правку ячейки;
  • 📝 Текст — подменить отображаемое значение, данные при этом не меняются.

Установка текущей строки и перемещение курсора

Теперь вторая задача: после действия поставить курсор на конкретную строку. Например, после подбора товара встать на добавленную позицию.

В управляемой форме строка идентифицируется не номером, а идентификатором. Его даёт метод ПолучитьИдентификатор() у строки коллекции.

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

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

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

Индекс коллекции начинается с нуля, поэтому для пользовательского номера «строка 5» берём элемент с индексом 4. Эта ошибка на единицу самая банальная и самая частая.

После добавления новой строки через Объект.Товары.Добавить() курсор сам не переместится. Делайте так:

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

Если нужно сразу открыть строку на редактирование, после установки текущей строки вызывают Элементы.Товары.ИзменитьСтроку();. Метод работает на клиенте, на сервере его нет.

Найти строку по значению и встать на неё

Чтобы найти позицию по условию, используют НайтиСтроки с структурой отбора:

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

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

НайтиСтроки возвращает массив строк. Если совпадений нет, массив пустой, и обращаться к [0] без проверки нельзя: получите ошибку выхода за границы.

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

Читать выбор из кода нужно в клиентской процедуре. Есть два свойства элемента.

  • ТекущиеДанные — данные строки, на которой стоит курсор. Если курсор никуда не поставлен (пустая таблица), вернётся Неопределено.
  • ВыделенныеСтроки — массив идентификаторов всех строк, выделенных мышью с Ctrl или Shift.

Типичная кнопка «Удалить выделенные»:

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

	Выделенные = Элементы.Товары.ВыделенныеСтроки;

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

	// Удаляем с конца, чтобы не сбивать идентификаторы
	Для Индекс = 1 По Выделенные.Количество() Цикл
		ИдСтроки = Выделенные[Выделенные.Количество() - Индекс];
		Строка   = Объект.Товары.НайтиПоИдентификатору(ИдСтроки);
		Объект.Товары.Удалить(Строка);
	КонецЦикла;

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

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

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

События таблицы: когда реагировать на выбор и смену строки

Иногда выделение нужно привязать к действию пользователя. В свойствах элемента-таблицы доступны события:

СобытиеКогда срабатываетДля чего
ПриАктивизацииСтрокиКурсор перешёл на другую строкуПоказать подробности текущей позиции
ВыборДвойной щелчок или Enter по строкеОткрыть карточку, выполнить действие
ПередНачаломИзмененияПеред правкой строкиЗапретить редактирование
ПриНачалеРедактированияСтрока перешла в режим правкиЗаполнить значения по умолчанию
ПриОкончанииРедактированияСтрока записанаПересчитать итоги

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

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

Подсветка строк с ошибками при проверке данных

Хороший приём для валидации: не показывать пользователю сообщение «в строке 14 ошибка», а ещё и покрасить строку. Нужна служебная колонка, которая хранит признак.

  1. Добавьте в табличную часть реквизит ЕстьОшибка с типом «Булево». Если таблица не хранится в базе, это реквизит формы-таблицы значений.
  2. Создайте условное оформление: ТоварыЕстьОшибка равно Истина — цвет фона светло-красный.
  3. В проверке заполняйте признак и выводите сообщение с привязкой к строке.
&НаСервере
Процедура ПроверитьСтроки(Отказ)

	Для Каждого Строка Из Объект.Товары Цикл
		Строка.ЕстьОшибка = (Строка.Количество <= 0);

		Если Строка.ЕстьОшибка Тогда
			Индекс = Объект.Товары.Индекс(Строка);
			ТекстОшибки = "Укажите количество больше нуля";
			Сообщить(ТекстОшибки + " (строка " + (Индекс + 1) + ")");
			Отказ = Истина;
		КонецЕсли;
	КонецЦикла;

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

Лучше выводить сообщение через объект СообщениеПользователю с полем Поле = "Объект.Товары[" + Индекс + "].Количество". Тогда клиент сам поставит курсор на проблемную ячейку, и отдельно выделять её не придётся. Это встроенное поведение, и оно надёжнее ручной установки ТекущаяСтрока.

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

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

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

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

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

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

Курсор в обычной форме ставят иначе: ЭлементыФормы.Товары.ТекущаяСтрока = СтрокаТЧ;, причём присваивается сама строка, а не идентификатор. Если вы переносите код между типами форм, это первое, что ломается.

Типичные проблемы с выделением и как их исправить

Несколько ситуаций, которые встречаются чаще всего.

  • 🟥 Правило есть, цвета нет. Проверьте имя поля оформления: ТоварыКоличество, а не Количество и не Объект.Товары.Количество. В поле оформления идёт имя элемента формы.
  • 🟥 Цвет пропал после перезаполнения. Если вы очистили УсловноеОформление.Элементы и не добавили правила заново, форма вернётся к виду по умолчанию.
  • 🟥 ТекущиеДанные равно Неопределено. Таблица пуста или курсор не стоит на строке. Проверяйте перед обращением.
  • 🟥 Курсор прыгает на первую строку. После обновления формы с сервера текущая строка может сброситься. Запомните идентификатор перед вызовом и верните его после.
  • 🟥 Выделение не видно на цветном фоне. Подберите светлую заливку: тёмная сливается с системной подсветкой выбранной строки.
  • 🟥 На сервере нет Элементы.Товары.ТекущаяСтрока. Свойства элементов управления доступны только на клиенте. Серверный код получает данные параметрами.

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

Что вам нужно сделать со строкой?

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

Можно ли выделить сразу несколько строк программно?
Прочитать выделение можно через `ВыделенныеСтроки`. Задать его целиком из кода в управляемой форме нельзя: надёжно можно поставить только текущую строку. Если нужен визуальный результат, используйте условное оформление.
Почему условное оформление не меняет цвет выбранной строки?
Системная подсветка выбранной строки накладывается поверх вашей заливки. Цвет виден у строк без курсора. Для проверки уберите курсор на другую строку.
Как покрасить строку по значению из другой таблицы?
Сначала вынесите нужное значение в служебную колонку или реквизит формы при заполнении, а в условии сравнивайте уже эту колонку. Прямого отбора по другой таблице условное оформление не делает.
Как сохранить текущую строку при обновлении формы?
Запомните `Элементы.Товары.ТекущаяСтрока` перед вызовом сервера, после возврата присвойте то же значение. Если строка могла быть удалена, сначала проверьте её через `НайтиПоИдентификатору`.
Работает ли подсветка в веб-клиенте и на мобильной платформе?
Условное оформление поддерживается во всех клиентах, но на мобильной платформе набор параметров беднее. Цвет фона и текста доступны, остальное проверяйте на своём устройстве.