Отчеты, СКД, построитель

Размещаем на форме отчета поле выбора «ПолеВыбораВарианта». В модуль формы добавляем:

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

Для автоматического формирования отчета на СКД при открытии его формы надо добавить в модуль формы в процедуру ПриСозданииНаСервере:

Параметры.СформироватьПриОткрытии = Истина;

а для автоматического формирования из команды надо добавить в модуль команды в процедуру ОбработкаКоманды:

ПараметрыФормы = Новый Структура("СформироватьПриОткрытии", ИСТИНА);
ОткрытьФорму("Отчет.ОстатокДенежныхСредств.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно);

Что бы избежать запроса на сохранение варианта отчета при его закрытии надо в клиентскую процедуру ПередЗакрытием вставить:

ВариантМодифицирован = Ложь;

Первоначальные пользовательские настройки устанавливаются в процедуре ПриЗагрузкеПользовательскихНастроекНаСервере:

ЭтаФорма.Отчет.Период = ТекущаяДата();
Параметр = ЭтаФорма.Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Период"));
Параметр.Значение = ЭтаФорма.Отчет.Период;
Параметр.Использование = ИСТИНА;

Передача периода из формы отчета в СКД

НачалоПериода и КонецПериода - заданные в компановщике параметры

Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("НачалоПериода"));
Параметр.Значение = НачалоДня(НачПериода);
Параметр.Использование = ИСТИНА;

Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("КонецПериода"));
Параметр.Значение = КонецДня(КонПериода);
Параметр.Использование = ИСТИНА;

Передача реквизита СкладОтбор из формы отчета в СКД

ПолеСклад = Новый ПолеКомпоновкиДанных("Склад");

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

Если ЭлементОтбора = Неопределено Тогда
	ЭлементОтбора = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
КонецЕсли; 

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ЛевоеЗначение = ПолеСклад;
ЭлементОтбора.ПравоеЗначение = СкладОтбор;
ЭлементОтбора.Использование = НЕ СкладОтбор.Пустая();

Отчет на СКД можно сформировать программно в процедуре «ПриКомпоновкеРезультата()» модуля отчета:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	СтандартнаяОбработка = ЛОЖЬ;
	
	НастройкиКомпоновки = КомпоновщикНастроек.ПолучитьНастройки();
	
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиКомпоновки, ДанныеРасшифровки);
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры

При программном выводе отчета возможно вмешаться в выводимою форму. В примере ниже показано добавление наименования Родителя (/Родитель/) к тексту выводимого поля Номенклатура:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	. . . // см. пример выше
	
	КоличествоСтрок = ДокументРезультат.ВысотаТаблицы;
	КоличествоКолонок = ДокументРезультат.ШиринаТаблицы;
	
	Для СтрокаДокумента = 1 По КоличествоСтрок Цикл
		
		Для КолонкаДокумента = 1 По КоличествоКолонок Цикл
		
			Область = ДокументРезультат.Область(СтрокаДокумента, КолонкаДокумента);
			Расшифровка = Область.Расшифровка;
			Если ТипЗнч(Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
				
				ПоляРасшифровки = ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля();
				НайденноеПоле = ПоляРасшифровки.Найти("Номенклатура");
				Если НЕ НайденноеПоле = НЕОПРЕДЕЛЕНО Тогда
					
					ЗначениеПоля = НайденноеПоле.Значение;
					Если ТипЗнч(ЗначениеПоля) = Тип("СправочникСсылка.Номенклатура") И ЗначениеЗаполнено(ЗначениеПоля) Тогда
						
						Область.Текст = "/" + ЗначениеПоля.Родитель + "/ " + ЗначениеПоля.Наименование;
						
					КонецЕсли; 
					
				КонецЕсли; 
				
			КонецЕсли; 
		
		КонецЦикла; 
	
	КонецЦикла; 
	
КонецПроцедуры

При программном формировании отчета можно добавить свою область шапки или подвала в формируемый отчет:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	ДокументРезультат.Очистить();
	МакетШапки = ПолучитьМакет("МакетШапки");
	ОбластьШапка = НашМакетШапки.ПолучитьОбласть("Шапка");
	ДокументРезультат.Вывести(ОбластьШапка);
	
	. . . // программно формируем отчет
	
КонецПроцедуры

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ИмяОбъектаСодержащегоДанные", ТаблицаЗначений);

СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпановки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);

ПроцессорКомпановкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпановкиДанных.Инициализировать(МакетКомпановки, ВнешниеНаборыДанных);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпановкиДанных);

Существует ряд ограничений. Главное из которых: в настройках должны присутствовать только группировки и поля (без таблиц и т.п.).

Макет компановки задается:

МакетКомпановки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

Для процессора вывода используется метод УстановитьОбъект:

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДеревоЗначений);

Вывод производится: в цикле:

ПроцессорВывода.НачатьВывод();
Пока Истина Цикл
	ЭлементРезультатаКомпановкиДанных = ПроцессорКомпановкиДанных.Следующий();
	Если ЭлементРезультатаКомпановкиДанных = Неопределено Тогда
		Прервать;
	КонецЕсли;
	ПроцессорВывода.ВывестиЭлемент(ЭлементРезультатаКомпановкиДанных);
КонецЦикла;
ПроцессорВывода.ЗакончитьВывод();

Весь код:

СхемаКомпоновкиДанных = ПолучитьМакет("МакетКомпановкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпановки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ПроцессорКомпановкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпановкиДанных.Инициализировать(МакетКомпановки);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДеревоЗначений);

ПроцессорВывода.НачатьВывод();
Пока Истина Цикл
	ЭлементРезультатаКомпановкиДанных = ПроцессорКомпановкиДанных.Следующий();
	Если ЭлементРезультатаКомпановкиДанных = Неопределено Тогда
		Прервать;
	КонецЕсли;
	ПроцессорВывода.ВывестиЭлемент(ЭлементРезультатаКомпановкиДанных);
КонецЦикла;
ПроцессорВывода.ЗакончитьВывод();

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

при программном выполнении отчета надо инициализировать так:

ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки,,,Истина);

Полезно использовать для конца периода в СКД в параметрах в поле Выражение следующую конструкцию:

ВЫБОР
	КОГДА &Период.ДатаОкончания=ДАТАВРЕМЯ(1,1,1) ИЛИ &Период.ДатаОкончания<&Период.ДатаНачала ТОГДА
		ДАТАВРЕМЯ(3999,12,31,23,59,59)
 	ИНАЧЕ
 		&Период.ДатаОкончания
КОНЕЦ

В параметрах виртуальной таблицы регистра накопления периодичность выбирается «АВТО». В выбранные поля добавляется Регистратор и обязательно - ПериодСекунда.


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


Построитель = Новый ПостроительОтчета;
Построитель.Текст = "Текст запроса";
Построитель.Параметры.Вставить("ПараметрЗапроса", ЗначениеПараметраЗапроса);
Построитель.ЗаполнитьНастройки();
Построитель.МакетОформления = ПолучитьМакетОформления(СтандартноеОформление.БезОформления);
Построитель.Выполнить();
Построитель.Вывести();
// Или Построитель.Вывести(ТабДок) (ТабДок может быть ЭлементыФормы.ПолеТабличногоДокумента)
// посмотреть макет можно: Построитель.Макет.Показать()

Статья Печенкина Романа на Mista.ru Ссылка на статью