Шаблон типового отчета (СКД) в привилегированном режиме

Программирование - Инструментарий

Отчет СКД привилегированный режим

3
Шаблон типового отчета СКД (https://its.1c.ru/db/metod8dev#content:3048:hdoc), формирование отчета перенесено в привилегированный модуль. Для конфигураций, где есть общий модуль ТиповыеОтчеты.

Появилось несколько задач сделать внешние отчеты без ограничения прав, обычные формы, клиент- сервер, УПП 1.3.

Дано: пользователь с ролями "Пользователь ", "Вывод информации", надо сделать для него отчет, например, по Основным средствам.

При этом:

1. Роли добавить пользователю нельзя;

2. УстановитьПривилегированныйРежим(Истина) - во внешних отчетах на обычных формах не работает;

3. Сделать отчет на управляемых формах и встроить отчет в конфигурацию - заказчик против, т.к. у него уже настроен доступ ко внешним отчетам и обработкам через RLS.

в остается формирование отчета в привилегированном модуле.

За основу взят "Шаблон типового отчета СКД" https://its.1c.ru/db/metod8dev#content:3048:hdoc, формирование результата вынесено в привилегированный модуль.

Реализация такая:

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

2. В отчете, как обычно, в основной схеме компоновки добавляем набор данных - Запрос, делаем настройки. При запуске отчета создается программно еще одна схема - но с набором данных - Объект. Копируются все поля, параметры и ресурсы. Эта схема используется в отчете для инициализации компоновщика настроек и пользователь может настроить структуру без красных крестиков на полях.

Настройки, которые установил пользователь передаются на сервер, загружаются в настройки компоновщика основной схемы

Отчет по основной схеме формируется на сервере в общем модуле ДоработкиПривилегированный, возвращается назад уже готовый результат - Табличный документ.

Расшифровку полностью победить не удалось, оставила только одно действие - ОткрытьЗначение. Если  у пользователя есть права на объект - при двойном клике по объекту - откроется значение, если прав нет, выводится стандартное сообщение "У пользователя недостаточно прав для исполнение операции над базой данных".

Очень важно!!! В основной схеме компоновки данных в наборах данных обязательно должны быть указаны типы значений полей.

Функция СформироватьОтчет из модуля отчета:

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

	АдресРезультат = ДоработкиПривилегированный.СформироватьОтчетПривРежТабличныйДокумент(АдресСтруктураОтчета);
	РезультатСтруктура = ПолучитьИзВременногоХранилища(АдресРезультат);
	
	РезультатТабличныйДокумент = РезультатСтруктура.ТабличныйДокумент;         
	ДанныеРасшифровки = РезультатСтруктура.ДанныеРасшифровки;
	ДанныеРасшифровки.Настройки = КомпоновщикНастроек.Настройки;
	
	Результат.Вывести(РезультатТабличныйДокумент);
	
	Результат.ФиксацияСверху 			= РезультатТабличныйДокумент.ФиксацияСверху;

	Результат.Показать();	
        
        УдалитьИзВременногоХранилища(АдресСтруктураОтчета);
	УдалитьИзВременногоХранилища(АдресРезультат);
        //--конец

	//ТиповыеОтчеты.СформироватьТиповойОтчет(ЭтотОбъект, Результат, ДанныеРасшифровки, ВыводВФормуОтчета);
	КомпоновщикНастроек.ЗагрузитьНастройки(НастрокаПоУмолчанию);
	
КонецФункции     

Функция из модуля отчета, которая создает схему с набором данных Объект:

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

В процедуре ПрименитьНастройку модуля отчета:

Процедура ПрименитьНастройку() Экспорт
	
	//СхемаДляНастройки = ТиповыеОтчеты.ПолучитьСхемуКомпоновкиОбъекта(ЭтотОбъект);
	//++начало
	Схема = ПолучитьСхемуДляНастройки();
	//--конец
	
	// Считываение структуры настроек отчета
 	Если Не СохраненнаяНастройка.Пустая() Тогда
		
		СтруктураНастроек = СохраненнаяНастройка.ХранилищеНастроек.Получить();
		Если Не СтруктураНастроек = Неопределено Тогда
			КомпоновщикНастроек.ЗагрузитьНастройки(СтруктураНастроек.НастройкиКомпоновщика);
			ЗаполнитьЗначенияСвойств(ЭтотОбъект, СтруктураНастроек);
		Иначе
			КомпоновщикНастроек.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
		КонецЕсли;
		
	Иначе
		КомпоновщикНастроек.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
	КонецЕсли;

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

В модуле отчета основную схему компоновки данных подменяем на созданную нами схему:

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

Функция в общем модуле ДоработкиПривилегированный (почти копия ТиповыеОтчеты.УниверсальныйМеханизмФормированияОтчета)

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

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

	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
		
	//Обозначим начало вывода
	ПроцессорВывода.НачатьВывод();
	ТаблицаЗафиксирована = Ложь;
	
	ТабличныйДокумент.ФиксацияСверху = 0;
	
	//определим нужна ли фиксация в отчете. Если элементов структуры больше 2-х
	КолВоВключеныхЭлементов = 0;
	Для каждого ЭлементСтруктуры из НастройкиКомпоновщика.Структура Цикл
		Если ЭлементСтруктуры.Использование тогда 
			КолВоВключеныхЭлементов = КолВоВключеныхЭлементов + 1;
		КонецЕсли;
		
		Если КолВоВключеныхЭлементов > 1 тогда
			ТаблицаЗафиксирована = истина;
		КонецЕсли;
	КонецЦикла;
	
	//Основной цикл вывода отчета
	Пока Истина Цикл
		
		//Получим следующий элемент результата компоновки
		ЭлементРезультата = ПроцессорКомпоновки.Следующий();
		
		Если ЭлементРезультата = Неопределено Тогда
			//Следующий элемент не получен - заканчиваем цикл вывода
			Прервать;
			
		Иначе
			
			Если  Не ТаблицаЗафиксирована 
				И ЭлементРезультата.ЗначенияПараметров.Количество() > 0 
				И ТипЗнч(НастройкиКомпоновщика.Структура[0]) <> Тип("ДиаграммаКомпоновкиДанных") Тогда
				
				ТаблицаЗафиксирована = Истина;
				ТабличныйДокумент.ФиксацияСверху = ТабличныйДокумент.ВысотаТаблицы;
				ОбластьШапки = ТабличныйДокумент.Область(3, ,ТабличныйДокумент.ВысотаТаблицы, );
				ТабличныйДокумент.ПовторятьПриПечатиСтроки = ОбластьШапки;

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

В архиве внешний отчет и текст для общего модуля. Тестировался на Управление производственным предприятием, редакция 1.3 (1.3.82.1). Не проверяла на сложных схемах с произвольными макетами, вложенными схемами.

3

Скачать файлы

Наименование Файл Версия Размер
Шаблона типового отчета (СКД) в привилегированном режиме:
.7z 33,64Kb
01.11.17
8
.7z 33,64Kb 8 Скачать

См. также

Комментарии
Избранное Подписка Сортировка: Древо
1. NoRazum 20 02.11.17 12:08 Сейчас в теме
Если отчет встраивать в конфу нельзя. То почему общие модули можно?

За код спасибо. Но полезность сомнительна.
2. user660938_zerkalo242 22.05.18 12:57 Сейчас в теме
Спасибо автору. Только такой подход сработал. Много времени потратил на поиск решения проблемы в интернет.
3. sergathome 22.05.18 13:14 Сейчас в теме
вызываемые функции будут всёравно в безопасном режиме вызываться, интересно, или нет ?
4. Lusha_28 31 24.05.18 07:34 Сейчас в теме
(3) У всех пользователей, которые пользуются этими отчетами стоит галка "Защита от опасных действий", на ошибки никто не жалуется.
5. sergathome 24.05.18 09:18 Сейчас в теме
(4) а это фиолетово. все внешние функции, вызываемые при компоновке, ранее вызывались в безопасном режиме несмотря вообще ни на что, даже если они располагались в модуле прив. режима... если можете проверить - проверьте, очень интересно.
Оставьте свое сообщение