Как изменить цвет фона строки или ячейки номенклатуры в документе «Реализация товаров и услуг»?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Разбор исходной проблемы: почему сравнение не работает?

Рассмотрим ситуацию, с которой часто сталкиваются начинающие программисты 1С при работе в Обычных формах. Задача состоит в том, чтобы покрасить строку таблицы, если в колонке номенклатуры выбран определенный товар (например, товар с названием "Товар").

Типичный ошибочный код в обработчике события выглядит следующим образом:


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Если ДанныеСтроки.Номенклатура = "Товар" Тогда
        ОформлениеСтроки.Цветфона = WebЦвета.Красный;
    КонецЕсли;
КонецПроцедуры

Выясним причину, почему этот код не работает и строка не меняет свой цвет. Дело в том, что реквизит ДанныеСтроки.Номенклатура имеет тип данных СправочникСсылка.Номенклатура. Это уникальный идентификатор записи в базе данных, ссылка на объект. В то же время значение "Товар" (в кавычках) — это обычная строка (тип Строка). Платформа 1С не может напрямую сравнить ссылку на элемент справочника со строковым литералом, поэтому условие всегда возвращает значение Ложь, и код внутри условия никогда не выполняется.

Решение проблемы через обращение к свойствам объекта

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


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Если ДанныеСтроки.Номенклатура.Наименование = "Товар" Тогда
        ОформлениеСтроки.ЦветФона = WebЦвета.Красный; // Красим всю строку
    КонецЕсли;
КонецПроцедуры

Если требуется покрасить не всю строку целиком, а только конкретную ячейку в колонке номенклатуры, мы можем обратиться к коллекции ячеек оформления строки:


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    Если ДанныеСтроки.Номенклатура.Наименование = "Товар" Тогда
        ОформлениеСтроки.Ячейки.Номенклатура.ЦветФона = WebЦвета.Красный; // Красим только ячейку
    КонецЕсли;
КонецПроцедуры

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

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

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

Когда мы пишем конструкцию ДанныеСтроки.Номенклатура.Наименование, происходит так называемое разыменование ссылки. Платформа 1С вынуждена отправить отдельный, неявный запрос к базе данных СУБД, чтобы получить наименование для данной конкретной ссылки номенклатуры. Если на экране отображается 30 строк, система выполнит 30 отдельных микро-запросов к базе данных. При быстрой прокрутке списка количество запросов начнет исчисляться сотнями и тысячами. Это приведет к заметным задержкам (интерфейс начнет "лагать" и "зависать"), а также создаст избыточную нагрузку на сервер СУБД.

Рассмотрим два профессиональных и оптимизированных способа решения этой задачи для Обычных форм.

Оптимизированное решение №1: Использование готового текста ячейки

Если колонка "Номенклатура" уже отображается на экране в табличном поле, это значит, что платформа 1С уже самостоятельно запросила из базы данных текстовое представление этой номенклатуры и вывела его на экран. Мы можем перехватить это готовое текстовое значение прямо из оформления ячейки, не делая повторных запросов к базе данных:


Процедура ТоварыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    // Получаем текст, который платформа уже подготовила для вывода на экран
    ТекстНоменклатуры = ОформлениеСтроки.Ячейки.Номенклатура.Текст;
    
    Если ТекстНоменклатуры = "Товар" Тогда
        ОформлениеСтроки.ЦветФона = WebЦвета.Красный;
    КонецЕсли;
КонецПроцедуры

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

Оптимизированное решение №2: Использование события ПриПолученииДанных

Что делать, если нам нужно красить строки по более сложному условию? Например, если нам нужно проверить реквизит номенклатуры, который вообще не выведен на экран (например, проверить вид номенклатуры или какую-то определенную группу товаров). В этом случае использовать событие ПриВыводеСтроки категорически противопоказано.

Для таких задач в 1С предусмотрено событие ПриПолученииДанных. Оно срабатывает один раз для всей пачки (порции) строк, подготовленных к выводу на экран. Это позволяет нам собрать все ссылки на номенклатуру из этих строк и получить их свойства одним-единственным запросом к базе данных.

Рассмотрим пример реализации этого алгоритма:


Процедура ТоварыПриПолученииДанных(Элемент, ОформленияСтрок)
    
    // Шаг 1. Собираем все уникальные ссылки номенклатуры из оформляемых строк
    МассивНоменклатуры = Новый Массив;
    СоответствиеСтрок = Новый Соответствие;
    
    Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
        ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
        Если ДанныеСтроки <> Неопределено Тогда
            МассивНоменклатуры.Добавить(ДанныеСтроки.Номенклатура);
            // Запоминаем связь ссылки и оформления строки
            СоответствиеСтрок.Вставить(ДанныеСтроки.Номенклатура, ОформлениеСтроки);
        КонецЕсли;
    КонецЦикла;
    
    Если МассивНоменклатуры.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Шаг 2. Делаем один пакетный запрос к СУБД для получения нужных реквизитов
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Номенклатура.Ссылка КАК Ссылка,
        |	Номенклатура.Наименование КАК Наименование
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Ссылка В (&МассивНоменклатуры)";
    
    Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        // Шаг 3. Бежим по результатам запроса и раскрашиваем строки
        Пока Выборка.Следующий() Цикл
            Если Выборка.Наименование = "Товар" Тогда
                ОформлениеСтроки = СоответствиеСтрок.Получить(Выборка.Ссылка);
                Если ОформлениеСтроки <> Неопределено Тогда
                    ОформлениеСтроки.ЦветФона = WebЦвета.Красный;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

Этот подход является эталонным стандартом разработки под Обычные формы 1С, обеспечивающим максимальное быстродействие системы даже на очень слабых компьютерах и медленных каналах связи.

Современный подход: Управляемые формы (1С 8.3)

Если вы работаете в современных конфигурациях 1С на управляемом интерфейсе (например, «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация 2»), то концепция работы с цветом там кардинально изменилась. Событий ПриВыводеСтроки и ПриПолученииДанных в управляемом приложении больше нет, так как передача оформления по каждой строке между сервером и тонким клиентом слишком сильно нагружала бы сеть.

Вместо этого используется механизм Условного оформления. Платформа 1С 8.3 сама оптимизирует процесс покраски на уровне ядра. Настроить его можно двумя способами.

Способ А. Настройка условного оформления без программирования (в конфигураторе)

Вы можете настроить визуальное отображение строк за пару кликов мыши без написания кода:

  1. Откройте форму документа «Реализация товаров и услуг» в конфигураторе.
  2. В окне свойств формы перейдите на вкладку «Условное оформление» и нажмите кнопку «Открыть».
  3. Добавьте новый элемент оформления:
    • В колонке «Оформление» укажите желаемый цвет (например, «Цвет фона» -> красный).
    • В колонке «Условие» добавьте новый элемент отбора: левое значение — Объект.Товары.Номенклатура.Наименование, вид сравнения — «Равно», правое значение — «Товар».
    • В колонке «Оформляемые поля» выберите поле табличной части (например, ТоварыНоменклатура), если нужно покрасить только одну колонку, либо оставьте это поле пустым, если хотите покрасить всю строку целиком.

Способ Б. Программная настройка условного оформления

Иногда условия раскраски динамически меняются в зависимости от настроек пользователя. В таких случаях условное оформление формы настраивают программно при создании формы на сервере:


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

Использование условного оформления в Управляемых формах гарантирует высокую скорость работы веб-клиента и тонкого клиента 1С, полностью избавляя разработчика от ручного контроля за получением данных с сервера базы данных.

← На главную