При разработке интерфейсов в 1С часто возникает задача визуального выделения важных данных. Например, требуется выделить строку или конкретную ячейку красным цветом, если в текстовом представлении статуса содержится слово "Отказ" или строка начинается с определенного символа. На первый взгляд задача кажется простой, но при ее реализации разработчики часто сталкиваются с техническими нюансами: регистрозависимостью поиска, лишними пробелами, а также ограничениями платформы и режимов совместимости.
В этой статье мы подробно разберем, как правильно реализовать раскраску ячеек по текстовому условию в обычных и управляемых формах 1С, как избежать падения производительности интерфейса и что делать, если платформа выдает ошибку о неопределенной функции СтрНайти.
Если при попытке выполнить поиск подстроки код возвращает ошибку компиляции, указывающую на неопределенность функции СтрНайти, это свидетельствует об ограничениях используемой платформы или режима совместимости конфигурации.
Функция СтрНайти была добавлена в платформу 1С:Предприятие начиная с версии 8.3.6. Если ваша информационная база запущена на более ранней версии платформы или в свойствах конфигурации установлен режим совместимости с версиями 8.3.5, 8.2 или 8.1, данная функция будет недоступна.
Для решения этой проблемы необходимо использовать классическую функцию Найти(), которая поддерживается абсолютно всеми версиями платформы 1С.
В обычных формах для динамического изменения оформления строк и ячеек используется событие табличного поля ПриВыводеСтроки. В обработчик этого события передаются параметры ОформлениеСтроки и ДанныеСтроки.
Рассмотрим базовый пример кода, который решает задачу автора темы: если в колонке СостояниеСчета содержится текст "Отказ" или строка начинается с буквы "О", ячейка окрашивается в красный цвет, а шрифт становится полужирным.
Процедура ТабличноеПолеПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
// Проверяем, что в строке есть данные и тип реквизита является строкой
Если ДанныеСтроки <> Неопределено И ТипЗнч(ДанныеСтроки.СостояниеСчета) = Тип("Строка") Тогда
// Защищаем код от случайных пробелов и приводим к верхнему регистру для регистронезависимости
СтрокаПроверки = ВРег(СокрЛП(ДанныеСтроки.СостояниеСчета));
// Проверяем условия: наличие слова "ОТКАЗ" или первый символ "О"
Если (Найти(СтрокаПроверки, "ОТКАЗ") > 0) Или (Лев(СтрокаПроверки, 1) = "О") Тогда
// Настройка оформления конкретной ячейки
ОформлениеСтроки.Ячейки.СостояниеСчета1.Шрифт = Новый Шрифт(,, Истина);
ОформлениеСтроки.Ячейки.СостояниеСчета1.ЦветФона = WebЦвета.Красный;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Разберем важные детали этого кода:
Найти() чувствительна к регистру символов. Если пользователь введет "отказ" или "ОТКАЗ", обычный поиск слова "Отказ" вернет 0 (ложь). Использование функции ВРег() приводит анализируемую строку к верхнему регистру, что делает проверку надежной.СокрЛП() мы удаляем пробелы в начале и конце строки. Это гарантирует, что проверка первого символа через функцию Лев(СтрокаПроверки, 1) = "О" сработает корректно, даже если пользователь случайно ввел пробел перед словом.ДанныеСтроки может принимать значение Неопределено. Проверка этого условия предотвращает аварийное завершение работы программы.Использование события ПриВыводеСтроки для сложных проверок может существенно замедлить отрисовку списков, особенно при быстрой прокрутке. Это происходит потому, что событие вызывается для каждой строки отдельно (построчно).
Для оптимизации интерфейса в обычных формах рекомендуется использовать событие ПриПолученииДанных. Оно позволяет обрабатывать оформление пакетом — сразу для всех видимых на экране строк. Посмотрим на пример реализации:
Процедура ТабличноеПолеПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
Если ДанныеСтроки <> Неопределено И ТипЗнч(ДанныеСтроки.СостояниеСчета) = Тип("Строка") Тогда
СтрокаПроверки = ВРег(СокрЛП(ДанныеСтроки.СостояниеСчета));
Если (Найти(СтрокаПроверки, "ОТКАЗ") > 0) Или (Лев(СтрокаПроверки, 1) = "О") Тогда
ОформлениеСтроки.Ячейки.СостояниеСчета1.Шрифт = Новый Шрифт(,, Истина);
ОформлениеСтроки.Ячейки.СостояниеСчета1.ЦветФона = WebЦвета.Красный;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важное правило оптимизации: Никогда не обращайтесь к базе данных через точку от реквизитов строки (например, ДанныеСтроки.ДокументСсылка.Автор.Наименование) внутри этих событий. Это приводит к отправке сотен одиночных запросов к СУБД (проблема N+1 запроса). Все необходимые для оформления данные должны быть заранее выведены в скрытые или видимые колонки списка.
Если вы работаете в управляемом интерфейсе (динамические списки, управляемые формы), использовать обработчики визуализации строк в коде крайне не рекомендуется. Платформа 1С v8.3 предоставляет для этого декларативный и гораздо более производительный механизм — Условное оформление.
Настроить его можно как интерактивно в конфигураторе (в свойствах списка), так и программно при создании формы. Программный метод предпочтителен, если условия оформления зависят от логики программы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создаем элемент условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// 1. Настраиваем отбор: СостояниеСчета содержит "Отказ"
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Список.СостояниеСчета");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
ЭлементОтбора.ПравоеЗначение = "Отказ";
ЭлементОтбора.Использование = Истина;
// 2. Настраиваем оформление: устанавливаем красный цвет фона
ЦветФона = ЭлементОформления.Оформление.Элементы.Найти("BackColor");
ЦветФона.Значение = WebЦвета.Красный;
ЦветФона.Использование = Истина;
// 3. Указываем оформляемые поля (колонку, которую нужно покрасить)
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("СостояниеСчета");
ПолеОформления.Использование = Истина;
КонецПроцедуры
Использование условного оформления динамических списков работает на уровне платформы и базы данных. Это исключает лишний код на встроенном языке и гарантирует максимальное быстродействие интерфейса программы.