Содержание

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

назад


Язык выражений СКД


Функции языка выражений СКД


Макеты СКД (статья на Инфостарте no name (json))

макеты_скд.pdf © ООО «Инфостарт»


Программная работа с настройками СКД (статья на Инфостарте Дмитрия Иванова)


Использование предопределенных макетов (статья на 1С ITS )

использование_предопределенных_макетов.pdf © ООО «1С»


Вывод иерархического справочника в СКД


Заготовка с формами (БСП БП 3.0)


Универсальная процедура программного вывода СКД (статья на Инфостарте ""Меньше копипаста!", или как Вася универсальную процедуру писал" Виталия Черненко (SeiOkami))

Вывод варианта отчета на СКД (неуправляемая форма)

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

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

СКД открытие и закрытие

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

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

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

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

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

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

Пользовательские настройки СКД

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Программный вывод отчета и расшифровки к нему

    НастройкиСКД = КомпоновщикНастроек.Настройки;
    
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    
    ДанныеРасшифровкиОтчета = Новый ДанныеРасшифровкиКомпоновкиДанных;
    
    НастройкиСКД.ПараметрыДанных.Элементы.Найти("Номенклатура").Значение = Справочники.Номенклатура.НайтиПоКоду("1"); // заполняем какие-то параметры

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

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

ДанныеРасшифровкиОтчета - это переменная модуля формы отчета (то, что объявляется через ключевое слово Перем). ЭлементыФормы.Результат - Результат это имя табличного документа куда выводится отчет.

Вывод расшифровок:

Вариант 1.

На табличном документе идет в обработчики событий и делаем обработчик на событие ОбработкаРасшифровки. Процедура обработчик будет иметь вид похожий на это:

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

    МассивДоступныхДействий = Новый Массив;
    МассивДоступныхДействий.Добавить(ДействиеОбработкиРасшифровкиКомпоновкиДанных.ОткрытьЗначение);

    НастройкиРасшифровки = ОбработкаРасшифровки.Выполнить(Расшифровка,, МассивДоступныхДействий);
    
КонецПроцедуры

Результат работы этого когда: двойной клик на любой ячейке ссылочного типа производит открытие этого элемента. Будь то документ, элемент справочника или ещё что-нибудь.

Вариант 2.

Все так же идем в обработчики события поля табличного документа и устанавливаем обработчик на ОбработкаРасшифровки:

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

    ПолеРасшифровки = ДанныеРасшифровкиОтчета.Элементы[Расшифровка].ПолучитьПоля()[0];
    Если ПолеРасшифровки.Поле = "Контрагент" ИЛИ
        ПолеРасшифровки.Поле = "Документ" Тогда
        
        Ссылка = ПолеРасшифровки.Значение;
        ОткрытьЗначение(Ссылка);
    КонецЕсли;
    
КонецПроцедуры

Тут получаем информацию о том куда пользователь щелкнул. Зная это мы можем получить значение, которое находится в расшифровке. Дальше с ним можем делать что угодно. В этом примере результат не отличается от варианта 1, т.к. и в том и в том случае мы просто хотим открыть значения каких-то ссылок. Но если бы, например, мы получали текст или число, которое нужно было как-то хитро обработать, то в варианте №2 мы можем это сделать.

Вместо выводов: если вы хотите открывать ссылочные типы, тогда какой вариант использовать - дело ваше. Преимущество первого над вторым, я вижу, только в компактности и универсальности кода. Как насчет быстродействия, например, я не мерял. Но если же вам нужно получить результат расшифровки и как-то его обработать дополнительно - вы можете воспользоваться вариантом №2.


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

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

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

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

Использоваие внешнего набора данных (программное выполнение компоновщика)

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

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

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

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

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

Вывод компоновщика в дерево значений

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

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

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

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

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

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

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

Весь код:

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

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

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

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

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

Вывод в таблицу значений:

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

Отбор с помощью СКД

Внешняя обработка, демонстрирующая использование отборов с помощью СКД


Использование внешних функций в СКД

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

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

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

Функция Вычислить в СКД

Вычислить(Выражение, Группировка, ТипРасчета)

Параметры: Выражение (Строка). Cодержит вычисляемое выражение; Группировка (Строка). Содержит имя группировки, в контексте которой необходимо вычислить выражение. В случае если в качестве имени группировки используется пустая строка, вычисление будет выполнено в контексте текущей группировки. В случае если в качестве имени группировки будет использована строка ОбщийИтог, вычисление будет выполнено в контексте общего итога. В остальных случаях вычисление будет выполняться в контексте родительской группировки с таким именем.

Например:

Сумма(СуммаОборот) / Вычислить("Сумма(СуммаОборот)", "ОбщийИтог")

В данном примере в результате получится отношение суммы по полю «СуммаОборот» записи группировки к сумме того же поля во всей компоновке. ТипРасчета (Строка). В случае если данный параметр имеет значение «ОбщийИтог», выражение будет вычисляться для всех записей группировки. В случае если значение параметра «Группировка», значения будут вычисляться для текущей групповой записи группировки.


Использование Пользовательских полей в СКД

В СКД можно создавать пользовательские поля.

пример вывода в детальных записях процента Суммы договора от итога по вышестоящей группировке (Проект):

Выбор
	Когда Вычислить("Сумма(СуммаДоговора)", "Проект") > 0
		Тогда Формат(СуммаДоговора / Вычислить("Сумма(СуммаДоговора)", "Проект") * 100, "ЧДЦ=2")
	Иначе 0
Конец

Конец периода в СКД

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

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

Правильный вывод остатков регистра накопления при выводе регистратора в СКД

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


Особенности получения остатков по регистру в СКД

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


Построитель отчета

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

&НаСервере
Функция ПолучитьТабличныйДокументИзТабличнойЧасти(НаименованиеТабЧасти = "ТаблицаРезультат_ОбщПравилаОстатки")

	ТабДокумент = Новый ТабличныйДокумент;
	ОбработкаОбъект = РеквизитФормыВЗначение("Отчет");
	ТаблицаСДанными = Неопределено;
	Выполнить("ТаблицаСДанными = ОбработкаОбъект." + НаименованиеТабЧасти + ".Выгрузить()");
	Если ТипЗнч(ТаблицаСДанными) <> Тип("ТаблицаЗначений") Тогда
		Возврат ТабДокумент;
	КонецЕсли; 
	
	Построитель = Новый ПостроительОтчета;
	Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаСДанными);
	Построитель.Выполнить();
	Построитель.Вывести(ТабДокумент);
	Возврат ТабДокумент;

КонецФункции

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