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