При работе с управляемыми формами 1С начинающие разработчики часто сталкиваются с проблемой: при попытке изменить цвет ячейки через свойства элемента формы (например, в обработчике ПриИзменении), окрашивается вся колонка целиком. Это происходит потому, что в управляемом приложении элементы формы (поля ввода в таблице) являются лишь «шаблонами» для отображения данных, а не отдельными объектами для каждой строки. Чтобы выделить конкретную ячейку по условию, необходимо использовать механизм Условного оформления.
В рамках этой статьи мы разберем, как правильно реализовать программное оформление ячеек, особенно в ситуациях, когда разработка ведется в расширении и мы ограничены в изменении структуры основной конфигурации.
Проанализируем типичную ошибку. Когда мы пишем Элемент.ЦветТекста = WEBЦвета.Красный; в коде на стороне клиента, мы обращаемся к объекту типа ПолеФормы. Этот объект отвечает за визуальное представление всей колонки. Управляемая форма рисует строки динамически, используя настройки этого объекта для каждой строки. Поэтому, изменив цвет один раз, вы меняете его для всех строк сразу.
Для решения задачи нам нужно передать платформе инструкции: «Рисуй ячейку красным, только если данные в этой конкретной строке соответствуют условию». Эти инструкции хранятся в коллекции УсловноеОформление формы.
Если условие раскраски простое (например, значение в той же строке больше константы), мы можем настроить оформление при создании формы на сервере. Рассмотрим этот процесс по шагам.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создаем новый элемент условного оформления
ЭлементУО = УсловноеОформление.Элементы.Добавить();
// 1. Настраиваем оформление: что именно мы меняем?
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветФона", WebЦвета.Лосось);
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина); // Можно менять и другие свойства
// 2. Настраиваем условие (отбор): когда применять оформление?
ЭлементОтбора = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.Количество");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше;
ЭлементОтбора.ПравоеЗначение = 50;
ЭлементОтбора.Использование = Истина;
// 3. Указываем оформляемые поля: какие ячейки красить?
ПолеОформления = ЭлементУО.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыКоличество");
ПолеОформления.Использование = Истина;
КонецПроцедуры
В данном примере мы жестко задали число 50. Но что делать, если лимит для каждой номенклатуры свой и хранится в базе данных?
Проанализируем сложную ситуацию: условие зависит от данных регистра, а мы работаем в расширении. Автор темы справедливо заметил, что добавлять новые реквизиты в табличную часть объекта в расширении не всегда удобно или возможно из-за режима совместимости. Однако мы можем добавить Реквизит формы.
Выясним причину, почему это лучше: реквизит формы существует только «в памяти» открытого окна и не требует изменения структуры таблиц в базе данных. Выполним следующие действия:
Товары (например, реквизит ПревышенЛимит с типом Булево).Товары.ПревышенЛимит Равно Истина.Рассмотрим пример кода для обработки изменения значения:
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
// Вызываем сервер, чтобы проверить данные по регистру
ТекущаяСтрока.ПревышенЛимит = ПроверитьПревышениеНаСервере(ТекущаяСтрока.Номенклатура, ТекущаяСтрока.Количество);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьПревышениеНаСервере(Номенклатура, Количество)
// Здесь выполняем запрос к регистру сведений
МаксЛимит = РегистрыСведений.ЛимитыПродаж.ПолучитьМаксимум(Номенклатура);
Возврат Количество > МаксЛимит;
КонецФункции
Если вам нужно «подсветить» строку программно в произвольный момент (например, после нажатия кнопки проверки), можно использовать ИдентификаторСтроки. Посмотрим на пример ситуации, когда мы хотим покрасить конкретную строку, зная её индекс.
Важно помнить: номер строки (1, 2, 3...) может измениться при сортировке, поэтому лучше использовать свойство КлючСвязи или внутренний идентификатор.
&НаСервере
Процедура ВыделитьСтрокуЦветом(ИдентификаторСтроки)
// Удаляем старое оформление с таким же заголовком, чтобы не дублировать
Для Каждого Элемент Из УсловноеОформление.Элементы Цикл
Если Элемент.Представление = "ДинамическаяПодсветка" Тогда
УсловноеОформление.Элементы.Удалить(Элемент);
КонецЕсли;
КонецЦикла;
ЭлементУО = УсловноеОформление.Элементы.Добавить();
ЭлементУО.Представление = "ДинамическаяПодсветка";
// Условие по идентификатору конкретной строки
ЭлементОтбора = ЭлементУО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.ИдентификаторСтроки");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ИдентификаторСтроки;
ЭлементУО.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Красный);
ПолеОформления = ЭлементУО.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТоварыКоличество");
КонецПроцедуры
Разберем важный нюанс: если табличная часть документа содержит сотни строк, вызов сервера ПриИзменении для каждой ячейки может замедлить работу пользователя. Проанализируем, как этого избежать:
ПриЧтенииНаСервере) рассчитайте лимиты сразу для всех строк одним запросом и заполните служебные колонки (флаги).Соответствие).&НаСервереБезКонтекста, чтобы не гонять данные всей формы между клиентом и сервером.Таким образом, мы выяснили, что для оформления ячеек в 1С 8.3 следует всегда использовать Условное оформление, а передавать в него условия лучше всего через скрытые технические реквизиты формы, что особенно актуально при разработке в расширениях.