Top.Mail.Ru

Универсальная печатная форма Приказа/Договора с возможностью настройки макета в пользовательском режиме

Обратился клиент, который, среди всего прочего, занимается организацией прохождения производственной и преддипломной практики на своих предприятиях. Постановка задачи звучала как-то так: "У нас есть большое количество различных приказов, текст которых утвержден, но может часто меняться. Также для каждого подразделения текст и бланк приказа может быть разный. Также в частном случае текст может быть изменен, но макет при этом менять не нужно, а вот сделанные изменения запомнить нужно. При этом мы не хотим платить программистам каждый раз, когда нам нужно что-то поменять в макете, пусть все изменения макета происходят в пользовательском режиме". Ну и небольшой особенностью клиента является то, что все печатные формы должны сразу быть в формате Word.

Взяли все варианты их приказов и начали анализировать. Структура всех макетов схожа:
- Шапка – Номер / Дата
- Заголовок – Текст заголовка по центру страницы
- Преамбула – Текст без форматирования, в котором присутствует фиксированный текст и текст, который можно выделить как параметры
- Пункты приказа – Набор абзацев текста без форматирования, в котором присутствует фиксированный текст и текст, который можно выделить как параметры. Абзацы могут быть либо пронумерованы, либо нет. В абзаце может быть повторяющийся текст, например:
«…организовать прохождение производственной практики студенту(ам): Иванову И.И.; Петрову П.П.; Сергееву С.С…». Также обратили внимание, что в разных абзацах повторяющийся текст может быть разным.
- Подвал – различные подписанты

Клиент работает в дописанной ЗУП 3.1.13.120. Поискали что-нибудь подходящее в типовых решениях, но на 100% подходящего ничего не нашлось. К тому же документ, который будет фиксировать приказы, создавать нужно, поэтому было принято решение добавлять новый функционал.

В основе всей доработки лежит макет табличного документа с ровно одной ячейкой с видом заполнения «Шаблон».

Абсолютно универсальный механизм реализовать либо невозможно, либо очень трудозатратно, поэтому с клиентом был согласован список параметров, которые пользователь сможет вставлять в макет в режиме предприятия. Так же условились, что структура макета будет иметь вид как описан выше.

Для начала был разработан справочник «Шаблоны приказов»:  



Форма элемента справочника "Шаблоны приказов"

Справочник имеет 2 реквизита типа строка неограниченной длины и 2 табличные части, в каждой из которых поле типа строка неограниченной длины. 

Одна табличная часть будет содержать тексты пунктов, а во второй будут описаны шаблоны повторяющегося текста. 

Во всех выше описанных полях может присутствовать текст, построенный по принципу Шаблона в макете Табличного документа. Список доступных параметров описан в отдельном макете MXL_ДоступныеПараметры. Для удобства работы с макетом и копирования из него параметров, была добавлена страница «Доступные параметры» с одним реквизитом типа ТабличныйДокумент. Вид макета:   


Скриншот макета MXL_ДоступныеПараметры

Затем был разработан документ «Приказ об организации прохождения практики». Документ разделен на 2 страницы: 

1. Основные данные – для заполнения данных документа:  


Вид страницы Основные данные


2. Шаблон приказа – для подготовки текста Приказа:  

4.png

Вид страницы Шаблон приказа

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

При выборе Шаблона заполнения из базы данных получается структура самого шаблона и данные для заполнения параметров.   

Код получения структуры шаблона:

//---------------------------------------------
//  Форма документа
//---------------------------------------------
                            
&НаСервере
Процедура ЗаполнитьПоШаблонуНаСервере(ШаблонПриказа)

	// Сперва очистим значения
	Объект.ЗаголовокПриказа = "";
	Объект.ПреамбулаПриказа = "";
	Объект.ПунктыПриказа.Очистить();
	
	Объект.ШаблонЗаполнения = ШаблонПриказа;
	
	// Получаем реквизиты справочника Шаблон с текстом для заполнения
	ДанныеШаблона = ШаблоныПриказовСервер.ПолучитьДанныеШаблона(ШаблонПриказа);
    ...

//---------------------------------------------
//  Общий модуль ШаблоныПриказовСервер
//---------------------------------------------

// Возвращает данные шаблона, необходимые для заполнения форм
//
// Параметры:
//  Шаблон  - СправочникСсылка.ШаблоныПриказов - шаблон приказа
//
// Возвращаемое значение:
//   Структура   - содержит:
//     * Заголовок        - Строка
//     * Преамбула  - Булево
//     * Пункты  - Массив из строк
//     * Варианты - СписокЗначений - содержит:
//        ** Значение        - Число - порядковый номер пункта
//        ** Представление   - Строка - сожержание варианта
//
Функция ПолучитьДанныеШаблона(Шаблон) Экспорт

	СтруктураДанных = Новый Структура;
	СтруктураДанных.Вставить("Заголовок", 	"");
	СтруктураДанных.Вставить("Преамбула", 	"");
	СтруктураДанных.Вставить("Пункты", 		Новый Массив);
	СтруктураДанных.Вставить("Варианты", 	Новый СписокЗначений);
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ШаблоныПриказов.Заголовок КАК Заголовок,
		|	ШаблоныПриказов.Преамбула КАК Преамбула,
		|	ШаблоныПриказов.Пункты.(
		|		СодержаниеПункта КАК СодержаниеПункта
		|	) КАК ТаблицаПункты,
		|	ШаблоныПриказов.ВариантыПовторяющегосяТекста.(
		|		НомерСтроки КАК НомерСтроки,
		|		СожержаниеВарианта КАК СожержаниеВарианта
		|	) КАК ТаблицаВарианты
		|ИЗ
		|	Справочник.ШаблоныПриказов КАК ШаблоныПриказов
		|ГДЕ
		|	ШаблоныПриказов.Ссылка = &Шаблон";
	
	Запрос.УстановитьПараметр("Шаблон", Шаблон);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если НЕ РезультатЗапроса.Пустой() Тогда
	
		Выборка = РезультатЗапроса.Выбрать();
		Выборка.Следующий();

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

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

Получение шаблона ячейки для заполнения  

Код получения шаблона ячейки для заполнения

//---------------------------------------------
//  Форма документа
//---------------------------------------------
                            
    ...
	// Получаем служебную переменную, чтобы через нее подставлять параметры в шаблон
	ШаблонЯчейкиДляЗаполнения = ШаблоныПриказовСерверПовтИсп.ПолучитьМакетЯчейкиДляЗаполнения();
    ...

//---------------------------------------------
//  Общий модуль ШаблоныПриказовСерверПовтИсп
//---------------------------------------------

Функция ПолучитьМакетЯчейкиДляЗаполнения() Экспорт

	Возврат Справочники.ШаблоныПриказов.ПолучитьМакет("MXL_ШаблонЯчейкиДляЗаполнения");	

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

 
Скриншот макета MXL_ШаблонЯчейкиДляЗаполнения

 
Код получения данных для заполнения параметров

//---------------------------------------------
//  Форма документа
//---------------------------------------------

// Получаем данные, которые будут подставляться в качестве параметров
	ДанныеДляЗаполнения = ШаблоныПриказовСервер.ПолучитьДанныеЗаполненияПоШаблону(Объект.Ссылка);

//---------------------------------------------
//  Общий модуль ШаблоныПриказовСервер
//---------------------------------------------

// Возвращает значения параметров для шаблона приказа
//
// Параметры:
//  ДокументОснование  - ДокументСсылка.ПриказОбОрганизацииПрохожденияПрактики - источник данных
//
// Возвращаемое значение:
//   Структура   - содержит (подробное описание в макете Справочники.ШаблоныПриказов.MXL_ДоступныеПараметры):
//     * Шапка        	- Структура 
//     * ТабличнаяЧасть - Массив структур
//
Функция ПолучитьДанныеЗаполненияПоШаблону(ДокументОснование) Экспорт
	
	СтруктураВозврата = Новый Структура;
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	ДокументОснование.Номер КАК НомерДокумента,
		|	ДокументОснование.Дата КАК ДатаДокумента,
		|	ДокументОснование.Организация КАК Организация,
		|	ДокументОснование.Наставник КАК Наставник,
		|	ДокументОснование.ДолжностьНаставника КАК ДолжностьРуководителяПрактики,
		|	ДокументОснование.Куратор КАК Куратор,
		|	ДокументОснование.ДолжностьКуратора КАК ДолжностьКуратораПрактики,
		|	ДокументОснование.Подписывающий КАК Подписывающий,
		|	ДокументОснование.ДолжностьПодписывающего КАК ДолжностьПодписывающегоПоДокументу,
		|	ДокументОснование.Подразделение КАК Подразделение,
		|	ПРЕДСТАВЛЕНИЕ(ДокументОснование.УчебноеЗаведение) КАК УчебноеЗаведение
		|ПОМЕСТИТЬ ДанныеШапкиДокумента
		|ИЗ
		|	Документ.ПриказОбОрганизацииПрохожденияПрактики КАК ДокументОснование
		|ГДЕ
		|	ДокументОснование.Ссылка = &ДокументОснование
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	ТаблицаПрактиканты.ДатаНачалаПрактики КАК ДатаНачалаПрохожденияПрактики,
		|	ТаблицаПрактиканты.ДатаОкончанияПрактики КАК ДатаОкончанияПрохожденияПрактики,
		|	ТаблицаПрактиканты.ВариантТекста КАК ВариантТекста,
		|	ТаблицаПрактиканты.Практикант КАК Практикант
		|ПОМЕСТИТЬ ДанныеПоПрактикантам
		|ИЗ
		|	Документ.ПриказОбОрганизацииПрохожденияПрактики.Практиканты КАК ТаблицаПрактиканты
		|ГДЕ
		|	ТаблицаПрактиканты.Ссылка = &ДокументОснование
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.Наставник КАК Сотрудник
		|ПОМЕСТИТЬ ТаблицаСотрудников
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.Куратор
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.Подписывающий
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ТаблицаСотрудников.Сотрудник КАК Сотрудник,
		|	ТаблицаСотрудников.Сотрудник.ФизическоеЛицо КАК ФизическоеЛицо
		|ПОМЕСТИТЬ ТаблицаСотрудниковФизЛиц
		|ИЗ
		|	ТаблицаСотрудников КАК ТаблицаСотрудников
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ТаблицаСотрудниковФизЛиц.ФизическоеЛицо КАК ФизическоеЛицо
		|ПОМЕСТИТЬ ТаблицаФизЛиц
		|ИЗ
		|	ТаблицаСотрудниковФизЛиц КАК ТаблицаСотрудниковФизЛиц
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеПоПрактикантам.ФизическоеЛицо
		|ИЗ
		|	ДанныеПоПрактикантам КАК ДанныеПоПрактикантам
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
		|	ТаблицаФизЛиц.ФизическоеЛицо КАК ФизическоеЛицо,
		|	ФизическиеЛица.Наименование КАК Наименование,
		|	ФизическиеЛица.Фамилия + "" "" + ФизическиеЛица.Инициалы КАК ФамилияИнициалы
		|ПОМЕСТИТЬ ТаблицаДанныхФизЛиц
		|ИЗ
		|	ТаблицаФизЛиц КАК ТаблицаФизЛиц
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК ФизическиеЛица
		|		ПО ТаблицаФизЛиц.ФизическоеЛицо = ФизическиеЛица.Ссылка
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ТаблицаСотрудниковФизЛиц.Сотрудник КАК Сотрудник,
		|	ТаблицаСотрудниковФизЛиц.ФизическоеЛицо КАК ФизическоеЛицо,
		|	ТаблицаДанныхФизЛиц.Наименование КАК ФизическоеЛицоНаименование,
		|	ТаблицаДанныхФизЛиц.ФамилияИнициалы КАК ФамилияИнициалы
		|ПОМЕСТИТЬ ТаблицаСотрудникиФизЛицаИДанные
		|ИЗ
		|	ТаблицаСотрудниковФизЛиц КАК ТаблицаСотрудниковФизЛиц
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанныхФизЛиц КАК ТаблицаДанныхФизЛиц
		|		ПО ТаблицаСотрудниковФизЛиц.ФизическоеЛицо = ТаблицаДанныхФизЛиц.ФизическоеЛицо
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|УНИЧТОЖИТЬ ТаблицаСотрудниковФизЛиц
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.ДолжностьРуководителяПрактики КАК Должность
		|ПОМЕСТИТЬ ТаблицаДолжностей
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.ДолжностьКуратораПрактики
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.ДолжностьПодписывающегоПоДокументу
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
		|	ТаблицаДолжностей.Должность КАК Должность,
		|	Должности.Наименование КАК ДолжностьНаименование
		|ПОМЕСТИТЬ ТаблицаДолжностейИДанных
		|ИЗ
		|	ТаблицаДолжностей КАК ТаблицаДолжностей
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Должности КАК Должности
		|		ПО ТаблицаДолжностей.Должность = Должности.Ссылка
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ТаблицаСотрудникиФизЛицаИДанные.ФизическоеЛицо КАК ОбъектСклонения,
		|	ТаблицаСотрудникиФизЛицаИДанные.Сотрудник КАК ИсходныйОбъект,
		|	ТаблицаСотрудникиФизЛицаИДанные.ФизическоеЛицоНаименование КАК ПредставлениеОбъектаСклонения
		|ПОМЕСТИТЬ ТаблицаОбъектовСклоненияСДублями
		|ИЗ
		|	ТаблицаСотрудникиФизЛицаИДанные КАК ТаблицаСотрудникиФизЛицаИДанные
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ДанныеПоПрактикантам.Практикант,
		|	ДанныеПоПрактикантам.Практикант,
		|	ТаблицаДанныхФизЛиц.Наименование
		|ИЗ
		|	ДанныеПоПрактикантам КАК ДанныеПоПрактикантам
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанныхФизЛиц КАК ТаблицаДанныхФизЛиц
		|		ПО ДанныеПоПрактикантам.Практикант = ТаблицаДанныхФизЛиц.ФизическоеЛицо
		|
		|ОБЪЕДИНИТЬ ВСЕ
		|
		|ВЫБРАТЬ
		|	ТаблицаДолжностейИДанных.Должность,
		|	ТаблицаДолжностейИДанных.Должность,
		|	ТаблицаДолжностейИДанных.ДолжностьНаименование
		|ИЗ
		|	ТаблицаДолжностейИДанных КАК ТаблицаДолжностейИДанных
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ТаблицаОбъектовСклоненияСДублями.ОбъектСклонения КАК ОбъектСклонения,
		|	ТаблицаОбъектовСклоненияСДублями.ИсходныйОбъект КАК ИсходныйОбъект,
		|	ТаблицаОбъектовСклоненияСДублями.ПредставлениеОбъектаСклонения КАК ПредставлениеОбъектаСклонения
		|ПОМЕСТИТЬ ТаблицаОбъектовСклонения
		|ИЗ
		|	ТаблицаОбъектовСклоненияСДублями КАК ТаблицаОбъектовСклоненияСДублями
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	ТаблицаОбъектовСклонения.ИсходныйОбъект КАК ИсходныйОбъект,
		|	ЕСТЬNULL(СклоненияПредставленийОбъектов.ИменительныйПадеж, ТаблицаОбъектовСклонения.ПредставлениеОбъектаСклонения) КАК ИменительныйПадеж,
		|	ЕСТЬNULL(СклоненияПредставленийОбъектов.РодительныйПадеж, """") КАК РодительныйПадеж,
		|	ЕСТЬNULL(СклоненияПредставленийОбъектов.ДательныйПадеж, """") КАК ДательныйПадеж
		|ПОМЕСТИТЬ СклоненияОбъектов
		|ИЗ
		|	ТаблицаОбъектовСклонения КАК ТаблицаОбъектовСклонения
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СклоненияПредставленийОбъектов КАК СклоненияПредставленийОбъектов
		|		ПО ТаблицаОбъектовСклонения.ОбъектСклонения = СклоненияПредставленийОбъектов.Объект
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДанныеШапкиДокумента.НомерДокумента КАК НомерДокумента,
		|	ДанныеШапкиДокумента.ДатаДокумента КАК ДатаДокумента,
		|	ДанныеШапкиДокумента.УчебноеЗаведение КАК УчебноеЗаведение,
		|	СклонениеНаставника.ИменительныйПадеж КАК ФамилияИмяОтчествоРуководителяПрактики,
		|	СклонениеНаставника.РодительныйПадеж КАК ФамилияИмяОтчествоРуководителяПрактикиРП,
		|	СклонениеНаставника.ДательныйПадеж КАК ФамилияИмяОтчествоРуководителяПрактикиДП,
		|	ФамилияИнициалыНаставника.ФамилияИнициалы КАК ФамилияИнициалыРуководителяПрактики,
		|	ФамилияИнициалыНаставника.ФамилияИнициалы КАК ФамилияИнициалыРуководителяПрактикиРП,
		|	ФамилияИнициалыНаставника.ФамилияИнициалы КАК ФамилияИнициалыРуководителяПрактикиДП,
		|	СклонениеДолжностиНаставника.ИменительныйПадеж КАК ДолжностьРуководителяПрактики,
		|	СклонениеДолжностиНаставника.РодительныйПадеж КАК ДолжностьРуководителяПрактикиРП,
		|	СклонениеДолжностиНаставника.ДательныйПадеж КАК ДолжностьРуководителяПрактикиДП,
		|	СклонениеКуратора.ИменительныйПадеж КАК ФамилияИмяОтчествоКуратораПрактики,
		|	СклонениеКуратора.РодительныйПадеж КАК ФамилияИмяОтчествоКуратораПрактикиРП,
		|	СклонениеКуратора.ДательныйПадеж КАК ФамилияИмяОтчествоКуратораПрактикиДП,
		|	ФамилияИнициалыКуратора.ФамилияИнициалы КАК ФамилияИнициалыКуратораПрактики,
		|	ФамилияИнициалыКуратора.ФамилияИнициалы КАК ФамилияИнициалыКуратораПрактикиРП,
		|	ФамилияИнициалыКуратора.ФамилияИнициалы КАК ФамилияИнициалыКуратораПрактикиДП,
		|	СклонениеДолжностиКуратора.ИменительныйПадеж КАК ДолжностьКуратораПрактики,
		|	СклонениеДолжностиКуратора.РодительныйПадеж КАК ДолжностьКуратораПрактикиРП,
		|	СклонениеДолжностиКуратора.ДательныйПадеж КАК ДолжностьКуратораПрактикиДП,
		|	СклонениеПодписывающего.ИменительныйПадеж КАК ФамилияИмяОтчествоПодписывающегоПоДокументу,
		|	СклонениеПодписывающего.РодительныйПадеж КАК ФамилияИмяОтчествоПодписывающегоПоДокументуРП,
		|	СклонениеПодписывающего.ДательныйПадеж КАК ФамилияИмяОтчествоПодписывающегоПоДокументуДП,
		|	ФамилияИнициалыПодписывающего.ФамилияИнициалы КАК ФамилияИнициалыПодписывающегоПоДокументу,
		|	ФамилияИнициалыПодписывающего.ФамилияИнициалы КАК ФамилияИнициалыПодписывающегоПоДокументуРП,
		|	ФамилияИнициалыПодписывающего.ФамилияИнициалы КАК ФамилияИнициалыПодписывающегоПоДокументуДП,
		|	СклонениеДолжностиПодписывающего.ИменительныйПадеж КАК ДолжностьПодписывающегоПоДокументу,
		|	СклонениеДолжностиПодписывающего.РодительныйПадеж КАК ДолжностьПодписывающегоПоДокументуРП,
		|	СклонениеДолжностиПодписывающего.ДательныйПадеж КАК ДолжностьПодписывающегоПоДокументуДП
		|ИЗ
		|	ДанныеШапкиДокумента КАК ДанныеШапкиДокумента
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеНаставника
		|		ПО ДанныеШапкиДокумента.НаставникСотрудник = СклонениеНаставника.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеКуратора
		|		ПО ДанныеШапкиДокумента.Куратор = СклонениеКуратора.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеПодписывающего
		|		ПО ДанныеШапкиДокумента.Подписывающий = СклонениеПодписывающего.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеДолжностиНаставника
		|		ПО ДанныеШапкиДокумента.ДолжностьРуководителяПрактики = СклонениеДолжностиНаставника.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеДолжностиКуратора
		|		ПО ДанныеШапкиДокумента.ДолжностьКуратораПрактики = СклонениеДолжностиКуратора.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклонениеДолжностиПодписывающего
		|		ПО ДанныеШапкиДокумента.ДолжностьПодписывающегоПоДокументу = СклонениеДолжностиПодписывающего.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСотрудникиФизЛицаИДанные КАК ФамилияИнициалыНаставника
		|		ПО ДанныеШапкиДокумента.НаставникСотрудник = ФамилияИнициалыНаставника.Сотрудник
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСотрудникиФизЛицаИДанные КАК ФамилияИнициалыКуратора
		|		ПО ДанныеШапкиДокумента.Куратор = ФамилияИнициалыКуратора.Сотрудник
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСотрудникиФизЛицаИДанные КАК ФамилияИнициалыПодписывающего
		|		ПО ДанныеШапкиДокумента.Подписывающий = ФамилияИнициалыПодписывающего.Сотрудник
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДанныеПоПрактикантам.ДатаНачалаПрохожденияПрактики КАК ДатаНачалаПрохожденияПрактики,
		|	ДанныеПоПрактикантам.ДатаОкончанияПрохожденияПрактики КАК ДатаОкончанияПрохожденияПрактики,
		|	ДанныеПоПрактикантам.ВариантТекста КАК ВариантТекста,
		|	ДанныеПоПрактикантам.УчебноеЗаведениеПрактиканта КАК УчебноеЗаведениеПрактиканта,
		|	СклоненияОбъектов.ИменительныйПадеж КАК ФамилияИмяОтчествоПрактиканта,
		|	СклоненияОбъектов.РодительныйПадеж КАК ФамилияИмяОтчествоПрактикантаРП,
		|	СклоненияОбъектов.ДательныйПадеж КАК ФамилияИмяОтчествоПрактикантаДП,
		|	ТаблицаДанныхФизЛиц.ФамилияИнициалы КАК ФамилияИнициалыПрактиканта,
		|	ТаблицаДанныхФизЛиц.ФамилияИнициалы КАК ФамилияИнициалыПрактикантаРП,
		|	ТаблицаДанныхФизЛиц.ФамилияИнициалы КАК ФамилияИнициалыПрактикантаДП
		|ИЗ
		|	ДанныеПоПрактикантам КАК ДанныеПоПрактикантам
		|		ЛЕВОЕ СОЕДИНЕНИЕ СклоненияОбъектов КАК СклоненияОбъектов
		|		ПО ДанныеПоПрактикантам.ФизическоеЛицо = СклоненияОбъектов.ИсходныйОбъект
		|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаДанныхФизЛиц КАК ТаблицаДанныхФизЛиц
		|		ПО ДанныеПоПрактикантам.ФизическоеЛицо = ТаблицаДанныхФизЛиц.ФизическоеЛицо";
	
	Запрос.УстановитьПараметр("ДокументОснование", 	ДокументОснование);
	
	РезультатыЗапроса = Запрос.ВыполнитьПакет();
	
	СтруктураВозврата = ДополнитьДанныеЗаполненияПоШаблону(РезультатыЗапроса);
	
	Возврат СтруктураВозврата;
	
КонецФункции

// Дополняет данные заполнения склонениями фамилии с инициалами
//
// Параметры:
//  РезультатЗапроса  - РезультатЗапроса - см. функцию ПолучитьДанныеЗаполненияПоШаблону
//
// Возвращаемое значение:
//   Структура   - содержит:
//		* Шапка - Структура данных "шапки" документа
//		* ТабличнаяЧасть - Массив структур данных табличной части документа
//
Функция ДополнитьДанныеЗаполненияПоШаблону(РезультатыЗапроса)

	НаибольшийИндекс = РезультатыЗапроса.ВГраница();
	
	ТаблицаШапки = РезультатыЗапроса[НаибольшийИндекс - 1].Выгрузить();
	
	СтруктураШапки 		= Неопределено;
	МассивСтруктурТЧ 	= Новый Массив;
	
	Если ТаблицаШапки.Количество() <> 0 Тогда
		
		ЗаполнитьСклоненияВСтроке(ТаблицаШапки[0], ТаблицаШапки.Колонки);
		СтруктураШапки = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(ТаблицаШапки[0]);
	
	КонецЕсли;
	
	ТаблицаТабличнойЧасти = РезультатыЗапроса[НаибольшийИндекс].Выгрузить();
	
	Для каждого Строка Из ТаблицаТабличнойЧасти Цикл
	
		ЗаполнитьСклоненияВСтроке(Строка, ТаблицаТабличнойЧасти.Колонки);
		СтруктураСтроки = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Строка);
		МассивСтруктурТЧ.Добавить(СтруктураСтроки);
	
	КонецЦикла;
	
	СтруктураВозврата = Новый Структура;
	СтруктураВозврата.Вставить("Шапка", 			СтруктураШапки);
	СтруктураВозврата.Вставить("ТабличнаяЧасть", 	МассивСтруктурТЧ);
	
	Возврат СтруктураВозврата;

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



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

Код склонения полей содержащих фамилию с инициалами


//---------------------------------------------
//  Общий модуль ШаблоныПриказовСервер
//---------------------------------------------

Процедура ЗаполнитьСклоненияВСтроке(СтрокаТаблицы, Колонки)

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

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

Функция ЭтоКолонкаФамилияИнициалыСоСклонением(ИмяКолонки)

	Результат = Ложь;
	
	Если СтрНайти(ИмяКолонки, "Инициалы") <> 0
		И (Прав(ИмяКолонки, 2) = "РП" ИЛИ Прав(ИмяКолонки, 2) = "ДП") Тогда
	
		Результат = Истина;	
	
	КонецЕсли;
	
	Возврат Результат;

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

Функция ПолучитьПадеж(ИмяКолонки)

	Если Прав(ИмяКолонки, 2) = "РП" Тогда // Родительный
	
		Возврат 2;	
	
	ИначеЕсли Прав(ИмяКолонки, 2) = "ДП" Тогда // Дательный
	
		Возврат 3;	
	
	Иначе // Тогда именительный
		
		Возврат 1;
		
	КонецЕсли;	

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


Затем идет подстановка параметров в шаблон и заполнение полей документа, отвечающих за «предварительный просмотр» печатной формы.

Код заполнения параметров шаблона

//---------------------------------------------
//  Форма документа
//---------------------------------------------
                            
    ...
	// Заполнение параметров Заголовка и Преамбулы
	Если ДанныеДляЗаполнения.Шапка <> Неопределено Тогда
	
		Объект.ЗаголовокПриказа = ШаблоныПриказовСервер.ПолучитьЗаполненныйТекст(ШаблонЯчейкиДляЗаполнения, ДанныеШаблона.Заголовок, ДанныеДляЗаполнения.Шапка); 
															
		Объект.ПреамбулаПриказа = ШаблоныПриказовСервер.ПолучитьЗаполненныйТекст(ШаблонЯчейкиДляЗаполнения, ДанныеШаблона.Преамбула, ДанныеДляЗаполнения.Шапка);
		
	КонецЕсли;
	
	// Заполнение параметрами Пунктов шаблона
	Для каждого СтрокаПункта Из ДанныеШаблона.Пункты Цикл
	
		// Найдем в тексте повторяющийся текст (в фигурных скобках), вырежем его и на его место поставим "метку"
		МассивПовторяющихсяБлоков = Новый Массив; // Повторяющихся блоков может быть несколько
		ШаблоныПриказовСервер.ПоискВыделениеПовторяющегосяТекста(СтрокаПункта, МассивПовторяющихсяБлоков, ДанныеШаблона.Варианты);
		
		// Заполним повторяющийся текст параметрами из табличной части документа
		Если МассивПовторяющихсяБлоков.Количество() > 0 Тогда
			
			Для каждого Блок Из МассивПовторяющихсяБлоков Цикл
				
				// Заменим в повторяющемся тексте тэги разделения блоков
				ШаблоныПриказовСервер.ПодставитьТэгиПереноса(Блок.ТекстБлока);
				
				ГотовыйТекстБлока = "";
				
				Для каждого СтрокаТаблицы Из ДанныеДляЗаполнения.ТабличнаяЧасть Цикл
					
					Если СтрокаТаблицы.ВариантТекста
						<> Блок.НомерВарианта Тогда
					
						Продолжить;	
					
					КонецЕсли;
					
					ФрагментТекста = ШаблоныПриказовСервер.ПолучитьЗаполненныйТекст(ШаблонЯчейкиДляЗаполнения, Блок.ТекстБлока, СтрокаТаблицы, ДанныеДляЗаполнения.Шапка);
																				
					ГотовыйТекстБлока = ГотовыйТекстБлока + ФрагментТекста;
				
				КонецЦикла;
				
				// Вернем повторяющийся текст на место "метки"
				СтрокаПункта = СтрЗаменить(СтрокаПункта, Блок.МеткаБлока, ГотовыйТекстБлока);
				
			КонецЦикла;
			
		КонецЕсли;
			
		СтрокаПункта = ШаблоныПриказовСервер.ПолучитьЗаполненныйТекст(ШаблонЯчейкиДляЗаполнения, СтрокаПункта, ДанныеДляЗаполнения.Шапка);	
		
		Строка = Объект.ПунктыПриказа.Добавить();
		Строка.СодержаниеПункта = СтрокаПункта;
	
	КонецЦикла;

//---------------------------------------------
//  Общий модуль ШаблоныПриказовСервер
//---------------------------------------------

// Заполняет параметры в табличном документе и возвращает готовый текст
//
// Параметры:
//  ШаблонЯчейки  - ТабличныйДокумент - макет ячейки
//					(см. ШаблоныПриказовСерверПовтИсп.ПолучитьМакетЯчейкиДляЗаполнения)
//  ТекстСПараметрами  - Строка - шаблон текста, содержащий параметры в квадратных скобках
//
//  ИсточникЗаполнения  - Структура  - источник основных данных для заполнения
//
//  ДополнительныйИсточникЗаполнения  - Структура  - необязательный
//														источник дополнительных данных для заполнения
//
// Возвращаемое значение:
//   Строка   - текст с заполненными параметрами
//
Функция ПолучитьЗаполненныйТекст(ШаблонЯчейки, ТекстСПараметрами, ИсточникЗаполнения,
										ДополнительныйИсточникЗаполнения = Неопределено) Экспорт

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

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

// Ищет в строке шаблона текста тэги повторяющегося текста.
//	Если тэги есть, то заменяет их маркерами и
//	дополняет массив МассивПовторяющихсяБлоков
//
// Параметры:
//  СтрокаШаблона  - Строка - шаблон текста пункта приказа
//
//  МассивПовторяющихсяБлоков  - Массив - заполняется структурами:
//     					* ТекстБлока - Строка - строка с параметрами
//     					* МеткаБлока - Строка - особая метка вида #Метка<Номер>
//     					* НомерВарианта  - Число - порядковый номер варианта в шаблоне приказа
//
//  СписокВариантов  - СписокЗначений - см. ШаблоныПриказовСервер.ПолучитьДанныеШаблона
//
Процедура ПоискВыделениеПовторяющегосяТекста(СтрокаШаблона, МассивПовторяющихсяБлоков, СписокВариантов) Экспорт

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

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

// Заменяет в строке служебные параметры на их значения.
//	см. ШаблоныПриказовСерверПовтИсп.ПолучитьМакетДоступныхПараметров
//
// Параметры:
//  СтрокаБлока  - Строка - шаблон повторяющего текста
//
Процедура ПодставитьТэгиПереноса(СтрокаБлока) Экспорт

	СтрокаБлока = СтрЗаменить(СтрокаБлока, "#ТочкаЗапятая", "; ");	
	СтрокаБлока = СтрЗаменить(СтрокаБлока, "#ПереносСтроки", Символы.ПС);	

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


Теперь пользователь может редактировать полученный текст с заполненными параметрами и отправлять документ на печать.

Рассмотрим процесс одной из печатных форм (Для хранения Бланков был разработан отдельный справочник, т.к. он использовался еще в других подсистемах разработки. Для упрощения можно использовать функционал Присоединенных файлов)

Код печати Приказа об организации прохождения практики

//---------------------------------------------
//  Модуль менеджера документа
//---------------------------------------------

// Формирует печатные формы.
//
// Параметры:
//  МассивОбъектов  - Массив    - ссылки на объекты, которые нужно распечатать;
//  ПараметрыПечати - Структура - дополнительные настройки печати;
//  КоллекцияПечатныхФорм - ТаблицаЗначений - сформированные табличные документы (выходной параметр),
//                                            см. УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм.
//  ОбъектыПечати         - СписокЗначений  - значение - ссылка на объект;
//                                            представление - имя области в которой был выведен объект (выходной
//                                                            параметр);
//  ПараметрыВывода       - Структура       - дополнительные параметры сформированных табличных документов (выходной
//                                            параметр).
//
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

	// печать Приказ об организации прохождения практики
	ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ПриказОбОрганизацииПрохожденияПрактики");
	Если ПечатнаяФорма <> Неопределено Тогда
		
		ИмяМакета = "ПриказОбОрганизацииПрохожденияПрактики";
		МакетИДанныеОбъекта = УправлениеПечатьюВызовСервера.МакетыИДанныеОбъектовДляПечати(
													"Документ.ПриказОбОрганизацииПрохожденияПрактики",
													ИмяМакета,
													МассивОбъектов);
		
		ОфисныеДокументы = Новый Соответствие;
		
		Шаблон = НСтр("ru = 'Приказ об организации прохождения практики №[Номер] от [Дата]'");
		ЗначенияРеквизитовДокументов = ОбщегоНазначения.ЗначенияРеквизитовОбъектов(МассивОбъектов, "Номер, Дата, Ссылка");
		Для Каждого Ссылка Из МассивОбъектов Цикл
			
			ЗначенияРеквизитовДокумента = ЗначенияРеквизитовДокументов[Ссылка];
			ЗначенияРеквизитовДокумента.Дата = Формат(ЗначенияРеквизитовДокумента.Дата, "ДЛФ=D");
			ЗначенияРеквизитовДокумента.Номер = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(
																					ЗначенияРеквизитовДокумента.Номер);
			ИмяДокумента = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ЗначенияРеквизитовДокументов[Ссылка]);
			
			АдресХранилищаОфисныйДокумент = ПодготовитьДокументПриказ(Ссылка,
																		МакетИДанныеОбъекта,
																		ИмяМакета);
			
			ОфисныеДокументы.Вставить(АдресХранилищаОфисныйДокумент, ИмяДокумента);
			
		КонецЦикла;
		
		ПечатнаяФорма.СинонимМакета    = НСтр("ru = 'Приказ об организации прохождения практики'");
		ПечатнаяФорма.ОфисныеДокументы = ОфисныеДокументы;
		
	КонецЕсли;
	
КонецПроцедуры

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

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

Функция ПолучитьДанныеПриказа(ОбъектСсылка)

	СтруктураДанных = Новый Структура;
	СтруктураДанных.Вставить("БланкДвоичныеДанные",	Неопределено);
	СтруктураДанных.Вставить("Шапка", 				Неопределено);
	СтруктураДанных.Вставить("ТабличнаяЧасть", 		Новый Массив);
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	Приказ.Номер КАК Номер,
		|	Приказ.Дата КАК Дата,
		|	Приказ.ЗаголовокПриказа КАК ТекстЗаголовока,
		|	Приказ.ПреамбулаПриказа КАК ТекстПреамбулы,
		|	Приказ.Организация КАК Организация,
		|	Приказ.Подразделение КАК Подразделение
		|ПОМЕСТИТЬ ДанныеДокумента
		|ИЗ
		|	Документ.ПриказОбОрганизацииПрохожденияПрактики КАК Приказ
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК ФизическиеЛица
		|		ПО Приказ.Подписывающий.ФизическоеЛицо = ФизическиеЛица.Ссылка
		|ГДЕ
		|	Приказ.Ссылка = &ОбъектСсылка
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	Бланки.Файл КАК Файл
		|ИЗ
		|	Справочник.БланкиПриказовПисем КАК Бланки
		|ГДЕ
		|	Бланки.ТипБланка = ЗНАЧЕНИЕ(Перечисление.ТипыБланков.Приказ)
		|	И (Бланки.Организация, Бланки.Подразделение) В
		|			(ВЫБРАТЬ
		|				ДанныеДокумента.Организация КАК Организация,
		|				ДанныеДокумента.Подразделение КАК Подразделение
		|			ИЗ
		|				ДанныеДокумента КАК ДанныеДокумента)
		|	И Бланки.Файл <> ЗНАЧЕНИЕ(Справочник.БланкиПриказовПисемПрисоединенныеФайлы.ПустаяСсылка)
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ДанныеДокумента.Номер КАК Номер,
		|	ДанныеДокумента.Дата КАК Дата,
		|	ДанныеДокумента.ТекстЗаголовока КАК ТекстЗаголовока,
		|	ДанныеДокумента.ТекстПреамбулы КАК ТекстПреамбулы
		|ИЗ
		|	ДанныеДокумента КАК ДанныеДокумента
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	Приказ.СодержаниеПункта КАК ТекстПункта
		|ИЗ
		|	Документ.ПриказОбОрганизацииПрохожденияПрактики.ПунктыПриказа КАК Приказ
		|ГДЕ
		|	Приказ.Ссылка = &ОбъектСсылка
		|
		|УПОРЯДОЧИТЬ ПО
		|	Приказ.НомерСтроки";
	
	Запрос.УстановитьПараметр("ОбъектСсылка", ОбъектСсылка);
	
	РезультатыЗапроса = Запрос.ВыполнитьПакет();
	ГраницаРезультатов = РезультатыЗапроса.ВГраница();
	
	Если РезультатыЗапроса[ГраницаРезультатов - 1].Пустой() Тогда
	
		Возврат СтруктураДанных;
	
	КонецЕсли;
	
	ТаблицаДанных = РезультатыЗапроса[ГраницаРезультатов - 1].Выгрузить();
	
	СтруктураДанных.Шапка = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(ТаблицаДанных[0]);
	СтруктураДанных.Шапка.Дата = Формат(СтруктураДанных.Шапка.Дата, "ДЛФ=DD");
	СтруктураДанных.Шапка.Номер = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(СтруктураДанных.Шапка.Номер);
	
	ТаблицаДанных = РезультатыЗапроса[ГраницаРезультатов].Выгрузить();
	
	Для каждого Строка Из ТаблицаДанных Цикл
	
		СтруктураДанных.ТабличнаяЧасть.Добавить(ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Строка));	
	
	КонецЦикла;
	 
	Если НЕ РезультатыЗапроса[ГраницаРезультатов - 2].Пустой() Тогда
	
		Выборка = РезультатыЗапроса[ГраницаРезультатов - 2].Выбрать();
		Выборка.Следующий();
		
		СтруктураДанных.БланкДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(Выборка.Файл);
		
	КонецЕсли; 
	
	Возврат СтруктураДанных;
	
КонецФункции

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

//---------------------------------------------
//  Общий модуль ШаблоныПриказовСерверПовтИсп
//---------------------------------------------

Функция ПолучитьСоответствиеИменМакетовИПутей() Экспорт

	Соответствие = Новый Соответствие;
	
	Соответствие.Вставить("ПриказОбОрганизацииПрохожденияПрактики",
		"Справочник.ШаблоныПриказов.DOC_ПриказОбОрганизацииПрохожденияПрактики");
	
	// Тут должны быть еще шаблоны, но для примера хватит и одного
	
	Возврат Соответствие;
	
КонецФункции

Бурмистров.png
Статью подготовил старший разработчик 1С «ИнфоСофт» Бурмистров Алексей.
Статья опубликована на портале ИнфоСтарт