среда, 18 января 2017 г.

Пример универсальной функции для создания схемы компоновки данных

Пример универсальной функции для создания схемы компоновки данных

Если вам приходится часто создавать схему компоновки данных программно или вы начинающий специалист и пытаетесь разобраться, что же за зверь такой СКД, то эта статья может оказаться вам полезной. Функция создает схему компоновки с минимально необходимой структурой данных. С помощью передачи дополнительных параметров есть возможность добавления ресурсов и оформления.

Оригинал статьи: http://infostart.ru/public/575659/
Появилась необходимость часто прибегать к программному созданию схемы компоновки данных. Было принято решение написать универсальную функцию принимающую различные наборы данных и на выходе возвращающую готовую СКД. Функция на вход принимает запрос, текст запроса, таблицу значений и дерево значений.
Помимо набора данных функция принимает ряд необязательных параметров:
  •  Структура ресурсов: содержит перечень полей ресурсов, где ключ - ИмяПоля, Значение(Строка) - Агрегатная функция ("Сумма", "Среднее", "Количество",  и т.д.);
  •  Флаг АвтоЗаполнениеДоступныхПолей;
  •  Строковое имя макета оформления.
// НаборДанных (Типы: Строка, запрос, ТаблицаЗначений, ДеревоЗначений)
// Искомый набор данных
//
// СтруктураРесурсов (Тип: Структура) - Структура полей ресурсов, где ключ - ИмяПоля, Значение(Строка) - Агрегатная функция
//
// ВноситьПоляВыбора (Тип: Булево) - Флаг добавление полей набора
//
// ИмяСтандартногоМакетаОформления (Тип: Строка) - Имя макета оформления 
//
Функция СоздатьСхемуКомпоновкиДанных(НаборДанных, СтруктураРесурсов = Неопределено, АвтоЗаполнениеДоступныхПолей = Истина, ИмяСтандартногоМакетаОформления = "")
 
 СКД = Новый СхемаКомпоновкиДанных;
 
 // Заполнение основных данных схемы
 ИсточникДанных = СКД.ИсточникиДанных.Добавить();
 ИсточникДанных.Имя = "ИсточникДанных";
 ИсточникДанных.ТипИсточникаДанных = "Local";
 
 Если ТипЗнч(НаборДанных) = Тип("Строка") или ТипЗнч(НаборДанных) = Тип("Запрос") Тогда
  ТекущийНаборДанных = СКД.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
  ТекущийНаборДанных.Имя = "ОсновнойНабор";
  ТекущийНаборДанных.Запрос = ?(ТипЗнч(НаборДанных) = Тип("Строка"),НаборДанных,НаборДанных.Текст);
  ТекущийНаборДанных.ИсточникДанных = "ИсточникДанных";   
  ТипНабора = "Запрос";
  ТекущийНаборДанных.АвтоЗаполнениеДоступныхПолей = АвтоЗаполнениеДоступныхПолей;
 ИначеЕсли ТипЗнч(НаборДанных) = Тип("ТаблицаЗначений") или ТипЗнч(НаборДанных) = Тип("ДеревоЗначений") Тогда
  ТекущийНаборДанных = СКД.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
  ТекущийНаборДанных.Имя = "ОсновнойНабор";
  ТекущийНаборДанных.ИмяОбъекта = "ТаблицаИсточник"; 
  ТекущийНаборДанных.ИсточникДанных = "ИсточникДанных";   
  ТипНабора = "Объект";
 Иначе   
  Возврат Неопределено;
 КонецЕсли; 
   
 НастройкиПоУмолчанию = СКД.НастройкиПоУмолчанию;
 
 // Создание структуры.
 // Группировка, детальные записи и автовыбранное поле
 Группировка = НастройкиПоУмолчанию.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
 Группировка.Использование = Истина;   
 АвтоПоле = Группировка.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
 АвтоПоле.Использование = Истина;
 
 КоллекцияКолонок = Новый ТаблицаЗначений;
 КоллекцияКолонок.Колонки.Добавить("Имя");
 КоллекцияКолонок.Колонки.Добавить("ТипЗначения");
 КоллекцияКолонок.Колонки.Добавить("Заголовок");
 
 Если ТипНабора = "Запрос" Тогда
  ПостроительЗапроса = Новый ПостроительЗапроса;
  Если ТипЗнч(НаборДанных) = Тип("Строка") Тогда
   ПостроительЗапроса.Текст = СокрЛП(НаборДанных);
  Иначе 
   ПостроительЗапроса.Текст = СокрЛП(НаборДанных.Текст);
  КонецЕсли;
  ПостроительЗапроса.ЗаполнитьНастройки();
  
  Для каждого ВыбранноеПоле Из ПостроительЗапроса.ВыбранныеПоля Цикл 
   НоваяКолонка = КоллекцияКолонок.Добавить();
   НоваяКолонка.Имя = ВыбранноеПоле.Имя;   
   НоваяКолонка.ТипЗначения = ПостроительЗапроса.ДоступныеПоля[ВыбранноеПоле.ПутьКДанным].ТипЗначения;
   НоваяКолонка.Заголовок = ВыбранноеПоле.Представление
  КонецЦикла;
  
 ИначеЕсли ТипНабора = "Объект" Тогда
  
  Для каждого Колонка Из НаборДанных.Колонки Цикл   
   НоваяКолонка = КоллекцияКолонок.Добавить();
   НоваяКолонка.Имя = Колонка.Имя;
   НоваяКолонка.ТипЗначения = Колонка.ТипЗначения;
   НоваяКолонка.Заголовок = Колонка.Имя;         
  КонецЦикла;
  
 КонецЕсли;
 
 // Добавление ресурсов
 Если ТипЗнч(СтруктураРесурсов) = Тип("Структура") Тогда   
  Для Каждого ЭлСтруктуры Из СтруктураРесурсов Цикл
   // Проверка, а существует ли поле ресурса среди полей набора
   Если КоллекцияКолонок.Найти(ЭлСтруктуры.Ключ) <> Неопределено Тогда
    // Проверка на правильность указания агрегатной функции
    Если    ЭлСтруктуры.Значение = "Сумма" 
     ИЛИ ЭлСтруктуры.Значение = "Среднее"
     ИЛИ ЭлСтруктуры.Значение = "Максимум"
     ИЛИ ЭлСтруктуры.Значение = "Минимум"
     ИЛИ ЭлСтруктуры.Значение = "Количество" Тогда
     
     ПолеРесурса             = СКД.ПоляИтога.Добавить();
     ПолеРесурса.ПутьКДанным = ЭлСтруктуры.Ключ;
     ПолеРесурса.Выражение   = ЭлСтруктуры.Значение + "(" + ЭлСтруктуры.Ключ + ")";     
     
    ИначеЕсли ЭлСтруктуры.Значение = "КоличествоРазличные" Тогда                      
     
     ПолеРесурса             = СКД.ПоляИтога.Добавить();
     ПолеРесурса.ПутьКДанным = ЭлСтруктуры.Ключ;
     ПолеРесурса.Выражение   = "Количество(Различные " + ЭлСтруктуры.Ключ + ")";
     
    КонецЕсли;
   КонецЕсли; 
  КонецЦикла;                                
 КонецЕсли;
  
 // Добавление полей в набор  
 Для каждого НоваяКолонка Из КоллекцияКолонок Цикл   
  ПолеНабора = ТекущийНаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
  ПолеНабора.Заголовок = СокрЛП(НоваяКолонка.Заголовок);
  ПолеНабора.Поле = СокрЛП(НоваяКолонка.Имя);
  ПолеНабора.ПутьКДанным = СокрЛП(НоваяКолонка.Имя);
  
  // Удалим неопределено и NULL
  Массив = Новый Массив;
  Для каждого ТекущийТип Из НоваяКолонка.ТипЗначения.Типы() Цикл
   Если ТекущийТип = Тип("Неопределено") или ТекущийТип = Тип("NULL") или ТекущийТип = Неопределено или ТекущийТип = Null Тогда 
    Продолжить; 
   КонецЕсли;
   Массив.Добавить(ТекущийТип);
  КонецЦикла;
  ПолеНабора.ТипЗначения = Новый ОписаниеТипов(Массив,НоваяКолонка.ТипЗначения.КвалификаторыЧисла,НоваяКолонка.ТипЗначения.КвалификаторыСтроки,НоваяКолонка.ТипЗначения.КвалификаторыДаты);
      
  ВыбранноеПолеКомпоновкиДанных = НастройкиПоУмолчанию.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));   
  ВыбранноеПолеКомпоновкиДанных.Поле = Новый ПолеКомпоновкиДанных(ПолеНабора.ПутьКДанным);
  ВыбранноеПолеКомпоновкиДанных.Использование = Истина;
 КонецЦикла;
  
 // Оформление
 Если не ПустаяСтрока(ИмяСтандартногоМакетаОформления) Тогда
  ЗначениеПараметраВывода = НастройкиПоУмолчанию.ПараметрыВывода.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("МакетОформления"));
  ЗначениеПараметраВывода.Значение = ИмяСтандартногоМакетаОформления;
  ЗначениеПараметраВывода.Использование = Истина;
 КонецЕсли;
  
 Возврат СКД;
 
КонецФункции

Комментариев нет:

Отправить комментарий