Работа с динамическими списками в 1С:Предприятии 8.3 часто вызывает вопросы, когда дело доходит до аналитических отчетов и агрегированных данных. Основная проблема заключается в самой идеологии динамического списка: он предназначен для быстрого, порционного отображения данных. Платформа считывает только те записи, которые видны пользователю на экране (и еще небольшой «запас»), поэтому расчет честных итогов по всей выборке внутри группировок стандартными средствами СКД в динамическом списке недоступен.
Тем не менее, задачи бизнеса часто требуют видеть количество документов в группе или сумму по складу прямо в списке. Разберем подробно, какие существуют способы решения этой задачи — от классических «костылей» до современных возможностей платформы. Для расширения возможностей и добавления новых полей в списки можно использовать методику доработки динамических списков четырьмя способами.
Проанализируем ситуацию с технической стороны. Когда мы открываем динамический список, система выполняет запрос с конструкцией ВЫБРАТЬ ПЕРВЫЕ... (или SELECT TOP... на уровне СУБД). Чтобы посчитать итог по группе, например, «Количество вакансий в статусе Работает», системе пришлось бы просканировать все записи этой группы, что противоречит принципу «динамичности». Если в группе 100 000 записей, расчет итога приведет к серьезным задержкам при прокрутке списка.
Это самый современный и эффективный метод. В новых версиях платформы 8.3.20+ в языке запросов появились оконные функции. Они позволяют вычислить агрегатное значение (сумму, количество, среднее) по определенному набору строк, не сворачивая саму выборку. Мы можем добавить результат этого расчета в каждую строку динамического списка.
Рассмотрим пример запроса для динамического списка, где нам нужно вывести общую сумму по складу в каждой строке документа:
ВЫБРАТЬ
ДокументПродажа.Ссылка КАК Ссылка,
ДокументПродажа.Склад КАК Склад,
ДокументПродажа.СуммаДокумента КАК СуммаДокумента,
СУММА(ДокументПродажа.СуммаДокумента) ОБЩЕЕ (ПАРТИЦИЯ ПО ДокументПродажа.Склад) КАК ИтогПоСкладу
ИЗ
Документ.Продажа КАК ДокументПродажа
В этом случае поле ИтогПоСкладу будет содержать общую сумму всех документов по данному складу. Хотя это не отдельная строка группировки, пользователь увидит сумму группы в каждой строке, что решает задачу информирования.
Если объем данных позволяет (например, несколько тысяч строк), наиболее правильным решением с точки зрения интерфейса будет использование ДереваЗначений. В отличие от динамического списка, дерево полностью загружается в память клиента и позволяет использовать все возможности агрегации.
Выполним следующие шаги для реализации:
ДеревоЗначений.ИТОГИ ПО.Пример программного заполнения дерева:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Вакансии.Статус КАК Статус,
| Вакансии.Ссылка КАК Вакансия,
| 1 КАК Количество
|ИЗ
| Справочник.Вакансии КАК Вакансии
|ИТОГИ
| СУММА(Количество)
|ПО
| Статус";
РезультатЗапроса = Запрос.Выполнить();
ДеревоОбъект = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоВакансий");
Преимущество: Полный контроль над итогами и внешним видом. Недостаток: При очень больших объемах данных форма будет открываться медленно.
В высоконагруженных системах расчет итогов «на лету» недопустим. Рассмотрим методику, при которой итоги хранятся заранее. Создадим Регистр сведений, в котором в разрезе нужных нам группировок (например, Статус Вакансии) будет храниться актуальное количество записей.
Проанализируем алгоритм:
ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы с этим регистром по полю группировки.Это обеспечит мгновенную работу списка, так как итог уже посчитан и просто отображается как обычное поле.
Существует «хитрый» способ подмены представления группы. Если группировка в списке идет по ссылочному полю (например, СправочникСсылка.Статусы), мы можем переопределить его представление.
Разберем реализацию по шагам:
ОбработкаПолученияПредставления.СтандартнаяОбработка = Ложь и формируем строку вида "Статус (15 шт)".Важно помнить: этот метод может замедлить отрисовку, если запросов в цикле будет слишком много. Рекомендуется использовать кеширование значений.
Если нам не нужны итоги по каждой группе, а достаточно общего итога по списку (с учетом установленных пользователем отборов), воспользуемся встроенным механизмом платформы 8.3.15+. При необходимости можно использовать готовое решение для настройки итогов в колонках динамического списка через вычисляемые поля.
Рассмотрим настройку:
ОтображатьПодвал.Роль (в СКД) или воспользуемся программной установкой:
ЭлементИтога = Список.НастройкиКомпоновкиДанных.Итоги.Элементы.Добавить();
ЭлементИтога.Поле = Новый ПолеКомпоновкиДанных("СуммаДокумента");
ЭлементИтога.ТипИтога = ТипИтогаКомпоновкиДанных.Сумма;
ЭлементИтога.Использование = Истина;
Теперь в нижней части списка всегда будет актуальная сумма по всем видимым (отфильтрованным) записям.
Выбор метода зависит от конкретных условий задачи:
Помните, что динамический список в первую очередь — это интерфейсный элемент для навигации, а не инструмент для построения сложных отчетов с глубокой аналитикой и итогами.