Подсветка и выделение строк табличной части: код и настройка формы
Содержание
Строку табличной части в управляемой форме красят через условное оформление: в форме открываете «Условное оформление», задаёте поле, условие отбора и цвет фона. Если строку надо сделать текущей из кода, пишете Элементы.Товары.ТекущаяСтрока = Идентификатор. Это два разных действия, и путают их постоянно.
Первое меняет вид строк по правилу, второе двигает курсор. Ниже оба способа с кодом, плюс подсветка по ошибке проверки, работа с несколькими выделенными строками и типовые грабли. Примеры написаны под платформу 8.3 и управляемые формы. Для обычных форм отдельный раздел.
Что такое выделение строки: курсор, выбор и оформление
Под словом «выделить» подразумевают три разные вещи. Выбор способа зависит от того, какую из них вам надо.
| Задача | Что использовать | Где работает |
|---|---|---|
| Покрасить строки по условию | Условное оформление | Клиент, без кода или из модуля |
| Поставить курсор на нужную строку | ТекущаяСтрока | Клиентский код |
| Узнать, что выбрал пользователь | ТекущиеДанные, ВыделенныеСтроки | Клиентский код |
| Подсветить строку с ошибкой | Условное оформление + служебная колонка | Форма целиком |
Важно помнить устройство управляемой формы. Табличная часть на форме это реквизит Объект.Товары, а на экране её показывает элемент формы «Товары». Элемент знает про курсор и выделение, реквизит хранит данные. Цвет, видимость и доступность задаются у элемента, а не у данных.
Условное оформление выполняется на сервере при отрисовке формы, а курсором управляет клиент. Поэтому «покрасить» и «встать на строку» всегда живут в разных процедурах.
Подсветка строк через условное оформление без кода
Это самый быстрый путь, программист не нужен. Подходит для типовых задач: красить строки с нулевым количеством, просроченные позиции, строки без цены.
- Откройте форму документа в конфигураторе и перейдите на закладку «Условное оформление» в свойствах формы.
- Нажмите «Добавить» и в поле «Оформляемые поля» укажите колонки таблицы. Если нужна вся строка, добавьте все колонки.
- В «Условии» создайте отбор: например,
Количество«Равно»0. - В «Оформлении» выберите «Цвет фона» и задайте мягкий цвет, например светло-жёлтый.
- Сохраните, обновите конфигурацию базы данных и откройте документ.
Цвет на всю строку, а не на одну ячейку
Типичная жалоба: покрасилась одна колонка. Причина простая, в списке оформляемых полей указана только она. Добавьте в оформляемые поля все колонки таблицы или оставьте поле пустым, тогда правило касается всех полей формы, где подходит условие. Для табличной части лучше перечислять явно, чтобы не перекрасить лишнее.
Несколько правил и порядок срабатывания
Правила применяются по порядку. Если два правила красят одну ячейку, победит нижнее. Держите общие правила выше, а исключения ниже. Включённый флажок «Использование» отключает правило без удаления, удобно при отладке.
Выделение строки из кода: условное оформление программно
Когда условие зависит от настроек или вычисляется, оформление добавляют в модуле формы. Делают это на сервере, в ПриСозданииНаСервере.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьОформлениеСтрок();
КонецПроцедуры
&НаСервере
Процедура УстановитьОформлениеСтрок()
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// Колонки, к которым применяется правило
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыНоменклатура");
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыКоличество");
// Условие: количество равно нулю
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Количество");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = 0;
ЭлементОтбора.Использование = Истина;
// Оформление
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 245, 190));
КонецПроцедуры
Имя поля оформления составляется из имени элемента формы: если таблица называется Товары, а колонка Количество, то поле ТоварыКоличество. В условии используется путь к данным: Объект.Товары.Количество. Это самая частая точка путаницы, поэтому проверяйте оба имени в дереве элементов формы.
Если вы вызываете этот код повторно (например, при каждом изменении настроек), старые правила не удаляются сами. Они копятся. Перед добавлением очистите коллекцию: УсловноеОформление.Элементы.Очистить();
Оформление не только цветом
Через УстановитьЗначениеПараметра задаются и другие параметры. Чаще всего берут такие:
- 🎨
ЦветФонаиЦветТекста— заливка и шрифт; - 🔠
Шрифт— жирный или зачёркнутый (например, для отменённых позиций); - 👁
Видимость— скрыть колонку по условию; - 🔒
Доступность— запретить правку ячейки; - 📝
Текст— подменить отображаемое значение, данные при этом не меняются.
Установка текущей строки и перемещение курсора
Теперь вторая задача: после действия поставить курсор на конкретную строку. Например, после подбора товара встать на добавленную позицию.
В управляемой форме строка идентифицируется не номером, а идентификатором. Его даёт метод ПолучитьИдентификатор() у строки коллекции.
&НаКлиенте
Процедура ПерейтиКСтроке(НомерСтроки)
Строка = Объект.Товары[НомерСтроки - 1];
Элементы.Товары.ТекущаяСтрока = Строка.ПолучитьИдентификатор();
КонецПроцедуры
Индекс коллекции начинается с нуля, поэтому для пользовательского номера «строка 5» берём элемент с индексом 4. Эта ошибка на единицу самая банальная и самая частая.
После добавления новой строки через Объект.Товары.Добавить() курсор сам не переместится. Делайте так:
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = Номенклатура;
НоваяСтрока.Количество = 1;
Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
Если нужно сразу открыть строку на редактирование, после установки текущей строки вызывают Элементы.Товары.ИзменитьСтроку();. Метод работает на клиенте, на сервере его нет.
Найти строку по значению и встать на неё
Чтобы найти позицию по условию, используют НайтиСтроки с структурой отбора:
Отбор = Новый Структура("Номенклатура", ТекущаяНоменклатура);
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Если НайденныеСтроки.Количество() > 0 Тогда
Элементы.Товары.ТекущаяСтрока = НайденныеСтроки[0].ПолучитьИдентификатор();
КонецЕсли;
НайтиСтроки возвращает массив строк. Если совпадений нет, массив пустой, и обращаться к [0] без проверки нельзя: получите ошибку выхода за границы.
Какие строки выбрал пользователь: ТекущиеДанные и ВыделенныеСтроки
Читать выбор из кода нужно в клиентской процедуре. Есть два свойства элемента.
ТекущиеДанные— данные строки, на которой стоит курсор. Если курсор никуда не поставлен (пустая таблица), вернётсяНеопределено.ВыделенныеСтроки— массив идентификаторов всех строк, выделенных мышью с Ctrl или Shift.
Типичная кнопка «Удалить выделенные»:
&НаКлиенте
Процедура УдалитьВыделенные(Команда)
Выделенные = Элементы.Товары.ВыделенныеСтроки;
Если Выделенные.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Выделите хотя бы одну строку.");
Возврат;
КонецЕсли;
// Удаляем с конца, чтобы не сбивать идентификаторы
Для Индекс = 1 По Выделенные.Количество() Цикл
ИдСтроки = Выделенные[Выделенные.Количество() - Индекс];
Строка = Объект.Товары.НайтиПоИдентификатору(ИдСтроки);
Объект.Товары.Удалить(Строка);
КонецЦикла;
КонецПроцедуры
Идентификаторы в управляемой форме стабильны, они не пересчитываются при удалении, как индексы. Но обход с конца всё равно хорошая привычка: код читается проще и не ломается, если позже кто-то перейдёт на индексы.
Для обработки пачки строк на сервере передавайте не сами идентификаторы, а значения нужных полей. Идентификаторы существуют только в рамках открытой формы.
События таблицы: когда реагировать на выбор и смену строки
Иногда выделение нужно привязать к действию пользователя. В свойствах элемента-таблицы доступны события:
| Событие | Когда срабатывает | Для чего |
|---|---|---|
ПриАктивизацииСтроки | Курсор перешёл на другую строку | Показать подробности текущей позиции |
Выбор | Двойной щелчок или Enter по строке | Открыть карточку, выполнить действие |
ПередНачаломИзменения | Перед правкой строки | Запретить редактирование |
ПриНачалеРедактирования | Строка перешла в режим правки | Заполнить значения по умолчанию |
ПриОкончанииРедактирования | Строка записана | Пересчитать итоги |
Важная деталь про ПриАктивизацииСтроки. Оно срабатывает при каждой смене строки, в том числе при программной установке ТекущаяСтрока. Если внутри события вы снова меняете текущую строку, получите зацикливание. Ставьте защиту флагом в реквизите формы или сравнивайте строку с предыдущей.
Тяжёлые действия в этом событии не делайте. Обращение к серверу на каждый шаг курсора заметно тормозит форму. Для подробностей используйте подключаемый обработчик ожидания: ПодключитьОбработчикОжидания("ОбновитьПодробности", 0.2, Истина). Он срабатывает один раз после паузы, а не при каждом нажатии стрелки.
Подсветка строк с ошибками при проверке данных
Хороший приём для валидации: не показывать пользователю сообщение «в строке 14 ошибка», а ещё и покрасить строку. Нужна служебная колонка, которая хранит признак.
- Добавьте в табличную часть реквизит
ЕстьОшибкас типом «Булево». Если таблица не хранится в базе, это реквизит формы-таблицы значений. - Создайте условное оформление:
ТоварыЕстьОшибкаравноИстина— цвет фона светло-красный. - В проверке заполняйте признак и выводите сообщение с привязкой к строке.
&НаСервере
Процедура ПроверитьСтроки(Отказ)
Для Каждого Строка Из Объект.Товары Цикл
Строка.ЕстьОшибка = (Строка.Количество <= 0);
Если Строка.ЕстьОшибка Тогда
Индекс = Объект.Товары.Индекс(Строка);
ТекстОшибки = "Укажите количество больше нуля";
Сообщить(ТекстОшибки + " (строка " + (Индекс + 1) + ")");
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Лучше выводить сообщение через объект СообщениеПользователю с полем Поле = "Объект.Товары[" + Индекс + "].Количество". Тогда клиент сам поставит курсор на проблемную ячейку, и отдельно выделять её не придётся. Это встроенное поведение, и оно надёжнее ручной установки ТекущаяСтрока.
Служебная колонка не должна попадать в базу. Если реквизит добавлен в табличную часть документа, он будет записан. Для чисто визуального признака держите отдельную таблицу значений на форме или очищайте поле в ПередЗаписью.
Обычные формы: ОформлениеСтроки и ТабличноеПоле
В старых конфигурациях и обработках ещё встречаются обычные формы. Там устройство иное: табличная часть показывается элементом «Табличное поле», а покраска идёт событием ПриВыводеСтроки.
Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Если ДанныеСтроки.Количество = 0 Тогда
ОформлениеСтроки.ЦветФона = Новый Цвет(255, 245, 190);
КонецЕсли;
КонецПроцедуры
Курсор в обычной форме ставят иначе: ЭлементыФормы.Товары.ТекущаяСтрока = СтрокаТЧ;, причём присваивается сама строка, а не идентификатор. Если вы переносите код между типами форм, это первое, что ломается.
Типичные проблемы с выделением и как их исправить
Несколько ситуаций, которые встречаются чаще всего.
- 🟥 Правило есть, цвета нет. Проверьте имя поля оформления:
ТоварыКоличество, а неКоличествои неОбъект.Товары.Количество. В поле оформления идёт имя элемента формы. - 🟥 Цвет пропал после перезаполнения. Если вы очистили
УсловноеОформление.Элементыи не добавили правила заново, форма вернётся к виду по умолчанию. - 🟥
ТекущиеДанныеравноНеопределено. Таблица пуста или курсор не стоит на строке. Проверяйте перед обращением. - 🟥 Курсор прыгает на первую строку. После обновления формы с сервера текущая строка может сброситься. Запомните идентификатор перед вызовом и верните его после.
- 🟥 Выделение не видно на цветном фоне. Подберите светлую заливку: тёмная сливается с системной подсветкой выбранной строки.
- 🟥 На сервере нет
Элементы.Товары.ТекущаяСтрока. Свойства элементов управления доступны только на клиенте. Серверный код получает данные параметрами.
Отдельное правило про цвета. Берите спокойные оттенки и не больше двух-трёх значений на форму: красный для ошибки, жёлтый для предупреждения, серый для неактуальных строк. Пользователь запоминает смысл, а радуга из шести оттенков только мешает.
УсловноеОформление.Элементы.Добавить().Элементы.Таблица.ТекущаяСтрока = Строка.ПолучитьИдентификатор() в клиентской процедуре.ТекущиеДанные для одной строки, ВыделенныеСтроки для нескольких.Объект.Таблица[Индекс].Колонка: курсор встанет на ячейку сам.ПриВыводеСтроки и ОформлениеСтроки.ЦветФона.