Как в 1С 8.3 выделить цветом строки табличного документа по условию?

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

При формировании печатных форм и отчетов в 1С часто возникает задача визуального выделения определенных строк — например, итоговых позиций, строк определенных категорий или значений, превышающих лимит. Нередко разработчики сталкиваются с ситуацией, когда вместо одной строки закрашивается вся таблица либо возникает ошибка Поле объекта не обнаружено (ЦветФона).

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

Выясним причину: почему закрашивается вся таблица?

Рассмотрим типичный сценарий: до начала цикла разработчик получает область строки из макета с помощью вызова Макет.ПолучитьОбласть("Строка"). В теле цикла заполняются параметры, проверяется условие, и если оно истинно, ячейкам этой области назначается ЦветФона.

Главная ошибка здесь кроется в механике работы с объектом области. В цикле многократно выводится одна и та же область, полученная до входа в итерации. Как только мы один раз изменили свойство ЦветФона у ячеек этой области, это изменение сохраняется в памяти шаблона. Все последующие строки, выводимые через ТабДок.Вывести(ОбластьСтрока), будут выводиться с этим же измененным цветом, так как исходный цвет фона никто не возвращал обратно.

Различие между методами ПолучитьОбласть и Область

При попытке закрасить уже выведенную строку в результирующем документе важно не перепутать два похожих метода объекта ТабличныйДокумент:

  1. ТабличныйДокумент.ПолучитьОбласть() — копирует указанный диапазон и возвращает его как отдельный независимый объект типа ТабличныйДокумент. У него нет свойства ЦветФона ячеек, поэтому попытка написать ТабДок.ПолучитьОбласть(...).ЦветФона вызывает ошибку платформы Поле объекта не обнаружено (ЦветФона).
  2. ТабличныйДокумент.Область() — возвращает объект типа ОбластьЯчеекТабличногоДокумента, представляющий собой прямую ссылку на ячейки внутри сформированного документа. Именно этот объект позволяет напрямую менять ЦветФона, ЦветТекста, Шрифт и рамки ячеек.

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

Способ 1. Создание двух отдельных областей в макете (рекомендуемый)

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

Посмотрим на пример реализации кода:


ОбластьОбычная = Макет.ПолучитьОбласть("СтрокаОбычная");
ОбластьВыделенная = Макет.ПолучитьОбласть("СтрокаВыделенная");

Для Каждого Стр Из Затраты Цикл
    Отбор = Новый Структура("Наименование", Стр.Статья);
    НайденныеСтроки = ТаблицаГрупп.НайтиСтроки(Отбор);
    
    // Выбираем шаблон области в зависимости от условия
    Если НайденныеСтроки.Количество() > 0 Тогда
        ОбластьВывода = ОбластьВыделенная;
    Иначе
        ОбластьВывода = ОбластьОбычная;
    КонецЕсли;
    
    ОбластьВывода.Параметры.Затрата = Стр.Статья;
    ОбластьВывода.Параметры.СуммаЗатраты = Стр.Сумма;
    
    ТабДок.Вывести(ОбластьВывода);
КонецЦикла;

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

Способ 2. Закрашивание ячеек в сформированном документе по ВысотаТаблицы

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

Разберем по шагам данный подход:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

Для Каждого Стр Из Затраты Цикл
    ОбластьСтрока.Параметры.Затрата = Стр.Статья;
    ОбластьСтрока.Параметры.СуммаЗатраты = Стр.Сумма;
    
    // Сначала выводим стандартную строку
    ТабДок.Вывести(ОбластьСтрока);
    
    Отбор = Новый Структура("Наименование", Стр.Статья);
    НайденныеСтроки = ТаблицаГрупп.НайтиСтроки(Отбор);
    
    // Проверяем условие и перекрашиваем выведенные ячейки
    Если НайденныеСтроки.Количество() > 0 Тогда
        НомерСтроки = ТабДок.ВысотаТаблицы;
        // Обращаемся к диапазону с 1 по 2 колонку только что выведенной строки
        ТабДок.Область(НомерСтроки, 1, НомерСтроки, 2).ЦветФона = WebЦвета.СеребристоСерый;
    КонецЕсли;
КонецЦикла;

Обратите внимание: здесь используется именно метод ТабДок.Область(НомерСтроки, 1, НомерСтроки, 2), что позволяет точно ограничить диапазон колонок и избежать окрашивания всей ширины листа.

Способ 3. Сброс цвета ячеек в исходном шаблоне области

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

Проанализируем пример кода со сбросом цвета:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

Для Каждого Стр Из Затраты Цикл
    ОбластьСтрока.Параметры.Затрата = Стр.Статья;
    ОбластьСтрока.Параметры.СуммаЗатраты = Стр.Сумма;
    
    Отбор = Новый Структура("Наименование", Стр.Статья);
    НайденныеСтроки = ТаблицаГрупп.НайтиСтроки(Отбор);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        ОбластьСтрока.Область(1, 1, 1, 2).ЦветФона = WebЦвета.СеребристоСерый;
    Иначе
        // Обязательно возвращаем стандартный цвет, если условие не выполнено
        ОбластьСтрока.Область(1, 1, 1, 2).ЦветФона = WebЦвета.Авто;
    КонецЕсли;
    
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

Рекомендации по оптимизации производительности

  1. Не вызывайте Макет.ПолучитьОбласть() внутри цикла: получение области из макета на каждой итерации циклически нагружает процессор и сильно замедляет формирование отчетов при тысячах строк. Получайте шаблоны областей один раз до начала цикла.
  2. Оптимизируйте поиск условий: метод Таблица.НайтиСтроки() внутри цикла обхода большой таблицы создает квадратичную нагрузку. Если таблица условий содержит много записей, перенесите фильтрацию в текст запроса либо используйте объект Соответствие для мгновенного поиска по ключу.
← На главную