При работе с отчетами и печатными формами в 1С часто возникает необходимость найти определенные данные в уже сформированном табличном документе и как-то их выделить, например, изменить цвет фона ячейки. Давайте разберем по шагам, как правильно реализовать этот функционал, выясним причину распространенных ошибок и проанализируем различные подходы к оформлению.
Прежде чем мы рассмотрим поиск по готовому документу, обратим внимание на самый правильный с точки зрения архитектуры подход. Гораздо проще и эффективнее проверять данные и раскрашивать ячейки непосредственно при формировании табличного документа. Выводите строчки, проверяете нужный параметр прямо в цикле формирования и сразу задаете оформление области макета. Это избавляет от необходимости искать данные постфактум.
Если табличный документ уже сформирован, или мы работаем с внешним файлом (например, загруженным из Excel), для получения координат ячейки с определенным значением мы будем использовать платформенный метод НайтиТекст(). Посмотрим на простой пример поиска первого вхождения:
ИскомаяОбласть = ТабДокумент.НайтиТекст("Искомое значение", , , Истина, Ложь, Истина, Ложь);
Если ИскомаяОбласть <> Неопределено Тогда
ИскомаяОбласть.ЦветФона = WebЦвета.Синий;
КонецЕсли;
Однако данный метод в таком виде найдет лишь первое совпадение в документе. Разберем ситуацию, когда ячеек с таким текстом может быть несколько. В этом случае метод нужно вызывать в цикле. Для этого в НайтиТекст передается параметр начала поиска, куда мы будем подставлять ранее найденную область. Также крайне полезно использовать параметр поиска ячейки целиком, чтобы избежать ложных срабатываний.
НайденнаяОбласть = Неопределено;
Пока Истина Цикл
// Ищем следующее совпадение, начиная с предыдущей найденной области
НайденнаяОбласть = ТабДок.НайтиТекст("Искомый текст", НайденнаяОбласть,,,, Истина);
Если НайденнаяОбласть = Неопределено Тогда
Прервать; // Больше совпадений не найдено, выходим из цикла
КонецЕсли;
// Оформляем найденную ячейку
НайденнаяОбласть.ЦветФона = WebЦвета.Синий;
КонецЦикла;
Иногда нам нужно не просто раскрасить ячейку, но и получить ее точные координаты для дальнейших алгоритмов. Когда область найдена, мы можем извлечь номера ее строк и колонок через свойства Верх, Низ, Лево и Право.
КоординатыВерх = ИскомаяОбласть.Верх;
КоординатыЛево = ИскомаяОбласть.Лево;
Координаты = "R" + КоординатыВерх + "C" + КоординатыЛево;
Сформированная строка Координаты является валидным адресом ячейки в формате R1C1. Это очень удобно, так как строку можно напрямую передать обратно в табличный документ для получения области:
ТекущаяЯчейка = ТабДок.Область(Координаты); // Например: ТабДок.Область("R2C4")
Проанализируем способы задания цвета фона. В примерах выше мы использовали коллекцию WebЦвета. Но платформа 1С предоставляет и другие мощные инструменты для работы с палитрой. Рассмотрим подробнее доступные варианты:
WebЦвета.Красный или WebЦвета.СветлоЗеленый.Новый Цвет(255, 245, 207).ЦветаСтиля.ЦветФонаКнопки.Помимо сплошной заливки свойства ЦветФона, мы можем использовать узоры. Для этого применяются свойства Узор и ЦветУзора. Можно выбрать диагональную штриховку, рябь и другие системные перечисления.
Разберем типичный антипаттерн, который часто встречается у начинающих разработчиков. Это попытка найти текст путем поячеечного перебора всей таблицы с помощью двойного цикла:
// ВНИМАНИЕ: ЭТО НЕОПТИМАЛЬНЫЙ КОД!
Для Стр = 1 По Макет.ВысотаТаблицы Цикл
Для НомерСтолбца = 1 По Макет.ШиринаТаблицы Цикл
Яч = Макет.Область(Стр, НомерСтолбца);
Если Яч.Текст = "Искомое значение" Тогда
Яч.ЦветФона = WebЦвета.Красный;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Почему мы настоятельно рекомендуем избегать такого подхода? Обращение к свойству Область(Стр, Кол) на каждой итерации для больших таблиц работает крайне медленно. В документах на несколько тысяч строк выполнение такого кода может занимать минуты или даже подвесить программу. Использование платформенного метода НайтиТекст(), который реализован на уровне ядра платформы (C++), отрабатывает в десятки и сотни раз быстрее.
Резюмируя: всегда старайтесь оформлять ячейки на этапе генерации печатной формы. Если же необходимо обработать готовый табличный документ, используйте метод НайтиТекст() в цикле Пока Истина для быстрого и корректного нахождения всех нужных данных.