При разработке в интерфейсе «Обычных форм» программисты часто сталкиваются с задачей визуального выделения строк в табличных частях документов. Например, нужно подсветить товары, участвующие в акции, или позиции с нулевым остатком. Однако стандартные методы реализации часто приводят к заметным задержкам интерфейса («фризам»), что вызывает недовольство пользователей. Рассмотрим, как решить эту задачу эффективно и профессионально.
Событие ПриПолученииДанных (OnGetData) является основным инструментом для оформления строк в обычных формах. Оно срабатывает каждый раз, когда данные отрисовываются на экране: при открытии формы, прокрутке колесиком мыши или перемещении курсора. Главная ошибка, которую совершают начинающие разработчики — выполнение запроса к базе данных внутри этого события для каждой строки в цикле. Поскольку процедура вызывается очень часто, даже «быстрый» запрос на 0.1 секунды превращает работу пользователя в мучение.
Проанализируем ситуацию: если на экране отображается 20 строк, и для каждой выполняется отдельный запрос, общее время ожидания составит 2 секунды при каждом движении мыши. Наша задача — свести количество обращений к серверу к минимуму.
Это наиболее стабильный вариант, если объем данных в табличной части предсказуем. Суть метода заключается в том, чтобы один раз при открытии документа собрать всю необходимую информацию для раскраски во временную таблицу или структуру (например, Соответствие или индексированную ТаблицаЗначений).
Рассмотрим по шагам реализацию этого метода:
ПриОткрытии заполним эту переменную данными.ПриПолученииДанных будем просто обращаться к этой переменной.Пример кода для модуля формы:
Перем мАкционныеТовары; // Переменная модуля для кеширования
Процедура ПриОткрытии()
// Создаем таблицу с индексами для быстрого поиска
мАкционныеТовары = Новый ТаблицаЗначений;
мАкционныеТовары.Колонки.Добавить("Номенклатура");
мАкционныеТовары.Индексы.Добавить("Номенклатура");
// Запрос, который определяет все активные акции для товаров в ТЧ
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТЧ.Номенклатура
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &Ссылка
| И ТЧ.Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ РегистрСведений.Акции.СрезПоследних)";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
мАкционныеТовары = Запрос.Выполнить().Выгрузить();
КонецПроцедуры
Процедура ТоварыПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
// Ищем товар в нашей подготовленной таблице
Если мАкционныеТовары.Найти(ОформлениеСтроки.ДанныеСтроки.Номенклатура, "Номенклатура") <> Неопределено Тогда
ОформлениеСтроки.ЦветФона = Новый Цвет(255, 230, 230); // Светло-красный
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если товаров в документе слишком много или акции могут меняться динамически, лучше использовать пакетный запрос непосредственно в событии ПриПолученииДанных. Секрет успеха здесь — использование параметра ОформленияСтрок, который содержит только те строки, которые видимы в данный момент на экране (обычно их не более 30-40).
Разберем алгоритм правильной работы:
Соответствие для моментального доступа.Посмотрим на пример кода:
Процедура ТоварыПриПолученииДанных(Элемент, ОформленияСтрок)
// 1. Собираем список номенклатуры из видимых строк
СписокТоваров = Новый Массив;
Для Каждого Оформление Из ОформленияСтрок Цикл
СписокТоваров.Добавить(Оформление.ДанныеСтроки.Номенклатура);
КонецЦикла;
// 2. Выполняем ОДИН запрос для всего списка видимых товаров
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| АкционныеТовары.Номенклатура
|ИЗ
| РегистрСведений.Акции.СрезПоследних(&Период, Номенклатура В (&Список)) КАК АкционныеТовары";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("Список", СписокТоваров);
Результат = Запрос.Выполнить().Выгрузить();
// 3. Создаем соответствие для быстрого поиска в цикле оформления
Акционные = Новый Соответствие;
Для Каждого Стр Из Результат Цикл
Акционные.Вставить(Стр.Номенклатура, Истина);
КонецЦикла;
// 4. Раскрашиваем строки
Для Каждого Оформление Из ОформленияСтрок Цикл
Если Акционные[Оформление.ДанныеСтроки.Номенклатура] <> Неопределено Тогда
Оформление.ЦветТекста = ЦветаСтиля.ЦветОтрицательногоПоказателя;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Иногда разработчики пытаются добавить в табличную часть (ТЧ) специальный реквизит ЕстьАкция (тип Булево), чтобы не делать запросы при каждом движении мыши. Однако программное заполнение этого реквизита при открытии формы приводит к тому, что 1С считает документ измененным. В результате при попытке закрыть форму без правок система выдает вопрос: «Сохранить изменения?», что раздражает пользователей.
Проанализируем, как обойти эту проблему. Для этого используется свойство формы Модифицированность. Если мы программно меняем данные для целей оформления, мы должны «обнулить» признак изменений.
Разберем по шагам:
ПриОткрытии (или ПередОткрытием) запускаем цикл по ТЧ и заполняем служебный признак.ЭтаФорма.Модифицированность = Ложь;.ПриВыводеСтроки или ПриПолученииДанных) просто проверяем значение этого реквизита.Важное замечание: Метод со скрытым реквизитом стоит использовать осторожно. Если пользователь действительно начнет редактировать документ, признак Модифицированность станет Истина естественным путем. Однако если вы сбросите его в неподходящий момент, пользователь может случайно закрыть документ, потеряв свои правки.
В обычных формах есть еще одно событие — ПриВыводеСтроки. Оно кажется проще, так как работает с одной конкретной строкой. Но именно в этом его слабость. В нем невозможно реализовать «пакетный» запрос (как в Решении 2). Если вы начнете делать запросы в ПриВыводеСтроки, интерфейс неизбежно будет «лагать». Поэтому для любых задач, требующих обращения к базе данных или сложным вычислениям для оформления, следует использовать исключительно ПриПолученииДанных с обработкой коллекции строк целиком.
Для создания отзывчивого интерфейса придерживайтесь следующих правил:
Новый Запрос внутри цикла по строкам табличного поля.Соответствие для быстрого поиска данных (оно работает быстрее, чем поиск в ТаблицаЗначений).ЦветФона, ЦветТекста или Шрифт объекта ОформлениеСтроки.Применяя эти методы, вы добьетесь мгновенной работы интерфейса даже в тяжелых документах с сотнями строк номенклатуры.