Каталог решений - Сложные отчеты для управляемых форм с использованием СКД: просто. На примере отчета ABC анализ номенклатуры, клиентов для УТ11

Сложные отчеты для управляемых форм с использованием СКД: просто. На примере отчета ABC анализ номенклатуры, клиентов для УТ11

Сложные отчеты для управляемых форм с использованием СКД: просто. На примере отчета ABC анализ номенклатуры, клиентов для УТ11

В наличии

Не очень часто, но все же, иногда приходится сталкиваться с необходимостью создания отчета, который очень сложно скомпоновать на "чистом" СКД, в этом случае альтернативой может являться следующая последовательность действий для получения итогового отчета: 1. при помощи одной схемы компоновки данных получить необходимую выборку данных; 2. запрограммировать (на языке 1С) некое преобразование этих данных; 3. при помощи другой схемы компоновки данных — произвести вывод необходимой информации в табличный документ. Как оказалось эта процедура не слишком сложная, хотя и немного запутанная.

Категория:

Описание

Когда запрос в СКД перестает «помещаться в голове» становится слишком громоздким (ЗиУП конечно не в счетSmile) и ситуацию не получается исправить различными фичами самой СКД, то можно использовать данный метод.

Сразу оговорюсь: иногда представленную методику можно использовать даже для простых случаев, с целью ускорения выполнения формирования отчета (это касается, например, случаев многкратного соединения больших объемов данных в запросе).

Общая идея:

1. Получаем необходимые данные при помощи первой схемы компоновки данных (можно конечно получить данные обычным запросом, но тогда нам самим придется описывать все поля условий, ресурсы и т.д., а также организовывать ввод пользовательских данных). В качестве данной СКД можно использовать основную схему компоновки данных отчета.

2. Обрабатываем полученную на первом этапе выборку используя язык программирования 1С (это обычно нагляднее чем сделать тоже самое, например, в запросе, к тому же в этом случае можно снабдить текст комментариями, не боясь того что их «проглотит» конструктор запросов).

3. Полученные на втором этапе данные — выводим при помощи другой схемы компоновки данных, используя всю (почти всю) мощь СКД в части вывода в табличный документ.

Проиллюстрируем на примере содания отчета ABC анализ номенклатуры, клиентов, уже построенного по этой методике:

1. Данные получаем при помощи СКД запросом к регистру Выручка и себестоимость продаж, будем использовать два варианта настройки (группировка по Номенклатуре и группировка по Клиентам)

2. Производим ABC анализ по методу, реализованонму в ТиС 7.7, и классическому методу ABC анализа

3. Выводим результаты используя другую СКД. 

Начнем пример:

1. Создаем новый внешний отчет, открываем основную схему комноновки данных, и формируем СКД для первоначальной выборки данных:

Здесь намеренно используется простой (неоптимизированный) запрос:

ВЫБРАТЬ РАЗРЕШЕННЫЕ

ВИСПОбороты.КоличествоОборот КАК Количество,
ВИСПОбороты.СуммаВыручкиОборот КАК Выручка,  
ВИСПОбороты.СебестоимостьОборот + ВИСПОбороты.СуммаДополнительныхРасходовОборот КАК СебестоимостьСДР,
ВИСПОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,  
ВИСПОбороты.АналитикаУчетаНоменклатуры.Склад КАК Склад,  ВИСПОбороты.СуммаВыручкиОборот — ВИСПОбороты.СебестоимостьОборот —    ВИСПОбороты.СуммаДополнительныхРасходовОборот КАК Прибыль,  
ВЫБОР       
    КОГДА ВИСПОбороты.СебестоимостьОборот + ВИСПОбороты.СуммаДополнительныхРасходовОборот = 0 
    ТОГДА 0
    ИНАЧЕ 100 * (ВИСПОбороты.СуммаВыручкиОборот — ВИСПОбороты.СебестоимостьОборот — ВИСПОбороты.СуммаДополнительныхРасходовОборот)
    / (ВИСПОбороты.СебестоимостьОборот + 
ВИСПОбороты.СуммаДополнительныхРасходовОборот) 
    КОНЕЦ КАК Прибыльность,   ВИСПОбороты.АналитикаУчетаПоПартнерам.Партнер КАК Партнер,  
ВИСПОбороты.АналитикаУчетаПоПартнерам.Организация КАК Организация,  
ВИСПОбороты.АналитикаУчетаПоПартнерам.Контрагент КАК Контрагент

ИЗ  РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&НачалоПериода, &КонецПериода, Авто,
  
    НЕ АналитикаУчетаПоПартнерам.Партнер = ЗНАЧЕНИЕ(Справочник.Партнеры.НашеПредприятие)) КАК ВИСПОбороты

Ресурсы:

Параметры:

Настройки:

Т.е. построена обычная СКД для выборки данных.

2. Добавляем основную форму отчета (удаляем с нее все элементы (это важно!)), и заново добавляем на нее Пользователские настройки компоновщика настроек отчета:

(если не отображаются названия колонок этой таблицы — включаем их отображение).

Наполняем содержимым форму (блок ABC):

Добавляем команду Сформировать и формируем соотвествующую кнопку.

3. Создаем СКД для вывода информации в табличный документ (добавляем соответствующий макет), описание полей:

 

Вычисляемые поля:

Ресурсы:

Вариант настроек БезГрупп:

Вариант настроек Классы:

 

Т.е. это тоже вполне обычная СКД, которая «заточена» под конкретные колонки таблицы значений, которую мы будем в нее передавать.

3. Наполняем содержимым команду Сформировать:

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

&НаСервере
Процедура СформироватьНаСервере()
   ОтчетОбъект = ДанныеФормыВЗначение(Отчет, Тип(«ОтчетОбъект«));

   //Первый этап: получаем данные при помощи СКД
   СКД = ОтчетОбъект.СхемаКомпоновкиДанных;                      
   ПользовательскиеНастройки = Отчет.КомпоновщикНастроек.ПользовательскиеНастройки; //Используем пользовательские настройки с формы отчета;
   Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(СКД.ВариантыНастроек[ОбъектАнализа].Настройки); //Используем нужный вариант
   Настройки = Отчет.КомпоновщикНастроек.Настройки;// Тут уже готовый вариант настроек
   //При необходимости корректируем поле группировки в соответствии с настройками
   //Это нужно когда выбрано значение СвойстоОбъектаАнализа
   //и анализ производится на основании значения реквизита соответствующего справочника
   Если ЗначениеЗаполнено(СвойствоОбъектаАнализа) Тогда
       ЭлементыПолейГруппировки = Настройки.Структура[0].ПоляГруппировки.Элементы;
       ЭлементыПолейГруппировки.Очистить();
       НовыйЭлементГруппировки = ЭлементыПолейГруппировки.Добавить(Тип(«ПолеГруппировкиКомпоновкиДанных«));
       НовыйЭлементГруппировки.Поле = Новый ПолеКомпоновкиДанных(?(ОбъектАнализа = «Клиенты», «Партнер», ОбъектАнализа) + «.» + СвойствоОбъектаАнализа);
       НовыйЭлементГруппировки.Использование = Истина;
  КонецЕсли;    
  //Копируем пользовательские настройки в основные настройки отчета
  Для Каждого ЭлементПользовательскихНастроек Из ПользовательскиеНастройки.Элементы Цикл
      Если ТипЗнч(ЭлементПользовательскихНастроек) = Тип(«ЗначениеПараметраНастроекКомпоновкиДанных») Тогда
         ЭлементНастройки = Настройки.ПараметрыДанных.Элементы.Найти(ЭлементПользовательскихНастроек.Параметр);
         ЗаполнитьЗначенияСвойств(ЭлементНастройки, ЭлементПользовательскихНастроек);
      ИначеЕсли ТипЗнч(ЭлементПользовательскихНастроек) = Тип(«ЭлементОтбораКомпоновкиДанных«) Тогда
         ЗаполнитьЭлементОтбораПоИД(Настройки.Отбор.Элементы, ЭлементПользовательскихНастроек); //Процедура определена в модуле формы
      КонецЕсли;
  КонецЦикла;
  //^^^^^^ все готово, чтобы получить исходную выборку
  //Следующие 8 строк — получение выборки в ТаблицуЗначений ТЗ:
  КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
  МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки, , , Тип(«ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений«));
  ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
  ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , );
  ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;  
  ТЗ = Новый ТаблицаЗначений;  
  ПроцессорВывода.УстановитьОбъект(ТЗ);  
  ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных, Ложь);
  //Конец Первого этапа: Выборка уже есть в ТЗ

  //Второй этап: Необходимые преобразования, для последующего вывода на экран
  //Тут реализуется алгоритм расчета для ABC анализа, взятый из ТиС 7.7, и классический ABC анализ
  //Здесь: Последняя сторка ТЗ — строка итогов, запомним числовые значения итогов в Структуре  
  Итоги = Новый Структура();  
  Для Каждого КолонкаТЗ Из ТЗ.Колонки Цикл
     ЗначениеЭлементаТЗ = ТЗ[ТЗ.Количество() — 1][КолонкаТЗ.Имя];
     Если Не ТипЗнч(ЗначениеЭлементаТЗ) = Тип(«Число«) Тогда Продолжить; КонецЕсли;
     Итоги.Вставить(КолонкаТЗ.Имя, ЗначениеЭлементаТЗ);
  КонецЦикла;
  ТЗ.Удалить(ТЗ.Количество() — 1); //Удалим строку итогов из ТЗ
  ТЗ.Колонки.Добавить(«ПроцентОтОбщего»); //Добавим новые колонки в ТЗ
  ТЗ.Колонки.Добавить(«Объект»);    
  ПоказательСтрокой = ?(Показатель = «Выручка по отгрузке», «Выручка«, ?(Показатель = «Прибыль по отгрузке», «Прибыль», «Прибыльность«));
  ОбъектАнализаСтрокой = ?(ОбъектАнализа = «Клиенты», «Партнер», ОбъектАнализа) + СокрЛП(СвойствоОбъектаАнализа);
  Для Каждого СтрокаТЗ Из ТЗ Цикл
     СтрокаТЗ.ПроцентОтОбщего = 100 * СтрокаТЗ[ПоказательСтрокой] / Итоги[ПоказательСтрокой];
     СтрокаТЗ.Объект = СтрокаТЗ[ОбъектАнализаСтрокой];  
  КонецЦикла;    
  //Обработка  
  Если СпособАнализа = 0 Тогда
     ПорядокСтрокой = ?(Порядок = «убывания», «Убыв», «Возр«);
     ТЗ.Сортировать(ПоказательСтрокой + » « + ПорядокСтрокой);
     КоличествоНужных = Окр(ТЗ.Количество() * Мин(ПроцентОбъектов, 100) / 100);
     Для Индекс = КоличествоНужных + 1 По ТЗ.Количество() — 1 Цикл
        ТЗ[Индекс].Объект = «»;
     КонецЦикла;  
  ИначеЕсли СпособАнализа = 1 Тогда
     ПорядокСтрокой = «Убыв»;
     ТЗ.Сортировать(ПоказательСтрокой + » « + ПорядокСтрокой);
     ОставитьСумму = Итоги[ПоказательСтрокой] * Мин(ПроцентСумм, 100) / 100;
     НакопленоСумма = 0;
     Для Каждого СтрокаТЗ Из ТЗ Цикл
       Если НакопленоСумма > ОставитьСумму Тогда
         СтрокаТЗ.Объект = «»;
       КонецЕсли;
       НакопленоСумма = НакопленоСумма + СтрокаТЗ[ПоказательСтрокой];
     КонецЦикла;
  Иначе
     ПорядокСтрокой = «Убыв»;
     ТЗ.Сортировать(ПоказательСтрокой + » « + ПорядокСтрокой);
     ТЗ.Колонки.Добавить(«Класс»);
     НакопленоСумма = 0;
     СуммаA = Итоги[ПоказательСтрокой] * ПроцентA / 100;
     СуммаAB = СуммаA + Итоги[ПоказательСтрокой] * ПроцентB / 100;
     СуммаABC = СуммаAB + Итоги[ПоказательСтрокой] * ПроцентC / 100;   //Все остальное D
     ТекущийКласс = «A»;
     Для Каждого СтрокаТЗ Из ТЗ Цикл
       СтрокаТЗ.Класс = ТекущийКласс;
       НакопленоСумма = НакопленоСумма + СтрокаТЗ[ПоказательСтрокой];
       Если ТекущийКласс = «A» И НакопленоСумма > СуммаA Тогда ТекущийКласс = «B»;
       ИначеЕсли ТекущийКласс = «B» И НакопленоСумма > СуммаAB Тогда ТекущийКласс = «C»;
       ИначеЕсли ТекущийКласс = «C» И НакопленоСумма > СуммаABC Тогда ТекущийКласс = «D»;
       КонецЕсли;
     КонецЦикла;
  КонецЕсли;
  //Конец Второго этапа: ТЗ преобразована и готова к выводу на экран.

  //Третий этап: Вывод через СКД в табличный документ, расположенный на форме 
  Результат.Очистить(); //Чистим Табличный документ от старых данных   
  ВнешниеНаборыДанных = Новый Структура(«ТЗ», ТЗ); //Готовим внешний набор который передадим СКД
  СКДВ = ОтчетОбъект.ПолучитьМакет(«СКДДляВывода»); //Получаем СКД Для Вывода из макетов Отчета;
  //Выбор нужного варианта настроек:
  НастройкиВ = СКДВ.ВариантыНастроек[?(СпособАнализа = 2, «Классы», «БезГрупп»)].Настройки; 
  //Настройка варианта графического отображения:
  НастройкиВ.Структура[1].Использование = (Диаграмма = «Гистограмма»);
  НастройкиВ.Структура[1].Выбор.Элементы[0].Поле = Новый ПолеКомпоновкиДанных(ПоказательСтрокой);
  НастройкиВ.Структура[2].Использование = (Диаграмма = «Круговая»);
  НастройкиВ.Структура[2].Выбор.Элементы[0].Поле = Новый ПолеКомпоновкиДанных(ПоказательСтрокой);    
  //Настройка сортировки:  
  ЭлементыСортировки = НастройкиВ.Порядок.Элементы;
  ЭлементыСортировки.Очистить();
  ЭлементСортировки = ЭлементыСортировки.Добавить(Тип(«ЭлементПорядкаКомпоновкиДанных»));
  ЭлементСортировки.Поле = Новый ПолеКомпоновкиДанных(ПоказательСтрокой);
  ЭлементСортировки.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных[ПорядокСтрокой];
  ЭлементСортировки.Использование = Истина;
  //Чтобы в итоговом отчете была Расшифровка, придется предпринять ряд шагов:

  ДанныеРасшифровкиКомпоновкиДанныхВ = Новый ДанныеРасшифровкиКомпоновкиДанных; //Сюда будут складываться данные для расшифровки
  КомпоновщикМакетаВ = Новый КомпоновщикМакетаКомпоновкиДанных;
  МакетКомпоновкиВ = КомпоновщикМакетаВ.Выполнить(СКДВ, НастройкиВ, ДанныеРасшифровкиКомпоновкиДанныхВ); //не забываем: данные для расшифровки
  ПроцессорКомпоновкиДанныхВ = Новый ПроцессорКомпоновкиДанных;
  ПроцессорКомпоновкиДанныхВ.Инициализировать(МакетКомпоновкиВ, ВнешниеНаборыДанных, ДанныеРасшифровкиКомпоновкиДанныхВ, Истина); 
  //^^^^ Предпоследний параметр: данные для расшифровки
  //^^^^Последний параметр — возможность использования внешних функций в компоновке, хотя они и не используются
  //Следующие 4 строки — вывод ТЗ в табличный документ:
  ПроцессорВыводаВ = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
  ПроцессорВыводаВ.УстановитьДокумент(Результат);
  ПроцессорВыводаВ.ОтображатьПроцентВывода = Истина;
  ПроцессорВыводаВ.Вывести(ПроцессорКомпоновкиДанныхВ);  
  //Передача через элемент формы, т.е. запоминаем адрес хранилища в параметре формы ДанныеРасшифровки
  ДанныеРасшифровки = ПоместитьВоВременноеХранилище(ДанныеРасшифровкиКомпоновкиДанныхВ, ЭтаФорма.УникальныйИдентификатор);
  //Избавление от надписи… скорее всего можно побороть как-то еще.
  ОтображениеСостояния = ЭтаФорма.Элементы.Результат.ОтображениеСостояния;
 
 ОтображениеСостояния.Видимость = Ложь;
  ОтображениеСостояния.ДополнительныйРежимОтображения = ДополнительныйРежимОтображения.НеИспользовать;
  //Установка текущей страницы
  Элементы.Страницы.ТекущаяСтраница = Элементы.Результаты;
  //Конец третьего этапа, Табличный документ заполнен результатами расчета

КонецПроцедуры

Это все. Тут не описано некоторое количество вспомогательных функций, которые можно увидеть непосредствено в реализации. 

has been added to your cart:
Оформление заказа