Подсмотрел универсальное решение расчета итогов в динамических списках. Основной принцип следующий:
- При создании формы с динамическим списком в дополнительные свойства настройки СКД списка добавляется таблица с указанием имени поля и нужной агрегатной функцией, например "Номер", "Количество". Таблица помещается в хранилище, а хранилище размещается размещается в ветке "РесурсыХранилище".
- На форму выводится отдельная кнопка "Расчет итогов". Обновлять итоги постоянно очень затратно по ресурсам и приводит к зависанию.
- Расчет итогов производится в общем модуле, в который передаются настройки СКД. Для получения настроек СКД, с учетом всех примененных отборов и поисков есть две волшебные функции: СКД = ЭтотОбъект.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных() и Настройки = ЭтотОбъект.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных().
- В полученной СКД программно добавляются группировка и ресурсы (ПоляИтогов), которые определяются из дополнительного свойства "РесурсыХранилище".
- Запускается формирование отчета по СКД, получаются значения итогов по ресурсам и программно заполняется текст подвала нужной колонки. На выходе получим таблицу с одной строкой и значениями нужных итогов.
Похожий пример можно посмотреть здесь https://v8book.ru/public/568012/
Теперь непосредственно сама реализация (взял целиком как есть).
Нужно вывести количество записей в колонке "Номер".
1. При создании на сервере формируем таблицу нужных итогов, записываем в хранилище и помещаем в дополнительное свойство.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЗаполнитьРесурсыДС(ЭтотОбъект.Список.КомпоновщикНастроек.Настройки);
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьРесурсыДС( НастройкиДС)
Если Не НастройкиДС.ДополнительныеСвойства.Свойство("РесурсыХранилище") Тогда // если ранее не было заполнено свойство, то создаем таблицу и помещаем в доп. свойство
ПодвалыВыбранныхПолей = Новый ТаблицаЗначений;
ПодвалыВыбранныхПолей.Колонки.Добавить("ВыбранноеПоле",Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(1000)));
ПодвалыВыбранныхПолей.Колонки.Добавить("Выражение",Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(1000)));
СтрокаТЗПодвалыВыбранныхПолей = ПодвалыВыбранныхПолей.Добавить();
СтрокаТЗПодвалыВыбранныхПолей.ВыбранноеПоле = "Номер";
СтрокаТЗПодвалыВыбранныхПолей.Выражение = "Количество";
НастройкиДС.ДополнительныеСвойства.Вставить("РесурсыХранилище", Новый ХранилищеЗначения(ПодвалыВыбранныхПолей));
Иначе // если доп. свойство было ранее заполнено, то добавляем при необходимости поля, хотя неясно, как это свойство было заполнено, если форма только создается. Наверное откуда-то взяли кусок кода.
ПодвалыВыбранныхПолей = НастройкиДС.ДополнительныеСвойства.РесурсыХранилище.Получить();
Если ПодвалыВыбранныхПолей.Найти("Наименование", "ВыбранноеПоле") = Неопределено Тогда
СтрокаТЗПодвалыВыбранныхПолей = ПодвалыВыбранныхПолей.Добавить();
СтрокаТЗПодвалыВыбранныхПолей.ВыбранноеПоле = "Наименование";
СтрокаТЗПодвалыВыбранныхПолей.Выражение = "Количество";
КонецЕсли;
НастройкиДС.ДополнительныеСвойства.Вставить("РесурсыХранилище", Новый ХранилищеЗначения(ПодвалыВыбранныхПолей));
КонецЕсли;
КонецПроцедуры
2. Обработка команды ОбновитьИтоги
&НаКлиенте
Процедура ОбновитьИтоги(Команда)
ОбновитьИтогиНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбновитьИтогиНаСервере()
КомпоновкаДанныхСервер.ОбновитьИтогиДС("Список",ЭтотОбъект);
КонецПроцедуры
3 Код общего модуля
// Обновляет итоги динамического списка
Функция ОбновитьИтогиДС(ИмяДС,пФорма) Экспорт
Результат = Неопределено;
СКД = пФорма.Элементы[ИмяДС].ПолучитьИсполняемуюСхемуКомпоновкиДанных(); // Получаем СКД динамического списка со всеми примененными отборами
Настройки = пФорма.Элементы[ИмяДС].ПолучитьИсполняемыеНастройкиКомпоновкиДанных(); // Получаем настройки СКД, которые применены для динамического списка, с учетом поиска
Настройки.Структура.Очистить();
ДетальныеЗаписи = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных")); // создаем группировку, предварительно остальные удалив
ДобавитьРесурсыСКД_ДС (СКД, Настройки,ДетальныеЗаписи); // добавляем поля ресурсов в СКД
// Формируем отчет по СКД с выводом в таблицу значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
Результат = Новый ТаблицаЗначений;
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,,,Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(Результат);
Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновки, Истина);
// выводим данные итогов в подвалы колонок
Для каждого стр из Результат цикл
Для каждого кол из Результат.Колонки цикл
УстановитьТекстПодвалаЭлемента(пФорма.Элементы[ИмяДС],ИмяДС+"."+ кол.Имя,стр[кол.Имя])
КонецЦикла ;
КонецЦикла ;
КонецФункции
// Добавляет ресурсы СКД динамического списка
// Взял как есть. Здесь лишний кусок кода, который подключает справочник РасширенияЗапросов. Основная мысль в том, чтобы получить таблицу с указанием итогов и добавить по ней поля ресурсов в СКД
Процедура ДобавитьРесурсыСКД_ДС (СКД, Настройки, ДетальныеЗаписи = Неопределено)Экспорт
Запрос = Новый Запрос;
ТекстЗапроса ="" ;
Если Настройки.ДополнительныеСвойства.Свойство("РесурсыХранилище") Тогда
ТЗРесурсыОсновногоСписка =Настройки.ДополнительныеСвойства.РесурсыХранилище.Получить();
ТекстЗапроса =
"ВЫБРАТЬ
| """" КАК Ссылка,
| ТЗРесурсыОсновногоСписка.ВыбранноеПоле КАК ВыбранноеПоле,
| ТЗРесурсыОсновногоСписка.Выражение КАК Выражение,
| """" КАК Представление
|ПОМЕСТИТЬ ТЗРесурсыОсновногоСписка
|ИЗ
| &ТЗРесурсыОсновногоСписка КАК ТЗРесурсыОсновногоСписка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТЗРесурсыОсновногоСписка.Ссылка КАК Ссылка,
| ТЗРесурсыОсновногоСписка.ВыбранноеПоле КАК ИмяПоля,
| ТЗРесурсыОсновногоСписка.Выражение КАК Выражение,
| ТЗРесурсыОсновногоСписка.Представление КАК Представление
|ИЗ
| ТЗРесурсыОсновногоСписка КАК ТЗРесурсыОсновногоСписка" ;
Запрос.УстановитьПараметр( "ТЗРесурсыОсновногоСписка",ТЗРесурсыОсновногоСписка) ;
КонецЕсли;
Если Настройки.ДополнительныеСвойства.Свойство("ВыбранныеРасширенияХранилище")Тогда
ВыбранныеРасширения =Настройки.ДополнительныеСвойства.ВыбранныеРасширенияХранилище.Получить();
ТекущийТекстЗапроса = ?(ЗначениеЗаполнено(ТекстЗапроса),ТекстЗапроса + ";","") ;
ТекущийТекстЗапроса = ТекущийТекстЗапроса + Символы.ПС +
"ВЫБРАТЬ
| ВТ_Расширение.Расширение КАК Расширение,
| ВТ_Расширение.Представление КАК Представление
|ПОМЕСТИТЬ Вт_Расширение
|ИЗ
| &ВыбранныеРасширения КАК ВТ_Расширение
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| РасширенияЗапросовДоступныеПоля.Ссылка КАК Ссылка,
| РасширенияЗапросовДоступныеПоля.ИмяПоля КАК ИмяПоля,
| РасширенияЗапросовДоступныеПоля.Выражение КАК Выражение,
| Вт_Расширение.Представление КАК Представление
|ИЗ
| Справочник.РасширенияЗапросов.ДоступныеПоля КАК РасширенияЗапросовДоступныеПоля
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Вт_Расширение КАК Вт_Расширение
| ПО РасширенияЗапросовДоступныеПоля.Ссылка = Вт_Расширение.Расширение
|ГДЕ
| (ВЫРАЗИТЬ(РасширенияЗапросовДоступныеПоля.Выражение КАК СТРОКА(1000))) <> """"" ;
Запрос.УстановитьПараметр("ВыбранныеРасширения",ВыбранныеРасширения);
Если ЗначениеЗаполнено(ТекстЗапроса) Тогда
ДополнительныйТекстЗапроса =
"ВЫБРАТЬ
| ТЗРесурсыОсновногоСписка.Ссылка ,
| ТЗРесурсыОсновногоСписка.ВыбранноеПоле ,
| ТЗРесурсыОсновногоСписка.Выражение ,
| ТЗРесурсыОсновногоСписка.Представление
|ИЗ
| ТЗРесурсыОсновногоСписка КАК ТЗРесурсыОсновногоСписка" ;
ТекстЗапроса = ОбъединитьЗапросСЗапросом(ТекущийТекстЗапроса,ДополнительныйТекстЗапроса);
Иначе
ТекстЗапроса = ТекущийТекстЗапроса;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ТекстЗапроса) Тогда
Возврат;
КонецЕсли;
Запрос.Текст = ТекстЗапроса ;
Выборка = Запрос.Выполнить().Выбрать();
ДанныеВыбора = Новый СписокЗначений;
ДанныеВыбора.Добавить("Количество");
ДанныеВыбора.Добавить("Максимум");
ДанныеВыбора.Добавить("Минимум");
ДанныеВыбора.Добавить("Сумма");
ДанныеВыбора.Добавить("Среднее");
Пока Выборка.Следующий() Цикл
ПрефиксПолей =?(ЗначениеЗаполнено(Выборка.Ссылка), ОбщегоНазначения.ПолучитьИдентификаторИзСтроки(Выборка.Представление)+"_","");
ИскомоеПоле = ПрефиксПолей + Выборка.ИмяПоля ;
ДоступноеПоле = Настройки.ДоступныеПоляВыбора.НайтиПоле(Новый ПолеКомпоновкиДанных(ИскомоеПоле));
Если ДоступноеПоле <> Неопределено и ЗначениеЗаполнено(Выборка.Выражение)и СКД.ПоляИтога.Найти(ИскомоеПоле)=Неопределено Тогда
Если ДетальныеЗаписи <> Неопределено Тогда
ДетальныеЗаписи.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных")).Поле = Новый ПолеКомпоновкиДанных(ИскомоеПоле);
КонецЕсли;
Если ДанныеВыбора.НайтиПоЗначению(СокрЛП(Выборка.Выражение))<> Неопределено Тогда
ПолеИтога = НовыйРесурс(СКД, ИскомоеПоле,Выборка.Выражение);
Иначе
Выражение = СтрЗаменить(Выборка.Выражение,Выборка.ИмяПоля,ИскомоеПоле);
ПолеИтога = НовыйРесурс(СКД, ИскомоеПоле,,Выражение);
КонецЕсли;
КонецЕсли;
КонецЦикла ;
КонецПроцедуры
// добавление нового ресурса в СКД
Функция НовыйРесурс(СхемаКД, ПутькДанным, Агрегат = "Сумма", ВыражениеРесурса = "") Экспорт
НовыйРесурс = СхемаКД.ПоляИтога.Добавить();
НовыйРесурс.ПутькДанным = ПутькДанным;
НовыйРесурс.Выражение = Агрегат + "("+ НовыйРесурс.ПутькДанным +")";
Если НЕ ПустаяСтрока(ВыражениеРесурса) Тогда
НовыйРесурс.Выражение = ВыражениеРесурса;
КонецЕсли;
Возврат НовыйРесурс;
КонецФункции
// Устанавливает текст подвала динамического списка
Процедура УстановитьТекстПодвалаЭлемента(Группа, Путь,ТекстПодвала)
Для Каждого Элемент Из Группа.ПодчиненныеЭлементы Цикл
Если ТипЗнч(Элемент) = Тип("ГруппаФормы") Тогда
УстановитьТекстПодвалаЭлемента(Элемент, Путь,ТекстПодвала);
ИначеЕсли ТипЗнч(Элемент) = Тип("ПолеФормы") и Элемент.ПутьКДанным = Путь Тогда
Если ТипЗнч(ТекстПодвала)= Тип("Число") Тогда
ФорматСумм = "ЧДЦ=" + Строка(ОбщегоНазначения.ПолучитьЗначениеКонстанты("ТочностьОкругленияСумм"));
ТекстПодвала = Формат(ТекстПодвала,ФорматСумм) ;
КонецЕсли;
Элемент.ТекстПодвала = Строка(ТекстПодвала);
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
|