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