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