Приветствую Вас ГостьСуббота, 18.05.2024, 12:15

Каталог статей


Итоги в динамических списках

Подсмотрел универсальное решение расчета итогов в динамических списках. Основной принцип следующий:

  1. При создании формы с динамическим списком в дополнительные свойства настройки СКД списка добавляется таблица с указанием имени поля и нужной агрегатной функцией, например "Номер", "Количество". Таблица помещается в хранилище, а хранилище размещается размещается в ветке "РесурсыХранилище".
  2. На форму выводится отдельная кнопка "Расчет итогов". Обновлять итоги постоянно очень затратно по ресурсам и приводит к зависанию.
  3. Расчет итогов производится в общем модуле, в который передаются настройки СКД. Для получения настроек СКД, с учетом всех примененных отборов и поисков есть две волшебные функции: СКД = ЭтотОбъект.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных() и Настройки = ЭтотОбъект.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных().
  4. В полученной СКД программно добавляются группировка и ресурсы (ПоляИтогов), которые определяются из дополнительного свойства "РесурсыХранилище".
  5. Запускается формирование отчета по СКД, получаются значения итогов по ресурсам и программно заполняется текст подвала нужной колонки. На выходе получим таблицу с одной строкой и значениями нужных итогов.

Похожий пример можно посмотреть здесь https://v8book.ru/public/568012/

Теперь непосредственно сама реализация (взял целиком как есть).

Нужно вывести количество записей в колонке "Номер".

1. При создании на сервере формируем таблицу нужных итогов, записываем в хранилище и помещаем в дополнительное свойство.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЗаполнитьРесурсыДС(ЭтотОбъект.Список.КомпоновщикНастроек.Настройки);
КонецПроцедуры   

&НаСервере
Процедура ЗаполнитьРесурсыДС( НастройкиДС)
    
    Если Не НастройкиДС.ДополнительныеСвойства.Свойство("РесурсыХранилище") Тогда // если ранее не было заполнено свойство, то создаем таблицу и помещаем в доп. свойство
        
        ПодвалыВыбранныхПолей = Новый ТаблицаЗначений;
        ПодвалыВыбранныхПолей.Колонки.Добавить("ВыбранноеПоле",Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(1000)));        
        ПодвалыВыбранныхПолей.Колонки.Добавить("Выражение",Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(1000)));
        
        СтрокаТЗПодвалыВыбранныхПолей = ПодвалыВыбранныхПолей.Добавить();
        СтрокаТЗПодвалыВыбранныхПолей.ВыбранноеПоле = "Номер";
        СтрокаТЗПодвалыВыбранныхПолей.Выражение = "Количество";       
        
        НастройкиДС.ДополнительныеСвойства.Вставить("РесурсыХранилище", Новый ХранилищеЗначения(ПодвалыВыбранныхПолей));
        
    Иначе // если доп. свойство было ранее заполнено, то добавляем при необходимости поля, хотя неясно, как это свойство было заполнено, если форма только создается. Наверное откуда-то взяли кусок кода.
        
        ПодвалыВыбранныхПолей = НастройкиДС.ДополнительныеСвойства.РесурсыХранилище.Получить();
        Если ПодвалыВыбранныхПолей.Найти("Наименование", "ВыбранноеПоле") = Неопределено Тогда
            СтрокаТЗПодвалыВыбранныхПолей = ПодвалыВыбранныхПолей.Добавить();
            СтрокаТЗПодвалыВыбранныхПолей.ВыбранноеПоле = "Наименование";
            СтрокаТЗПодвалыВыбранныхПолей.Выражение = "Количество";
        КонецЕсли;
        
        НастройкиДС.ДополнительныеСвойства.Вставить("РесурсыХранилище", Новый ХранилищеЗначения(ПодвалыВыбранныхПолей));
        
    КонецЕсли;
    
КонецПроцедуры

2. Обработка команды ОбновитьИтоги

&НаКлиенте
Процедура ОбновитьИтоги(Команда)
    ОбновитьИтогиНаСервере();
КонецПроцедуры

&НаСервере
Процедура ОбновитьИтогиНаСервере()
    КомпоновкаДанныхСервер.ОбновитьИтогиДС("Список",ЭтотОбъект);
КонецПроцедуры

3 Код общего модуля

// Обновляет итоги динамического списка
Функция ОбновитьИтогиДС(ИмяДС,пФорма) Экспорт
    
    Результат = Неопределено;
    СКД = пФорма.Элементы[ИмяДС].ПолучитьИсполняемуюСхемуКомпоновкиДанных(); // Получаем СКД динамического списка со всеми примененными отборами
    Настройки = пФорма.Элементы[ИмяДС].ПолучитьИсполняемыеНастройкиКомпоновкиДанных(); // Получаем настройки СКД, которые применены для динамического списка, с учетом поиска
    Настройки.Структура.Очистить();
    ДетальныеЗаписи = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных")); // создаем группировку, предварительно остальные удалив
    ДобавитьРесурсыСКД_ДС (СКД, Настройки,ДетальныеЗаписи); // добавляем поля ресурсов в СКД
    // Формируем отчет по СКД с выводом в таблицу значений
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    Результат = Новый ТаблицаЗначений;
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки,,,Истина);
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ПроцессорВывода.УстановитьОбъект(Результат);
    Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновки, Истина);
    // выводим данные итогов в подвалы колонок
    Для каждого стр из  Результат цикл
        Для каждого кол из Результат.Колонки цикл
            УстановитьТекстПодвалаЭлемента(пФорма.Элементы[ИмяДС],ИмяДС+"."+ кол.Имя,стр[кол.Имя])
        КонецЦикла ;
    КонецЦикла ;    
КонецФункции

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

// добавление нового ресурса в СКД
Функция НовыйРесурс(СхемаКД, ПутькДанным, Агрегат = "Сумма", ВыражениеРесурса = "") Экспорт
    
    НовыйРесурс = СхемаКД.ПоляИтога.Добавить();
    НовыйРесурс.ПутькДанным = ПутькДанным;
    НовыйРесурс.Выражение = Агрегат + "("+ НовыйРесурс.ПутькДанным +")";
    Если НЕ ПустаяСтрока(ВыражениеРесурса) Тогда
        НовыйРесурс.Выражение = ВыражениеРесурса;
    КонецЕсли;
    
    Возврат НовыйРесурс;
    
КонецФункции

// Устанавливает текст подвала динамического списка
Процедура УстановитьТекстПодвалаЭлемента(Группа, Путь,ТекстПодвала)
    Для Каждого Элемент Из Группа.ПодчиненныеЭлементы Цикл
        Если ТипЗнч(Элемент) = Тип("ГруппаФормы") Тогда
            УстановитьТекстПодвалаЭлемента(Элемент, Путь,ТекстПодвала);
        ИначеЕсли ТипЗнч(Элемент) = Тип("ПолеФормы") и Элемент.ПутьКДанным = Путь Тогда
            Если ТипЗнч(ТекстПодвала)= Тип("Число") Тогда
                ФорматСумм = "ЧДЦ=" + Строка(ОбщегоНазначения.ПолучитьЗначениеКонстанты("ТочностьОкругленияСумм"));
                ТекстПодвала = Формат(ТекстПодвала,ФорматСумм) ;
            КонецЕсли;
            Элемент.ТекстПодвала = Строка(ТекстПодвала);
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

 

Категория: Формы | Добавил: leshic (24.06.2022)
Просмотров: 570 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [41]
Администрирование [35]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0