Подключаемые печатные формы с .DOCX макетом без Word'а

Печать - Печатные формы документов

обработка word docx печатнаяформа макет печать внешняя обработка зуп

18
Данная обработка является подключаемой печатной формой в docx, своего рода шаблоном для удобного и быстрого выпуска новых печатных форм на основе docx макета. При этом не требуется установленный word.

ДЛЯ ЧЕГО/КОМУ ЭТО НУЖНО:

Если в вашей компании есть некий корпоративный стиль, дизайнеры и их не устраивает как выглядят ваши отчеты сверстаные на табличных документах в 1с - они могут вам предложить использовать другой выходной формат. Первыми на ум приходит pdf, html и word.

  1. pdf макеты не очень удобны в редактировании.
  2. html это скорее для вебсервисов и отчетов на почту.
  3. Остается word.

Эта обработка призвана послужить шаблоном для создания подключаемой печатной формы с участием docx макета, при этом не используя COMОбъект("Word.Application").

Она может может выдавать Word документ ко всем выделенным через CTRL || SHIFT объектам. Параметры задаются на макете довольно просто - выделяются определенным цветом, а также потдерживается обращение через точку прям в макете: Сотрудник.ФизическоеЛицо.Фамилия  (в будующем планирую добавить возможность склонения и форматирования параметра прям в макете). В обработку без изменений включена функция daСклонение, за что огромное спасибо её создателю - Михаилу Андропову, её создателю.

 

ЕСЛИ ЛЕНЬ ЧИТАТЬ И НАДО ДЕЛАТЬ:

  1. Изменяете имя и синоним обработки
  2. Изменяете тип данных реквизита СсылкаНаОбъект
  3. Заменяете макет макет_docx своим docx макетом, где фон параметров выделен цветом RED
  4. В модуле объекта редактируете процедуру ПолучитьПараметрыЗаполнения под себя (возвращает структуру, где ключи соответсвуют названиям параметров в макете.
  5. Сохраняете, пользуете, you are looking sweet now *__*

 

ЧТО К ЧЕМУ:

В обработке, в модуле объекта есть две процедуры и функции, с которых следует начать её рассмотрение

  • ПолучитьИнформациюОбОбработке

Функция возвращает структуру со всеми необходимыми значениями для подключения её как дополнительной обработки.

Все данные берутся из метаданных обработки (Имя, Синоним, Комментарий), Назначение обработки берется из массива типов реквизита СсылкаНаОбъект (в публикации это Справочник.Сотрудники и Документ.Увольнение)

 

  • ПолучитьПараметрыЗаполнения

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

 

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

  1. Типовой механизм БСП получает информацию об обработке из экспортной функции СведенияОВнешнейОбработке()
  2. Запускает на клиенте в модуле основной формы экспортную процедуру Печать
  3. Процедура обращается на сервер и запускает функцию модуля объекта СформироватьДокументы (возвращает массив двоичных данных для сохранения на клиенте)
  4. Получаем данные для заполнения печатной формы из функции ПолучитьПараметрыЗаполнения
  5. Начинаем заполнение макета в функции возвращающей двоичные данные и имя документа - ЗаполнитьМакет
  6. Извлекаем макет в папку с временными файлами (разархивируя docx на составные xml файлы)
  7. Перебираем полученные xml файлы в поисках параметров, разбирая DOM с помощью разыменователя и выражения XPath "descendant::w:r/w:rPr/w:highlight[@w:val='{ВАШ ЦВЕТ}']/../../w:t"
  8. Найденные узлы с параметрами макета заполняем из созданой ранее структуры с параметрами.
  9. Собираем назад docx документ из xml файлов.
  10. Отдаем данные на клиент, сохраняем во временные файлы, открываем.

Возможно это звучит несколько запутано, но по факту вам требуется лишь сделать необходимые запросы в функции ПолучитьПараметрыЗаполнения и вернуть результат в структуре с параметры совпадающими с параметрами макета. Параметры макета должны быть выделены цветом (в моем случае это RED, ну или другим удобным вам способом, в этом случае измените выражение XPath). 

Весь код открыт, пока разрабатывалось только под управляемые формы, но не вижу проблем переделать под legacy.

Внешних зависимостей быть не должно, испытывалось на версии 8.3.10, по сути должно работать из более ранней, но Я большой любитель СтрШаблон() и СтрРазделить() - в будующем постараюсь заменить их на скопированные из общего модуля БСП СтроковыеФункцииКлиентСервер.

 

UPD: К сожалению Инфостарт не дает бесплатно выложить обработку, поэтому прикрепляю листинг (ну или напишите мне):

 
 Сниппет модуля формы

//////////////////////////////////////////////////////////////
#Область Объявление_констант

#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область При_открытии

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	ЗаполнитьПоУмолчанию();
КонецПроцедуры  // ПриСозданииНаСервере()

&НаСервере
Процедура ЗаполнитьПоУмолчанию()
	Попытка
		Запрос	= Новый Запрос(СтрШаблон(
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1 Ссылка ИЗ %1"
		, Метаданные.НайтиПотипу(РеквизитФормыВЗначение("Объект").Метаданные().Реквизиты.СсылкаНаОбъект.Тип.Типы()[0]).ПолноеИмя()));
		Выборка	= Запрос.Выполнить().Выбрать();
		Если Не Выборка.Количество() Тогда Возврат КонецЕсли;
		Выборка.Следующий();
		Объект.СсылкаНаОбъект	= Выборка.Ссылка;
	Исключение
	КонецПопытки;
КонецПроцедуры  // ЗаполнитьПоУмолчанию()

#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Сформировать_документ
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, МассивОбъектов = Неопределено) Экспорт	
	Если ТипЗнч(ИдентификаторКоманды) = Тип("КомандаФормы") И (Объект.СсылкаНаОбъект = Неопределено Или Объект.СсылкаНаОбъект.Пустая()) Тогда
		// Если Печать вызвана из формы обработки, но СсылкаНаОбъект не заполнена
		Сообщение		= Новый СообщениеПользователю;
		Сообщение.Текст	= "Заполните данный реквизит.";
		Сообщение.Поле	= "Объект.СсылкаНаОбъект";
		Сообщение.УстановитьДанные(Объект.СсылкаНаОбъект);		
		Сообщение.Сообщить();
		Возврат;		 
	ИначеЕсли ТипЗнч(ИдентификаторКоманды) = Тип("КомандаФормы") Тогда
		// Если Печать вызвана из формы обработки
		МассивОбъектов	= Новый Массив;
		МассивОбъектов.Добавить(Объект.СсылкаНаОбъект);		
	ИначеЕсли ТипЗнч(МассивОбъектов) = Тип("Массив") И МассивОбъектов.Количество() Тогда
		// Если Печать вызвана из модуля объекта (подключаемая печатная форма)
				
	Иначе
		// Такого быть не должно
		ВызватьИсключение "Команда формы ""Печать"" вызвана не из модуля объекта и не по кнопке.";
		Возврат;
	КонецЕсли;
	МассивДокументов	= ПечатьНаСервере(МассивОбъектов);
	Если ТипЗнч(МассивДокументов) <> Тип("Массив") Или Не МассивДокументов.Количество() Тогда Возврат КонецЕсли;
	ВыбратьКаталогЗаписиФайлов(МассивДокументов);
КонецПроцедуры  // Печать()

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

// ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~
#Область Сохранить_файлы_на_диск
&НаКлиенте
Процедура ВыбратьКаталогЗаписиФайлов(МассивДокументов)
	ДополнительныеПараметры					= Новый Структура("МассивДокументов", МассивДокументов);
	
	ВыбранныеКаталоги						= Новый Массив;
	ВыбранныеКаталоги.Добавить(КаталогВременныхФайлов());
	
	// Вариант сохраненния во "временные файлы" (Папка %temp% в Windows)
	СохранитьФайлыВКаталог(ВыбранныеКаталоги, ДополнительныеПараметры);	
	Возврат;
	
	// Вариант выбора каталога пользователем 	
	Режим									= РежимДиалогаВыбораФайла.ВыборКаталога;
	ДиалогВыбораКаталога					= Новый ДиалогВыбораФайла(Режим);
	ДиалогВыбораКаталога.Заголовок			= СокрЛП("Выберите путь для сохранения файл" + ?(МассивДокументов.Количество()>1, "ов", "а"));
	ДиалогВыбораКаталога.МножественныйВыбор	= Ложь;
	ДиалогВыбораКаталога.ПолноеИмяФайла		= "";
	ДиалогВыбораКаталога.Каталог			= "";
	ДиалогВыбораКаталога.Расширение			= "";
	ОписаниеОповещения						= Новый ОписаниеОповещения("СохранитьНаДискФайлЗаписьФайла"
												, ЭтаФорма
												, ДополнительныеПараметры);
	ДиалогВыбораКаталога.Показать(ОписаниеОповещения);	
КонецПроцедуры  // ВыбратьКаталогЗаписиФайлов()

&НаКлиенте
Процедура СохранитьФайлыВКаталог(ВыбранныеКаталоги, ДополнительныеПараметры) Экспорт
	Если ТипЗнч(ВыбранныеКаталоги) <> Тип("Массив")
	Или ВыбранныеКаталоги.Количество() <> 1 
	Или ТипЗнч(ДополнительныеПараметры) <> Тип("Структура")
	Или Не ДополнительныеПараметры.Свойство("МассивДокументов")
	Или ТипЗнч(ДополнительныеПараметры.МассивДокументов) <> Тип("Массив")
	Или Не ДополнительныеПараметры.МассивДокументов.Количество() 
	Тогда Возврат КонецЕсли;

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


//////////////////////////////////////////////////////////////
#Область Заполнение_констант

#КонецОбласти
//////////////////////////////////////////////////////////////
 
 Сниппет модуля объекта

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда


//////////////////////////////////////////////////////////////
#Область Объявление_переменных
Перем ЦветВыделенияПараметров;
#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Основная_информация_об_обработке
// ОСНОВНАЯ ИНФОРМАЦИЯ НАЧАЛО 
Функция ПолучитьИнформациюОбОбработке() Экспорт
	Инф								= Новый Структура;
	// Наименование обработки (имя для регистрации в справочнике внешних отчетов и обработок)
	Инф.Вставить("Наименование",	Метаданные().Синоним);
	// Идентификатор без пробелов и знаков препинания
	Инф.Вставить("Идентификатор",	Метаданные().Имя);				
	// Дополнительная информация
	Инф.Вставить("Информация",		СтрЗаменить(СтрШаблон("%1 %2 (%3 г.)", Метаданные().Синоним, Метаданные().Комментарий, Формат(ТекущаяДата(), "ДФ='d MMM yyyy'")), "  ", " "));
	// Версия для удобства версирования (1.0, 1.1, и т.д.)
	Инф.Вставить("Версия",			Метаданные().Комментарий);
	// Варианты: "ДополнительнаяОбработка", "ДополнительныйОтчет", "ЗаполнениеОбъекта", "Отчет", "ПечатнаяФорма", "СозданиеСвязанныхОбъектов"
	Инф.Вставить("Вид",				"ПечатнаяФорма");
	// в безопасном режиме не доступна COM технология, загрузка внешних компонент, доступ к файловой системе, доступ к Интернету.
	Инф.Вставить("БезопасныйРежим", Ложь);
	// Использование. Варианты: "ОткрытиеФормы", "ВызовКлиентскогоМетода", "ВызовСерверногоМетода"	
	Инф.Вставить("Использование",	"ВызовКлиентскогоМетода");
	// Показывать оповещение. Варианты Истина, Ложь	
	Инф.Вставить("Оповещение",		Истина);
	// Модификатор	
	Инф.Вставить("Модификатор",		""); 	
	// Указываем назначение к которому делаем внешнюю печ. форму
	МассивНазначений	= Новый Массив;
	УказанныеТипы		= ЭтотОбъект.Метаданные().Реквизиты.СсылкаНаОбъект.Тип.Типы();	// Возьмем типы из реквизита "СсылкаНаОбъект"
	Для Каждого УказанныйТип ИЗ УказанныеТипы Цикл
		ОбъектМетаданных = Метаданные.НайтиПотипу(УказанныйТип);
		Если ОбъектМетаданных = Неопределено Тогда Продолжить; КонецЕсли;
		МассивНазначений.Добавить(ОбъектМетаданных.ПолноеИмя());		
	КонецЦикла;
	Инф.Вставить("Назначение",		МассивНазначений);
	Возврат Инф;	
КонецФункции  // ПолучитьИнформациюОбОбработке()
// ОСНОВНАЯ ИНФОРМАЦИЯ КОНЕЦ

// ПОДГОТОВКА РЕГИСТРАЦИИ НАЧАЛО
// ВСЕ ДАННЫЕ ПО РЕГИСТРАЦИИ ЗАПОЛНЯЮТСЯ В ФУНКЦИИ ПолучитьИнформациюОбОбработке() 
Функция СведенияОВнешнейОбработке() Экспорт 
	Инф						= ПолучитьИнформациюОбОбработке();
	ТаблицаКоманд			= ПолучитьТаблицуКоманд();	
	ПараметрыРегистрации	= Новый Структура;
	МассивНазначений		= Новый Массив;	
	Если Инф.Свойство("Назначение") И ТипЗнч(Инф.Назначение) = Тип("Массив") Тогда
		МассивНазначений = Инф.Назначение;	
	ИначеЕсли Инф.Свойство("Назначение") И ТипЗнч(Инф.Назначение) = Тип("Строка") И Не ПустаяСтрока(Инф.Назначение) Тогда 
		МассивНазначений.Добавить(Инф.Назначение);
	КонецЕсли;	
	ПараметрыРегистрации.Вставить("Назначение",			МассивНазначений);
	ПараметрыРегистрации.Вставить("Вид",				Инф.Вид);	 
	ПараметрыРегистрации.Вставить("Наименование",		Инф.Наименование); 
	ПараметрыРегистрации.Вставить("Версия",				Инф.Версия); 
	ПараметрыРегистрации.Вставить("БезопасныйРежим",	Инф.БезопасныйРежим); 
	ПараметрыРегистрации.Вставить("Информация",			Инф.Информация);
	ДобавитьКоманду(ТаблицаКоманд, 
		Инф.Наименование, 
		Инф.Идентификатор, 
		Инф.Использование,	  
		Инф.Оповещение, 
		Инф.Модификатор);
	ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
	Возврат ПараметрыРегистрации;
КонецФункции  // СведенияОВнешнейОбработке()
Функция ПолучитьТаблицуКоманд()
	Команды	= Новый ТаблицаЗначений; 
	Команды.Колонки.Добавить("Представление",			Новый ОписаниеТипов("Строка")); 
	Команды.Колонки.Добавить("Идентификатор",			Новый ОписаниеТипов("Строка")); 
	Команды.Колонки.Добавить("Использование",			Новый ОписаниеТипов("Строка")); 
	Команды.Колонки.Добавить("ПоказыватьОповещение",	Новый ОписаниеТипов("Булево")); 
	Команды.Колонки.Добавить("Модификатор",				Новый ОписаниеТипов("Строка"));
	Возврат Команды; 
КонецФункции  // ПолучитьТаблицуКоманд()
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
	НоваяКоманда						= ТаблицаКоманд.Добавить(); 
	НоваяКоманда.Представление			= Представление; 
	НоваяКоманда.Идентификатор			= Идентификатор; 
	НоваяКоманда.Использование			= Использование; 
	НоваяКоманда.ПоказыватьОповещение	= ПоказыватьОповещение; 
	НоваяКоманда.Модификатор			= Модификатор;
КонецПроцедуры  // ДобавитьКоманду()
// ПОДГОТОВКА РЕГИСТРАЦИИ КОНЕЦ 
#КонецОбласти
//////////////////////////////////////////////////////////////


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

Функция ПолучитьИмяДокумента(СсылкаНаОбъект)
	Шаблон			= СтрШаблон("%1 %2 %3.%4"
					, ПолучитьИнформациюОбОбработке().Наименование
					, Строка(СсылкаНаОбъект)
					, Формат(ТекущаяДата(), "ДФ=yyyy-MM-dd")
					, "docx");
	ИмяДокумента	= "";
	Для Итератор = 1 По СтрДлина(Шаблон) Цикл
		КодСимвола		= КодСимвола(Шаблон, Итератор);
		Если (КодСимвола > 1039 И КодСимвола < 1104)
		Или (КодСимвола > 64 И КодСимвола < 91)
		Или (КодСимвола > 96 И КодСимвола < 123)
		Или (КодСимвола > 47 И КодСимвола < 58)
		Или КодСимвола = 32 
		Или КодСимвола = 46 Тогда
			Символ	= Сред(Шаблон, Итератор, 1);
		Иначе
			Символ	= " ";
		КонецЕсли;
		ИмяДокумента	= ИмяДокумента + Символ; 	
	КонецЦикла;
	Возврат ИмяДокумента;		
КонецФункции  // ПолучитьИмяДокумента()
#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Получить_параметры_макета
// ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~
//					Получить параметры заполнения 
// ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~
// Функция формирует данные для заполнения макета по передаваемой ссылки на объект
//
// Функция возвращает:
//	Структура		- содержит исходные данные для дальнейшего заполнения макета
//	Неопределено	- в случае если нечто пошло не по плану 
//
// Параметры:
//	СсылкаНаОбъект	- [обязательный](Ссылка) параметром передается ссылка на объект
Функция ПолучитьПараметрыЗаполнения(СсылкаНаОбъект)
	ПараметрыЗаполнения	= Новый Структура;
	ОтладочнаяИнформация(СтрШаблон("Передана ссылка на объект: %1 (%2)", СсылкаНаОбъект, ТипЗнч(СсылкаНаОбъект)));
	
	// Если объект не является Сотрудником, 
	//  то попробуем найти в объекте сотрудника
	Если ТипЗнч(СсылкаНаОбъект) <> Тип("СправочникСсылка.Сотрудники") Тогда
		Сотрудник	= Неопределено;
		Для Каждого Реквизит Из СсылкаНаОбъект.Метаданные().Реквизиты Цикл
			Если Реквизит.Тип.Типы().Найти(Тип("СправочникСсылка.Сотрудники")) <> Неопределено Тогда
				Сотрудник	= СсылкаНаОбъект[Реквизит.Имя];
				Прервать;
			КонецЕсли;	
		КонецЦикла;
		Если Сотрудник = Неопределено Тогда
			Возврат ДобавитьЗапись("В переданых параметрах """ + Строка(СсылкаНаОбъект) + """ не найден сотрудник.");
		КонецЕсли;
	Иначе
		Сотрудник	= СсылкаНаОбъект;
	КонецЕсли;
	ОтладочнаяИнформация(СтрШаблон("Отчет по: %1 (%2)", Сотрудник, ТипЗнч(Сотрудник)));
	
	тДата		= ТекущаяДата();
	ПараметрыЗаполнения.Вставить("ТекущаяДата", Формат(тДата, "ДФ='d MMMM yyyy'") + " г.");
	
	// Получим данные по сотруднику
	Структура	= ПолучитьДанныеПоСотруднику(Сотрудник, тДата);
	Если Структура = Неопределено Тогда Возврат Неопределено КонецЕсли;
	ОбъединитьСтруктуры(ПараметрыЗаполнения, Структура, Ложь);
	
	// Получим данные по ответсвенным лицам
	Структура	= ПолучитьОтветственныеЛицаОрганизации(Структура.Организация, тДата);
	Если Структура = Неопределено Тогда Возврат Неопределено КонецЕсли;
	ОбъединитьСтруктуры(ПараметрыЗаполнения, Структура, Ложь);	
	
	// Получим паспортные данные физлица
	Структура	= ПолучитьПаспортныеДанныеФизическогоЛица(ПараметрыЗаполнения.ФизическоеЛицо, тДата);
	Если Структура = Неопределено Тогда Возврат Неопределено КонецЕсли;
	ОбъединитьСтруктуры(ПараметрыЗаполнения, Структура, Ложь);
	
	// Получить контактную информацию организации
	Структура	= ПолучитьКонтактнуюИнформациюОрганизации(ПараметрыЗаполнения.Организация);
	Если Структура = Неопределено Тогда Возврат Неопределено КонецЕсли;
	ОбъединитьСтруктуры(ПараметрыЗаполнения, Структура, Ложь);
	
	// Получить адрес по прописке физ лица
	Структура	= ПолучитьАдресПоПропискеФизЛица(ПараметрыЗаполнения.ФизическоеЛицо);
	Если Структура = Неопределено Тогда Возврат Неопределено КонецЕсли;
	ОбъединитьСтруктуры(ПараметрыЗаполнения, Структура, Ложь);
	
	ПараметрыЗаполнения.Вставить("ФизическоеЛицоРП", ТРег(daСклонение(ПараметрыЗаполнения.ФизическоеЛицо, "И", "Н", "ФИО", "Фамилия И. О.")));
	ПараметрыЗаполнения.Вставить("РуководительРП", ТРег(daСклонение(ПараметрыЗаполнения.Руководитель, "И", "Н", "ФИО", "Фамилия И. О.")));
	
	Возврат ПараметрыЗаполнения;
КонецФункции  // ПолучитьПараметрыЗаполнения()

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

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

#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Работа_с_word
Функция ЗаполнитьМакет(ПараметрыЗаполнения, ИмяМакета = "макет_docx")
	ПутьМакета	= ИзвлечьМакет(ИмяМакета);
	Файлы		= НайтиФайлы(ПутьМакета, "*.xml", Истина);
	// Разберем каждый xml файл
	Для Каждого Файл Из Файлы Цикл
		ОбработатьМакетXML(Файл.ПолноеИмя, ПараметрыЗаполнения)
	КонецЦикла;  // Для Каждого Файл Из Файлы
	Возврат СобратьДокумент(ПутьМакета);
КонецФункции  // ЗаполнитьМакет()
  
Функция ИзвлечьМакет(ИмяМакета = "макет_docx")   
	// Извлечем макет
	Если Метаданные().Макеты.Найти(ИмяМакета) = Неопределено Тогда
		ВызватьИсключение "Отсутсвует макет в обработке.";
		Возврат Неопределено; 
	КонецЕсли;
	ддМакет			= ПолучитьМакет(ИмяМакета);
	ВременныйПуть	= СокрЛП(СтрЗаменить(СтрШаблон("%1\МакетWord%2\", КаталогВременныхФайлов(), ИмяМакета), "\\", "\"));
	Файл			= Новый Файл(ВременныйПуть);
	Если Файл.Существует() Тогда
		УдалитьФайлы(ВременныйПуть);	
	КонецЕсли;  // Если Файл.Существует()
	Чтение			= Новый ЧтениеДанных(ддМакет);
	ддБуфер			= Чтение.ПрочитатьВБуферДвоичныхДанных();
	Поток			= Новый ПотокВПамяти(ддБуфер);
	ЧтениеZIP		= Новый ЧтениеZipФайла(Поток);
	ЧтениеZIP.ИзвлечьВсе(ВременныйПуть, РежимВосстановленияПутейФайловZIP.Восстанавливать);
	ЧтениеZIP.Закрыть(); Поток.Закрыть(); ддБуфер = Неопределено;
	Чтение.Закрыть(); ддМакет = Неопределено; Файл = Неопределено;
	Возврат ВременныйПуть;
КонецФункции  // ИзвлечьМакет()

Процедура ОбработатьМакетXML(ПутьФайла, ПараметрыЗаполнения)
	ЧтениеXML		= Новый ЧтениеXML;
	ЧтениеXML.ОткрытьФайл(ПутьФайла);

	Построитель		= Новый ПостроительDOM;
	ДокументDOM		= Построитель.Прочитать(ЧтениеXML);
	ЧтениеXML.Закрыть();
	
	Разыменователь	= Новый РазыменовательПространствИменDOM(ДокументDOM);
	URI				= Разыменователь.НайтиURIПространстваИмен("w");
	Если URI = Неопределено Тогда Возврат КонецЕсли; // Не найдено нужное пространство имен - нет смысла продолжать
	
	// Запишем параметры, найдя путь XPath
	ВыражениеXPath	= ДокументDOM.СоздатьВыражениеXPath(
						СтрШаблон("descendant::w:r/w:rPr/w:highlight[@w:val='%1']/../../w:t"
							, ЦветВыделенияПараметров)
						, Разыменователь);
	РезультатXPath	= ВыражениеXPath.Вычислить(ДокументDOM);	
	// Если xml документ не изменен - нет смысла продолжать
	Если Не ОбработатьУзелXPath(РезультатXPath, ПараметрыЗаполнения) Тогда Возврат КонецЕсли;  
	
	// Удалим выделение цветом параметров
	ВыражениеXPath	= ДокументDOM.СоздатьВыражениеXPath(
						СтрШаблон("descendant::w:r/w:rPr/w:highlight[@w:val='%1']"
							, ЦветВыделенияПараметров)
						, Разыменователь);
	РезультатXPath	= ВыражениеXPath.Вычислить(ДокументDOM);
	// Если не удалили выделение цветом - не продолжаем (это условие не должно выполняться, никогда)
	Если Не УдалитьУзелXPath(РезультатXPath) Тогда Возврат КонецЕсли; 
	
	// Запишем изменения
	ЗаписьDOM		= Новый ЗаписьDOM; 
	ЗаписьXML		= Новый ЗаписьXML;
	ЗаписьXML.ОткрытьФайл(ПутьФайла); 
	ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML); 
	ЗаписьXML.Закрыть(); ЗаписьDOM = Неопределено; ДокументDOM = Неопределено;
КонецПроцедуры  // ОбработатьМакетXML()

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

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

Функция СобратьДокумент(ПутьМакета)   
	// Запишем Word документ
	Поток		= Новый ПотокВПамяти;
	ЗаписьZIP	= Новый ЗаписьZipФайла(Поток);
	ЗаписьZIP.Добавить(СтрШаблон("%1*.*", ПутьМакета)
						, РежимСохраненияПутейZIP.СохранятьОтносительныеПути
						, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
	ЗаписьZIP.Записать();
	ЗаписьZIP	= Неопределено;
	
	// Уберем за собой
	Файл		= Новый Файл(ПутьМакета);
	Если Файл.Существует() Тогда
		УдалитьФайлы(ПутьМакета);	
	КонецЕсли;  // Если Файл.Существует()
	Файл		= Неопределено;
	
	Возврат Поток.ЗакрытьИПолучитьДвоичныеДанные();
КонецФункции  // СобратьДокумент()

#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Вспомогательные_запросы

Функция ЗапросСтруктурой(Поля, ТекстЗапроса, ПараметрыЗапроса = Неопределено)
	Попытка
		Структура		= Новый Структура(Поля);
		ТекстЗапроса	= СтрЗаменить(ТекстЗапроса, "Истина КАК Поля", Поля);  
		Запрос			= Новый Запрос(ТекстЗапроса);
		Для Каждого Параметр Из ПараметрыЗапроса Цикл
			Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);		
		КонецЦикла;
		Выборка			= Запрос.Выполнить().Выбрать();
		Если Не Выборка.Количество() Тогда Возврат Структура КонецЕсли;
		Выборка.Следующий();
		ЗаполнитьЗначенияСвойств(Структура, Выборка, Поля);
		Возврат Структура;
	Исключение
		Сообщить(СтрШаблон("Произошла ошибка во время запроса:
		| %1
		| ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~
		|Описание ошибки:
		| %2"
		, ТекстЗапроса
		, ОписаниеОшибки()));
		Возврат Неопределено;
	КонецПопытки;
КонецФункции  // ЗапросСтруктурой()

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

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

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

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

Функция ПолучитьАдресПоПропискеФизЛица(Физлицо)
	Поля			= "АдресПоПропискеФизЛица";
	ТекстЗапроса	= "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1 Представление КАК АдресПоПропискеФизЛица 
	|ИЗ Справочник.ФизическиеЛица.КонтактнаяИнформация ГДЕ Ссылка = &Физлицо
	|И Тип = Значение(Перечисление.ТипыКонтактнойИнформации.Адрес)
	|И Вид = Значение(Справочник.ВидыКонтактнойИнформации.АдресПоПропискеФизическиеЛица)"; 	
	ПараметрыЗапроса	= Новый Структура("Физлицо", Физлицо);	
	Возврат ЗапросСтруктурой(Поля, ТекстЗапроса, ПараметрыЗапроса);
КонецФункции  // ПолучитьАдресПоПропискеФизЛица()

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

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


//////////////////////////////////////////////////////////////
#Область Вспомогательные_функции

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

Функция ДобавитьЗапись(Текст, Сообщить = Истина, Журнал = Истина, Уровень = Неопределено)
	Уровень	= ?(Уровень = Неопределено, УровеньЖурналаРегистрации.Информация, Уровень); 
	Если Сообщить Тогда Сообщить(Текст, СтатусСообщения.Информация) КонецЕсли;		
	Если Журнал Тогда ЗаписьЖурналаРегистрации(Метаданные().Имя, Уровень, , , Текст) КонецЕсли;
	Возврат Неопределено;  // Возвращает Неопределено, тк это может быть удобным при неверно отработаной функции  
КонецФункции  // ДобавитьЗапись()

Процедура ОтладочнаяИнформация(Текст)
	Если Отладка Тогда Сообщить(Текст, СтатусСообщения.Информация) КонецЕсли;	
КонецПроцедуры  // ОтладочнаяИнформация()

#Область Склонение_функцией
Функция НазваниеПадежаПоНомеру(Номер) Экспорт
	Падежи	= Новый Соответствие;
	Падежи.Вставить(0, "Падеж");		// Номер падежа | Название падежа
	Падежи.Вставить(1, "Именительный");	// ( Кто?         ) Железняков Юрий Юрьевич
	Падежи.Вставить(2, "Родительный");	// ( нет кого?    ) Железнякова Юрия Юрьевича     
	Падежи.Вставить(3, "Дательный");	// ( кому?        ) Железнякову Юрию Юрьевичу 
	Падежи.Вставить(4, "Винительный");	// ( вижу кого?   ) Железнякова Юрия Юрьевича  
	Падежи.Вставить(5, "Творительный");	// ( кем?         ) Железняковым Юрием Юрьевичем    
	Падежи.Вставить(6, "Предложный");	// ( о ком?       ) Железнякове Юрии Юрьевиче
	Возврат Падежи.Получить(Номер);
КонецФункции // НазваниеПадежаПоНомеру()
//************************************************************
//(c) daMaster 2015
//mailto: damasterprog@yandex.ru
//
//СИНТАКСИС
//		daСклонение(_Выражение, _Падеж, _Род, _Режим, _ФорматнаяСтрока);
//			_Выражение 	 - склоняемое выражение
//			_Падеж 		 - падеж склонения, буква или цифра: "И" = 1, "Р" = 2, "В" = 3, "Д" = 4, "Т" = 5, "П" = 6
//			_Род 		 - род склоняемого выражения, буква или цифра: "М" = 1, "Ж" = 2, "С" = 3, "Н" = 4
//			_Режим		 - режим работы функции, определяется типом склоняемого выражения
//			_ФорматнаяСтрока - определяет формат и регистр выводимого результата
//
//СКЛОНЕНИЕ ФИО
//запуск выполняется в режиме "ФИО" или с пустым режимом, в таком случае - режим "ФИО" установится по умолчанию:
//		daСклонение("Пухов Федор Николаевич", "Р", "М", "ФИО")	= "Пухова Федора Николаевича"
//		daСклонение("Пухова Ольга Сергеевна", "Д") 				= "Пуховой Ольге Сергеевне"
//порядок символов "Ф", "И", "О" в параметре режима определяет порядок частей ФИО в склоняемом выражении, т.к. фамилия, имя и отчество склоняются по разным правилам
//		daСклонение("Мария Ивановна Кожедуб", "Т", , "ИОФ") 	= "Марией Ивановной Кожедуб"
//		daСклонение("В. Тёркин", "П", , "ИФ") 					= "В. Тёркине"
//		daСклонение("Тихончук", "Р", "Ж", "Ф") 					= "Тихончук"
//форматная строка может содержать ключевые слова "Фамилия", "Имя", "Отчество" или сокращения "Ф", "И", "О", их регистр определяет регистр выводимого результата
//		daСклонение("Чапаев Василий Иванович", "Р", , , "Имя Отчество Фамилия") 	= "Василия Ивановича Чапаева"
//		daСклонение("Чапаев Василий Иванович", "Д", , , "Фамилия И. О.") 			= "Чапаеву В. И."
//		daСклонение("Чапаев Василий Иванович", "И", , , "отчество: Имя - ФАМИЛИЯ") 	= "иванович: Василий - ЧАПАЕВ"
//
//ОПРЕДЕЛЕНИЕ РОДА
//если с параметром _Род передать переменную со значением "?", в нее вернется род в случае успеха или останется "?" в случае неудачи
//		ПоискРода = "?"; Результат = daСклонение("Лукашенко Александр Григорьевич", "Р", ПоискРода); Сообщить(ПоискРода); //"М"
//		ПоискРода = "?"; Результат = daСклонение("Лукашенко А. Г.", "Р", ПоискРода); Сообщить(ПоискРода); //"?"
//
//СКЛОНЕНИЕ ПРОФЕССИЙ
//запуск выполняется в режиме "Д":
//		daСклонение("Ведущий программист 1С и консультант по ЗиК", "Р", , "Д") = "Ведущего программиста 1С и консультанта по ЗиК"
//в этом и остальных режимах форматная строка определяет регистр слов результата и задается при помощи литер, если литера не задана - остается исходный регистр,
//А - первая буква первого слова, Б - первая буква остальных слов, В - все остальные буквы всех слов, Г - специально для аббревиатур:
//		daСклонение("Ведущий программист 1С и Консультант по ЗиК", "Р", , "Д", "АБВГ") 	= "ВЕДУЩЕГО ПРОГРАММИСТА 1С И КОНСУЛЬТАНТА ПО ЗИК"
//		daСклонение("Ведущий программист 1С и Консультант по ЗиК", "Р", , "Д", "абвг") 	= "ведущего программиста 1с и консультанта по зик"
//		daСклонение("Ведущий программист 1С и Консультант по ЗиК", "Р", , "Д", "АБ") 	= "Ведущего Программиста 1С и Консультанта По ЗиК"
//		daСклонение("Ведущий программист 1С и Консультант по ЗиК", "Р", , "Д", "Абв") 	= "Ведущего программиста 1С и консультанта по ЗиК"
//
//СКЛОНЕНИЕ СУЩЕСТВИТЕЛЬНЫХ, ПРИЛАГАТЕЛЬНЫХ, ГЛАГОЛОВ, ГЕОГРАФИЧЕСКИХ НАИМЕНОВАНИЙ
//запуск выполняется в режиме "В":
//		daСклонение("Генеральная доверенность", "Р", , "В")			= "Генеральной доверенности"
//		daСклонение("Санкт-Петербург", "П", , "В")					= "Санкт-Петербурге"
//в этом режиме возможно склонение в форме множественного числа, для этого в параметре _Род указывается "Н" (мНожественный):
//		daСклонение("Устав", "И", "Н", "В")							= "Уставы"
//		daСклонение("Генеральная доверенность", "Р", "Н", "В")		= "Генеральных доверенностей"
//возможно склонение глаголов по родам и по числам, исходный глагол может быть в форме любого рода и числа, но в настоящем времени:
//		daСклонение("Подготовили", "И", "Ж", "В")					= "Подготовила"
//		daСклонение("Утвердило ответственное лицо", "И", "Н", "В")	= "Утвердили ответственные лица"
//
//СКЛОНЕНИЕ ЧИСЕЛ, ВАЛЮТ, ЕДИНИЦ ИЗМЕРЕНИЯ
//запуск выполняется в режиме "Ч", возможно склонение по родам:
//		daСклонение("Двадцать один", "И", "С", "Ч")				= "Двадцать одно"
//		daСклонение("Двадцать один", "Р", "Ж", "Ч")				= "Двадцати одной"
//параметр _Выражение может иметь тип "Число":
//		daСклонение(21, "И", "С", "Ч")							= "Двадцать одно"
//		daСклонение(21, "Р", "Ж", "Ч")							= "Двадцати одной"
//возможно склонение сочетания числа и исчислимого (валюты, единицы измерения, прочих существительных)
//		daСклонение("32 доска", "Р", , "Ч")						= "Тридцати двух досок"
//исчислимое должно быть в начальной форме (именительный падеж, единственное число):
//		daСклонение("23 австралийский доллар", "Р", , "Ч")		= "Двадцати трех австралийских долларов"
//исключение для популярных валют, они могут быть в формате встроенной функции ЧислоПрописью()- "5 рублей", "13 долларов"):
//		daСклонение("14 рублей 88 копеек", "Р", , "Ч", "абв")	= "четырнадцати рублей восьмидесяти восьми копеек"
//если перед словом поставить символ "\", данное слово не будет изменено:
//		daСклонение("51 рубль \81 копейка", "Р", , "Ч")			= "Пятидесяти одного рубля 81 копейки"
//если перед числом поставить символ "^", данное слово будет склоняться без преобразования в пропись:
//		daСклонение("^25 страница", "П", , "Ч")					= "25-ти страницах"
//для получения формы винительного падежа одушевленных существительных, используется специальный падеж "О" (винительный Одушевленный):
//		daСклонение("41 мешок", "В", , "Ч")						= "Сорок один мешок"
//		daСклонение("41 маляр", "О", , "Ч")						= "Сорок одного маляра"
//
Функция daСклонение(_Выражение
					, _Падеж			= "И"
					, _Род				= ""
					, _Режим			= "ФИО"
					, _ФорматнаяСтрока	= ""
					) Экспорт
	
	_Версия = "17.06.2015";
		
	//ТАБЛИЦЫ ПРАВИЛ СКЛОНЕНИЯ
	//в колонке "Окончания" указывается перечень окончаний, для которых действует данное правило, разделитель "/", в конце также ставится разделитель
	//алгоритм ищет строки с окончаниями последовательно, при совпадении останавливается, поэтому более узкое правило ("РВИН") должно следовать выше, чем широкое ("ИН")
	//если окончание не найдено в таблице правил - такое слово не склоняется
	//колонка "Обрезка" определяет, сколько символов с конца слова обрезать, перед добавлением окончания из колонки падежа ("Р", "Д", "В", "Т", "П")
	_ПравилаФ = //Фамилия
	//Род;	Окончания;											Обрезка;	Р;		Д;		В;		Т;		П;		Комментарий   
	//символ "*" перед окончанием означает, что данное окончание сравнивается не с концом слова, а с целым словом ("*ГРИН" сработает только на Грин, а "ГРИН" - и на "Грин", и на "Багрин")
	"М-;	*ГРИН/*ЧАПЛИН/РВИН/*БИН/;							0;			а;		у;		а;		ом;		е;		Грин, Дарвин, Чаплин - исключения, чтобы пройти тест gramota.ru )
	//в колонке "Род" указывается один литерал рода ("М", "Ж", "С"), если окончание позволяет однозначно определить род ("Петров" - "М", "Ильина" - "Ж")
	|Ж;		ЕВА/ЁВА/ИНА/ОВА/ЫНА/;								1;			ой;		ой;		у;		ой;		ой;
	|М;		ЕВ/ЁВ/ИН/ОВ/ЫН/;									0;			а;		у;		а;		ым;		е;
	|М;		ЧИЙ/ШИЙ/ЩИЙ/;										2;			его;	ему;	его;	им;		ем;		Осадчий, Старший, Вещий
	|Ж;		ЧАЯ/ШАЯ/ЩАЯ/;										2;			ей;		ей;		ую;		ей;		ей;     Осадчая, Старшая, Вещая
	|Ж;		АЯ/;												2;			ой;		ой;		ую;		ой;		ой;     Крутая
	|Ж;		ЯЯ/;												2;			ей;		ей;		юю;		ей;		ей;     Верхняя
	//"М-" в колонке "Род" означает, что по окончанию род не определить, но правило действует  только для рода "М" ("Воробей" склоняется только для "М", для "Ж" - не склоняется)
	|М-;	*ВОРОБЕЙ/*СОЛОВЕЙ/;									2;			ья;		ью;		ья;		ьем;	ье;		Воробей, Соловей
	|М-;	*ЛЕВ/;												2;			ьва;	ьву;	ьва;	ьвом;	ьве;	Лев
	|М-;	*КИЙ/*БОКИЙ/;										1;			я;		ю;		я;		ем;		е;		Кий
	|М-;	ЦОЙ/ВИЙ/СОЙ/ЕЙ/АЙ/УЙ/;								1;			я;		ю;		я;		ем;		е;		Цой, Гелетей, Лузай
	|М;		ГОЙ/КОЙ/ХОЙ/ШОЙ/;									2;			ого;	ому;	ого;	им;		ом;     Плохой, Большой
	|М;		ЧОЙ/ЩОЙ/;											2;			его;	ему;	его;	им;		ом;     
	|М;		ОЙ/ЫЙ/;												2;			ого;	ому;	ого;	ым;		ом;     Крутой, Мудрый
	|М;		ГИЙ/КИЙ/;											2;			ого;	ому;	ого;	им;		ом;
	|М-;	ИЙ/;												1;			я;		ю;		я;		ем;		и;		Шарий
	|М-;	КАШ/;												0;			а;		у;		а;		ом;		е;      Лукаш
	|М-;	ЬМИЧ/;												0;			а;		у;		а;		ом;		е;      Кузьмич
	|М-;	ИЧ/Ш/;												0;			а;		у;		а;		ем;		е;      Митрич, Гаспажиньш, Милош, Хараш, Черныш
	|М-;	АК/АН/ЕР/ИР/ЙН/НГ/ОН/ОР/УК/ЯК/ЯН/БИХ/РИХ/;			0;			а;		у;		а;      ом;     е;                   
	//колонка "Род" пустая, если по окончанию род не определить, но правило склонения одинаковое для "М" и "Ж ("Живаго", "Лисица")
	|;		АГО/ИА/НКО/ОВО/ОТО/ЦКО/ЫХ/ЮДО/ОЛЯ/ЬДА/ИХ/ЫХ/УА/;	0;			;		;		;      	;     	;                   
	//символ "+" перед окончанием означает, что данное правило действует для не последней части составного слова (в "Абдул-Шах" часть "Абдул" не склоняется, а если "Абдул" - отдельное слово, то склоняется)
	|;		+ВАН/+АБДУЛ/+БЕЛИЦ/+ГАСАН/+ДЮССАР/+ДЮМОН/+КНИППЕР/+КОРВИН/  0;	;		;		;      	;     	;		
	|;		+КАРА/+САЕД/+БОНЧ/+ШОЛОМ/+ПРИЗВАН/+МЕЛИК/*ТЕР/*ВАР/*ФОН/;	0;	;		;		;      	;     	;		
	|;		*ДЮМА/*ТОМА/*ДЕГА/*ЛЮКА/*ФЕРМА/*ГАМАРРА/;           0;			;		;		;      	;     	;		
	|;		*ПЕТИПА/*ШАНДРА/*СКАЛЯ/*КАРУАНА/;					0;			;		;		;      	;     	;		
	|М-;	ИЯ/;												1;			и;		и;		ю;		ей;		и;      Берия             
	|М-;	ОЯ/;												1;			и;		е;		ю;		ей;		е;		
	|;		НЖА/;												1;			и;		е;		у;		ей;		е;		Стринжа
	|;		ЖА/;												1;			и;		е;		у;		ой;		е;		Ганжа
	|;		ГА/КА/УЛЕША/ВАША/ХА/;								1;			и;		е;		у;		ой;		е;		Кулеша/Кулешой
	|;		Я/;													1;			и;		е;		ю;		ей;		е;		Разиня
	|;		ЙА/ЧА/ША/ЩА/;										1;			и;		е;		у;		ей;		е;		Олеша/Олешей, Мойа
	|;		ЦА/;												1;			ы;		е;		у;		ей;		е;		Лисица
	|;		А/;													1;			ы;		е;		у;		ой;		е;                   
	|М-;	ЕНЬ/;												3;			ня;		ню;		ня;		нем;	не;		Камень
	|М-;	Ь/;													1;			я;		ю;		я;		ем;		е;		Даль
	|М-;	ЁК/;												2;			ька;	ьку;	ька;	ьком;	ьке;	Королёк
	|М-;	БЛОК/;												0;			а;		у;		а;		ом;		е;      Блок
	|М-;	ОК/;												2;			ка;		ку;		ка;		ком;	ке;		Миненок, Кисляченок
	|М-;	ИЕЦ/;												2;			йца;	йцу;	йца;	йцем;	йце;	Коломиец
	|М-;	ПАЛЕЦ/;												2;			ьца;	ьцу;	ьца;	ьцем;	ьце;	Долгопалец
	|М-;	ЛЕЦ/;												2;			ьца;	ьцу;	ьца;	ьцом;	ьце;	Стрелец
	|М-;	ЧЕЦ/;												0;			а;		у;		а;		ом;		е;		Чайчец
	|М-;	АВЕЦ/ЖЕЦ/;											2;			ца;		цу;		ца;		цем;	це;		Переяславец, Запорожец
	|М-;	ОВЕЦ/БЕЦ/АМЕЦ/НЕЦ/ТЕЦ/;								2;			ца;		цу;		ца;		цом;	це;		Горовец
	|М-;	ШВЕЦ/;												0;			а;		у;		а;		ом;		е;		Швец
	|М-;	Ц/;													0;			а;		у;		а;		ем;		е;		Кац, Бэц
	|М-;	ЁЛ/;												2;			ла;		лу;		ла;		лом;	ле;		Козёл
	|М-;	ДЖ/ИЖ/ОЖ/РЖ/ЙЧ/;									0;			а;		у;		а;		ем;		е;		Джордж, Лейч
	|М-;	Б/В/Г/Д/Ж/З/К/Л/М/Н/П/Р/С/Т/Ф/Х/Ч/Ш/Щ/;				0;			а;		у;		а;		ом;		е;		Заканчивается на согласную";
	
	_ПравилаИ = //Имя
	//Род;	Окончания;											Обрезка;	Р;		Д;		В;		Т;		П;		Комментарий   
	"Ж;		*ИЯ/;												1;			и;		е;		ю;		ей;		е;		Ия
	|Ж;		ИЯ/;												1;			и;		и;		ю;		ей;		и;		Мария
	|;		ГА/КА/ХА/;											1;			и;		е;		у;		ой;		е;		Ольга, Серега, Лука, Лика, Хоха
	|;		ЖА/ЙА/ЧА/ША/ЩА/;									1;			и;		е;		у;		ей;		е;		Миша, Маша
	|;		ЦА/;												1;			ы;		е;		у;		ей;		е;      Маца
	|Ж;		НА/ВЕРА/;											1;			ы;		е;		у;		ой;		е;      Инна, Нина, Ирина, Вера
	|Ж;		А/;													1;			ы;		е;		у;		ой;		е;      Тома (женские на -а чаще)
	|М;		*ШОТА/;												0;			;		;		;		;		;		Шота
	|М;		А/ЛО/;												1;			ы;		е;		у;		ой;		е;      Дима, Гаврило
	|М;		*ИЛЬЯ/*ИЛИЯ/;										1;			и;		е;		ю;		ей;		е;		Илья
	|Ж-;	Я/;													1;			и;		е;		ю;		ей;		е;		Дуня
	|М-;	Я/;													1;			и;		е;		ю;		ей;		е;		Гия
	|М;		РЬ/;												1;			я;		ю;		я;		ем;		е;		Игорь
	|Ж;		*ЛЮБОВЬ/*АГАРЬ/*РАХИЛЬ/*РУФЬ/*СУЛАМИФЬ/*ЭСФИРЬ/;	1;			и;		и;		ь;		ью;		и;		Любовь
	|Ж;		*ЮДИФЬ/*РАШЕЛЬ/*НИНЕЛЬ/*ИЗАБЕЛЬ/*ИСАБЕЛЬ/;			1;			и;		и;		ь;		ью;		и;		Любовь
	|М-;	Ь/;													1;			я;		ю;		я;		ем;		е;		Олесь
	|М;		*ПАВЕЛ/;											2;			ла;		лу;		ла;		лом;	ле;		Павел
	|М;		*ЛЕВ/;												2;			ьва;	ьву;	ьва;	ьвом;	ьве;	Лев
	|М;		ИЙ/;												1;			я;		ю;		я;		ем;		и;		Василий
	|М;		Й/;													1;			я;		ю;		я;		ем;		е;		Гай
	|М;		ЁТР/;												3;			етра;	етру;	етра;	етром;	етре;	Пётр
	|М;		+АХМАД/+АБДУЛ/+ГАСАН/+САЛИМ/+САИД/;					0;			;		;		;		;		;		Салим-Гирей
	|М;		ДЖ/;												0;			а;		у;		а;		ем;		е;		Джордж
	|М;		Б/В/Г/Д/Ж/З/К/Л/М/Н/П/Р/С/Т/Ф/Х/Ц/Ч/Ш/Щ/;			0;			а;		у;		а;		ом;		е;		Заканчивается на согласную";
	
	_ПравилаО = //Отчество
	//Род;	Окончания;											Обрезка;	Р;		Д;		В;		Т;		П;		Комментарий   
	"М;		*ИЛЬИЧ/*КУЗЬМИЧ/*ЛУКИЧ/*ФОМИЧ/;						0;			а;		у;		а;		ом;		е;		Ильичом, Кузьмичом (после шипящих под ударением!)
	|М;		ИЧ/;												0;			а;		у;		а;		ем;		е;
	|Ж;		НА/;												1;			ы;		е;		у;		ой;		е;
	|М;		ОГЛЫ/УЛЫ/УУЛУ/;										0;			;		;		;		;		;       Оглы, Улы, Уулу
	|Ж;		ЫЗЫ/ИЗИ/;											0;			;		;		;		;		;		Кызы, Гызы, Кизи
	|;		*ИБН/;												0;			;		;		;		;		;		ибн
	|;		+Б/+В/+Г/+Д/+Ж/+З/+К/+Л/+М/+Н/+П/+Р/+С/+Т/+Ф/+Х/+Ц/+Ч/+Ш/+Щ/;0;	;		;		;		;		;		Заканчивается на согласную - восточные отчества - не последняя часть слова
	|;		Б/В/Г/Д/Ж/З/К/Л/М/Н/П/Р/С/Т/Ф/Х/Ц/Ч/Ш/Щ/;			0;			а;		у;		а;		ом;		е;		Заканчивается на согласную - восточные отчества";
	
	_ПравилаД = //Должность
	//Род;	Окончания;											Тег;	Обрезка;	Р;		Д;		В;		Т;		П;		
	"М;		*ВЕНТИЛЕВОЙ/*РУЛЕВОЙ/*ДВЕРЕВОЙ/*ПЕЧЕВОЙ/*КОВШЕВОЙ/;											;		2;			ого;	ому;	ого;	ым;		ом;
	|М;		*ЛЮКОВОЙ/*СКИПОВОЙ/*МИКСЕРОВОЙ/*СТВОЛОВОЙ/*ГОРНОВОЙ/*ПОСТОВОЙ/*ВЕРХОВОЙ/*РАЗЪЕЗДНОЙ/*ПОРТНОЙ/;	;	2;			ого;	ому;	ого;	ым;		ом;
	|М;		*БИРЖЕВОЙ/*ПОЛЕВОЙ/*ПУТЕВОЙ/*ЛИЦЕВОЙ/*ЗУБНОЙ/*ПОЕЗДНОЙ/*РЕЧНОЙ/*РУЧНОЙ/*ВТОРОЙ/;					К;		2;			ого;	ому;	ого;	ым;		ом;
	|М;		*ПРАВОВОЙ/*БЕРЕГОВОЙ/*ТРУДОВОЙ/*СУДОВОЙ/*ГРУЗОВОЙ/*МИРОВОЙ/ЛЕНТОВОЙ/*БОРТОВОЙ/*МОСТОВОЙ/*СТРАХОВОЙ/;К;		2;			ого;	ому;	ого;	ым;		ом;
	|М;		*ЗАВОДСКОЙ/*ГОРОДСКОЙ/*МОРСКОЙ/;																	К;		2;			ого;	ому;	ого;	им;		ом;
	|М;		ЖИЙ/ЧИЙ/ШИЙ/ЩИЙ/;									;		2;			его;	ему;	его;	им;		ем;		
	|М;		СКИЙ/;												;		2;			ого;	ому;	ого;	им;		ом;		
	|М;		ЫЙ/;												;		2;			ого;	ому;	ого;	ым;		ом;		
	|Ж;		ЖАЯ/ЧАЯ/ШАЯ/ЩАЯ/;									;		2;			ей;		ей;		ую;		ей;		ей;		
	|Ж;		ЯЯ/;												;		2;			ей;		ей;		юю;		ей;		ей;		
	|Ж;		АЯ/;												;		2;			ой;		ой;		ую;		ой;		ой;		
	|;		Е/И/Ы/Ю/;											П;		0;			;		;		;		;		;		
	|;		ЗАВ/ЗАМ/НАЧ/;										П;		0;			;		;		;		;		;		
	|;		ОЙ/;												П;		0;			;		;		;		;		;		
	|;		*ОВЕЦ/;												;		0;			;		;		;		;		;		
	|;		ДЬЯ/;												;		1;			и;		е;		ю;		ей;		е;      
	|;		АРЬ/;												;		1;			я;		ю;		я;		ем;		е;		
	|;		ИСТ/;												;		0;			а;		у;		а;		ом;		е;		
	|Ж;		ЙКА/ИСТКА/ША/ТАРКА/ЕРКА/ЯРКА/ЕНКА/ЧИХА/ЖКА/;		;		1;			и;		е;		у;		ой;		е;		
	|Ж;		ИЦА/;												;		1;			ы;		е;		у;		ей;		е;      
	|Ж;		НЯ/ВЕЯ/НЬЯ/;										;		1;			и;		е;		ю;		ей;		е;      
	|Ж;		СЕСТРА/ССА/;										;		1;			ы;		е;		у;		ой;		е;      
	|Ж;		ДЕЛЬ/;												;		1;			и;		и;		ь;		ью;		и;      
	|М;		ГЛАВА/ШИНА/;										;		1;			ы;		е;		у;		ой;		е;      
	|М;		КАЛЬ/ГАЛЬ/ИТЕЛЬ/АТЕЛЬ/ОТЕЛЬ/ЕРЬ/;					;		1;			я;		ю;		я;		ем;		е;		
	|М;		АЧЕЙ/КЕЙ/ДЖЕЙ/;										;		1;			я;		ю;		я;		ем;		е;		
	|М;		ЛИСТ/;												;		0;			а;		у;		а;		ом;		е;		
	|М;		ЗНЕЦ/ТЕЦ/;											;		0;			а;		у;		а;		ом;		е;		
	|М;		АВЕЦ/ЕБЕЦ/ЕВЕЦ/ОВЕЦ/ЖЕЦ/РЕЦ/СЕЦ/НЕЦ/;				;		2;			ца;		цу;		ца;		цом;	це;		
	|М;		ОЕЦ/;												;		2;			йца;	йцу;	йца;	йцом;	йце;	
	|М;		ИЕЦ/;												;		2;			йца;	йцу;	йца;	йцем;	йце;	
	|М;		ПОСОЛ/;												;		2;			ла;		лу;		ла;		лом;	ле;		
	|М;		РЕЛОК/;												;		2;			ка;		ку;		ка;		ком;	ке;		
	|М;		РОНОМ/АНАТОМ/;										;		0;			а;		у;		а;		ом;		е;		
	|М;		ОРУБ/ДУВ/КЛАД/ВЕД/ЕВОД/ОВОД/ОХОД/ЛАЗ/ВАЛ/ДЕЛ/СОЛ/ОКОЛ/КОП/ВАР/ОПАР/ВЕС/МЕС/НОС/ТЕС/;		;	0;	а;		у;		а;		ом;		е;
	|М;		ЛОПРАВ/ТОПРАВ/РИВОД/ЫБАК/ЕГАР/АТУР/ТРОС/ИЛОТ/ПЕРТ/НАСТ/НТЕРН/АТЛЕТ/ХОДОК/ГРОК/ОБОЛ/;		;	0;	а;		у;		а;		ом;		е;
	|М;		РАБ/ТАВ/МАТ/ГОГ/ЛОГ/ПЕД/РОЖ/ЗАК/СУЛ/ОНАЛ/ЕРСАЛ/ЛЕН/МЕН/ЬОН/ОУН/;							;	0;	а;		у;		а;		ом;		е;
	|М;		БАТ/ДАТ/КАТ/ПАТ/ТАТ/ЕКТ/ИСТ/ОСТ/АНТ/ГЕНТ/ДЕНТ/РЕНТ/СТЕНТ/ЦЕНТ/ОНТ/;							;	0;	а;		у;		а;		ом;		е;
	|М;		НАР/САР/ТАР/ЦАР/ЧАР/АТР/ИТР/СТР/;															;	0;	а;		у;		а;		ом;		е;
	|М;		АЕР/ВЕР/ГЕР/ДЕР/ЖЕР/ЗЕР/ЙЕР/КЕР/ЛЕР/НЕР/ПЕР/РЕР/СЕР/ХЕР/ЧЕР/ШЕР/ЮЕР/;						;	0;	а;		у;		а;		ом;		е;
	|М;		ЕМЕР/ИМЕР/РМЕР/ЮМЕР/АЛЬЕР/ЕЛЬЕР/РЬЕР/ЁР/;													;	0;	а;		у;		а;		ом;		е;
	|М;		ДИТЕР/КТЕР/ЛТЕР/ЙТЕР/НТЕР/ОТЕР/ПТЕР/СТЕР/УТЕР/ФТЕР/ХТЕР/;									;	0;	а;		у;		а;		ом;		е;
	|М;		ДОР/ЗОР/ИОР/РОР/СОР/ТОР/ФОР/ЦОР/АТОР/ИТОР/КТОР/НТОР/;										;	0;	а;		у;		а;		ом;		е;
	|М;		ВИК/ЗИК/МИК/НИК/ГРАФИК/ЧИК/ШИК/ЩИК/ИРИК/ОРИК/ТРИК/ГИСТИК/ТИСТИК/УСТИК/АТИК/ЕТИК/ИТИК/ПТИК/;	;	0;	а;		у;		а;		ом;		е;
	|М;		ИВ/РГ/ИД/ЯК/АН/ГУН/ИР/ЭР/ЮР/ЯР/УС/ВТ/ЬТ/АФ/СОФ/ТУХ/ЮХ/АЧ/;									;	0;	а;		у;		а;		ом;		е;";
	
	_ПравилаЧ = //Числительное
	//Род;	Окончания;								Тег;	Обрезка;	И;			Р;			Д;			В;			Т;			П;			О;		Комментарий   
	"М;		*ОДИН/*ОДНА/*ОДНО/;						1;		2;			ин;			ного;		ному;		ин;			ним;		ном;		ного;	Один
	|С;		*ОДИН/*ОДНА/*ОДНО/;						1;		2;			но;			ного;		ному;		но;			ним;		ном;		ного;	Одно
	|Ж;		*ОДИН/*ОДНА/*ОДНО/;						1;		2;			на;			ной;		ной;		ну;			ной;		ной;		ну;		Одна
	|М;		*ДВА/*ДВЕ/;								2;		1;			а;			ух;			ум;			а;			умя;		ух;			ух;		Два, Две
	|С;		*ДВА/*ДВЕ/;								2;		1;			а;			ух;			ум;			а;			умя;		ух;			ух;		Два, Две
	|Ж;		*ДВА/*ДВЕ/;								2;		1;			е;			ух;			ум;			е;			умя;		ух;			ух;		Два, Две
	|;		*ТРИ/;									2;		1;			и;			ех;			ем;			и;			емя;		ех;			ех;		Три
	|;		*ЧЕТЫРЕ/;								2;		1;			е;			ех;			ем;			е;			ьмя;		ех;			ех;		Четыре
	|;		*ВОСЕМЬ/;								;		3;			емь;		ьми;		ьми;		емь;		емью;		ьми;		емь;	Восемь
	|;		*ПЯТЬ/*ШЕСТЬ/*СЕМЬ/*ДЕВЯТЬ/*ДЕСЯТЬ/ДЦАТЬ/;	;	1;			ь;			и;			и;			ь;			ью;			и;			ь;		Пять, Шесть, Семь, Десять и др.
	|;		*СОРОК/;								;		0;			;			а;			а;			;			а;			а;			;		Сорок
	|;		*ВОСЕМЬДЕСЯТ/;							;		8;			емьдесят;	ьмидесяти;	ьмидесяти;	емьдесят;	емьюдесятью;ьмидесяти;	емьдесят;Восемьдесят
	|;		ЬДЕСЯТ/;								;		6;			ьдесят;		идесяти;	идесяти;	ьдесят;		ьюдесятью;	идесяти; 	ьдесят;	Пятьдесят и др.
	|;		*СТО/*ДЕВЯНОСТО/;						;		1;			о;			а;			а;			о;			а;			а; 			о;		Девяносто, Сто
	|;		*ДВЕСТИ/;								;		4;			ести;		ухсот;		умстам;		ести;		умястами;	ухстах;		ести;	Двести
	|;		*ТРИСТА/;								;		4;			иста;		ехсот;		емстам;		иста;		емястами;	ехстах;		иста;	Триста
	|;		*ЧЕТЫРЕСТА/;							;		4;			еста;		ехсот;		емстам;		еста;		ьмястами;	ехстах;		еста;	Четыреста
	|;		*ВОСЕМЬСОТ/;							;		6;			емьсот;		ьмисот;		ьмистам;	емьсот;		емьюстами;	ьмистах;	емьсот;	Восемьсот
	|;		ЬСОТ/;									;		4;			ьсот;		исот;		истам;		ьсот;		ьюстами; 	истах;		ьсот;	Пятьсот, Шестьсот, Семьсот, Девятьсот
	|;		*НОЛЬ/*НУЛЬ/;							;		1;			ь;			я;			ю;			ь;			ем;			е;			ь;		Ноль, Нуль
	|М;		1/;										1;		0;			-ин;		-го;		-му;		-ин;		-им;		-ом;		-го;	
	|С;		1/;										1;		0;			-но;		-го;		-му;		-ин;		-им;		-ом;		-го;	
	|Ж;		1/;										1;		0;			-на;		-ой;		-ой;		-ну;		-ой;		-ой;        -ну;		
	|М;		2/;										2;		0;			-а;			-ух;		-ум;		-а;			-мя;		-ух;        -ух;	
	|С;		2/;										2;		0;			-а;			-ух;		-ум;		-а;			-мя;		-ух;        -ух;
	|Ж;		2/;										2;		0;			-е;			-ух;		-ум;		-е;			-мя;		-ух;        -ух;
	|;		3/;										2;		0;			-и;			-ех;		-ем;		-и;			-мя;		-ех;        -ех;	
	|;		4/;										2;		0;			-ре;		-х;			-ем;		-ре;		-мя;		-ех;        -ех;	
	|;		5/6/9/10/11/12/13/14/15/16/17/18/19/20/30/;;	0;			-ть;		-ти;		-ти;		-ть;		-тью;		-ти;		-ть;	
	|;		7/8/;									;		0;			-мь;		-ми;		-ми;		-мь;		-мью;		-ми;        -мь;	
	|;		40/;									;		0;			-к;			-ка;		-ка;		-к;			-ка;		-ка;		-к;		
	|;		50/60/70/80/;							;		0;			-т;			-ти;		-ти;		-т;			-тью;		-ти;        -т;		
	|;		90/;									;		0;			-сто;		-та;		-та;		-сто;		-та;		-та;        -сто;	
	|;		100/;									;		0;			;			-та;		-та;		;			-та;		-та;		;	
	|;		200/;									;		0;			-и;			-сот;		-стам;		-и;			-стами;		-стах;      -и;	
	|;		300/400/;								;		0;			-а;			-сот;		-стам;		-а;			-стами;		-стах;      -а;		
	|;		500/600/700/800/900/;					;		0;			-сот;		-сот;		-стам;		-сот;		-стами;		-стах;      -сот;	
	|;		*0/;									;		0;			-ль;		-ля;		-лю;		-ль;		-ем;		-ле;        -ль;	
	|;		0/;										;		0;			;			;			;			;			;			;			;";
	
	_ПравилаВ = //Выражение
	//Род;	Окончания;									Обрезка;	И;				Р;				Д;				В;				Т;				П;				О;				
	"С;		ЕНИЕ/;										1;			е/я;			я/й;			ю/ям;			е/я;			ем/ями;			и/ях;			е/й;			
	//"Р" в колонке "Род" означает, слово родоизменяемое, и порядок окончания в списке определяет род слова
	|Р;		КИЙ/КАЯ/КОЕ/КИЕ/;							2;			ий/ая/ое/ие;	ого/ой/ого/их;	ому/ой/ому/им;	ий/ую/ое/ие;	им/ой/им/ими;	ом/ой/ом/их;	ого/ую/ое/их;	
	|Р;		НИЙ/НЯЯ/НЕЕ/НИЕ/;							2;			ий/яя/ее/ие;	его/ей/его/их;	ему/ей/ему/им;	ий/юю/ее/ие;	им/ей/им/ими;	ем/ей/ем/их;	его/юю/ое/их;	
	|Р;		ЩИЙ/ЩАЯ/ЩЕЕ/ЩИЕ/;							2;			ий/ая/ее/ие;	его/ей/его/их;	ему/ей/ему/им;	ий/ую/ее/ие;	им/ей/им/ими;	ем/ей/ем/их;	его/ую/ое/их;	
	|Р;		ШИЙ/ШАЯ/ШОЕ/ШИЕ/;							2;			ий/ая/ее/ие;	его/ей/его/их;	ему/ей/ему/им;	ий/ую/ее/ие;	им/ей/им/ими;	ем/ей/ем/их;	его/ую/ое/их;	
	|Р;		ЫЙ/АЯ/ОЕ/ЫЕ/;								2;			ый/ая/ое/ые;	ого/ой/ого/ых;	ому/ой/ому/ым;	ый/ую/ое/ые;	ым/ой/ым/ыми;	ом/ой/ом/ых;	ого/ую/ое/ых;	
	|Р;		ЧЕЛ/ЧЛА/ЧЛО/ЧЛИ/;							2;			ел/ла/ло/ли;	ел/ла/ло/ли;	ел/ла/ло/ли;	ел/ла/ло/ли;	ел/ла/ло/ли;	ел/ла/ло/ли;	ел/ла/ло/ли;	
	|Р;		АЛ/АЛА/АЛО/АЛИ/;							0111;		/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			
	|Р;		ИЛ/ИЛА/ИЛО/ИЛИ/;							0111;		/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			
	|Р;		ЕЛ/ЕЛА/ЕЛО/ЕЛИ/;							0111;		/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			/а/о/и;			
	|Ж;		*ТЫСЯЧА/*ТЫСЯЧИ/*ТЫСЯЧ/;						110;		а/и;			и/;				е/ам;			у/и;			ей/ами;			е/ах;			у/и;			
	|М;		ЛЛИОН/ЛЛИОНА/ЛЛИОНОВ/ЛЛИАРД/ЛЛИАРДА/ЛЛИАРДОВ/;012012;	/ы;				а/ов;			у/ам;			/ы;				ом/ами;			е/ах;			/ы;				
	|;		*САНКТ/*УСТЬ/*ЙОШКАР/*НА/;					0;			/;				/;				/;				/;				/;				/;				/;				
	|;		*СТЕРЛИНГОВ/;								0;			/;				/;				/;				/;				/;				/;				/;				
	|М;		ОВЕК/;										0;			/и;				а/;				у/ам;			а/;				ом/ами;			е/ах;			а/;				
	|М;		ЕЦ/;										2;			ец/цы;			ца/цов;			цу/цам;			ец/цы;			цом/цами;		це/цах;			ца/цов;			
	|М;		ЕНЬ/;										3;			ень/ни;			ня/ней;			ню/ням;			ень/ни;			нем/нями;		не/нях;			ня/ней;			
	|М;		ШОК/;										2;			ок/ки;			ка/ков;			ку/кам;			ок/ки;			ком/ками;		ке/ках;			ка/ков;			
	|М;		*ДОЛЛАР/*ДОЛЛАРА/*ДОЛЛАРОВ/;				012;		/ы;				а/ов;			у/ам;			/ы;				ом/ами;			е/ах;			а/ов;			
	|М;		ЦЕНТ/ЦЕНТА/ЦЕНТОВ/;							012;		/ы;				а/ов;			у/ам;			/ы;				ом/ами;			е/ах;			а/ов;			
	|М;		*РУБЛЬ/*РУБЛЯ/*РУБЛЕЙ/;						112;		ь/и;			я/ей;			ю/ям;			ь/и;			ем/ями;			е/ях;			я/ей;			
	|Ж;		*КОПЕЙКА/*КОПЕЙКИ/*КОПЕЕК/;					332;		йка/йки;		йки/ек;			йке/йкам;		йку/йки;		йкой/йками;		йке/йках;		йку/ек;			
	|М;		Б/В/Д/З/Л/М/Н/П/Р/С/Т/Ф/Ц/;					0;			/ы;				а/ов;			у/ам;			/ы;				ом/ами;			е/ах;			а/ов;			
	|М;		Г/К/Х/;										0;			/и;				а/ов;			у/ам;			/и;				ом/ами;			е/ах;			а/ов;			
	|М;		Ж/Ч/Ш/Щ/;									0;			/и;				а/ей;			у/ам;			/и;				ем/ами;			е/ах;			а/ей;			
	|М;		Й/;											1;			й/и;			я/ев;			ю/ям;			й/и;			ем/ями;			е/ях;			я/ев;			
	|Ж;		Ь/;											1;			ь/и;			и/ей;			и/ям;			ь/и;			ью/ями;			и/ях;			и/ей;			
	|М;		Ь/;											1;			ь/и;			я/ей;			ю/ям;			ь/и;			ем/ями;			е/ях;			я/ей;			
	|Ж;		ЛЯ/;										2;			ля/ли;			ли/ель;			ле/лям;			лю/ли;			лей/лями;		ле/лях;			лю/ли;			
	|Ж;		ХНЯ/;										2;			ня/ни;			ни/онь;			не/ням;			ню/ни;			ней/нями;		не/нях;			ню/ни;			
	|Ж;		РЯ/НЯ/;										1;			я/и;			и/ей;			е/ям;			ю/и;			ей/ями;		 	е/ях;			ю/ей;			
	|Ж;		СКА/МКА/НКА/;								2;			ка/ки;			ки/ок;			ке/кам;			ку/ки;			кой/ками;		ке/ках;			ку/ок;			
	|Ж;		ЖА/ЙА/ЧА/ША/ЩА/;							1;			а/и;			и/;				е/ам;			у/и;			ей/ами;			е/ах;			у/;				
	|Ж;		ГА/КА/ХА/;									1;			а/и;			и/;				е/ам;			у/и;			ой/ами;			е/ах;			у/;				
	|Ж;		ЦА/;										1;			а/ы;			ы/;				е/ам;			у/ы;			ей/ами;			е/ах;			у/;				
	|Ж;		ВНА/;										2;			на/ны;			ны/ен;			не/нам;			ну/ны;			ной/нами;		не/нах;			ну/ен;			
	|Ж;		А/;											1;			а/ы;			ы/;				е/ам;			у/ы;			ой/ами;			е/ах;			у/;				
	|С;		*ЕВРО/;										0;			/;				/;				/;				/;				/;				/;				/;				
	|С;		КО/;										1;			о/а;			а/ов;			у/ам;			о/а;			ом/ами;			е/ах;			о/;				
	|С;		О/;											1;			о/а;			а/;				у/ам;			о/а;			ом/ами;			е/ах;			о/;				
	|С;		Е/;											1;			е/я;			я/й;			ю/ям;			е/я;			ем/ями;			и/ях;			е/й;			";
	
	_Параметр0 = _Выражение;
	_Параметр1 = _Падеж;
	_Параметр2 = _Род;
	_Параметр3 = _Режим;
	_Параметр4 = _ФорматнаяСтрока;
	
	Если _Параметр0 = "_РазделитьСтроку" Тогда
		
		_ПозРазделителя = Найти(_Параметр1, _Параметр2); _Режим = Сред(_Параметр1, _ПозРазделителя + СтрДлина(_Параметр2)); Возврат Лев(_Параметр1, _ПозРазделителя - 1);
		
	ИначеЕсли _Параметр0 = "_ВМассивБезРазделителей" Тогда
		
		_МассивСтрок = Новый Массив(); Пока ИСТИНА Цикл _Поз = Найти(_Параметр1, _Параметр2); Если _Поз = 0 Тогда _МассивСтрок.Добавить(_Параметр1); Возврат _МассивСтрок;	КонецЕсли;	_МассивСтрок.Добавить(СокрЛП(Лев(_Параметр1, _Поз - 1))); _Параметр1 = СокрЛП(Сред(_Параметр1, _Поз + СтрДлина(_Параметр2))); КонецЦикла; Возврат _МассивСтрок;
		
	ИначеЕсли _Параметр0 = "_ВМассивСРазделителями" Тогда
		
		_МассивСтрок = Новый Массив(); _КолРазделителей = СтрДлина(_Параметр2);	Пока ИСТИНА Цикл _МинПозРазделителя = 10000; Для _ИндРазделителя = 1 По _КолРазделителей Цикл _ПозРазделителя = Найти(_Параметр1, Сред(_Параметр2, _ИндРазделителя, 1)); Если _ПозРазделителя > 0 Тогда _МинПозРазделителя = Мин(_МинПозРазделителя, _ПозРазделителя); КонецЕсли; КонецЦикла; Если _МинПозРазделителя = 10000 Тогда _МассивСтрок.Добавить(_Параметр1); Возврат _МассивСтрок; КонецЕсли; _МассивСтрок.Добавить(Лев(_Параметр1, _МинПозРазделителя - 1)); Для _Поз = _МинПозРазделителя По СтрДлина(_Параметр1) + 1 Цикл _ТекСимвол = Сред(_Параметр1, _Поз, 1); Если Найти(_Параметр2, _ТекСимвол) = 0 ИЛИ _Поз = СтрДлина(_Параметр1) + 1 Тогда _МассивСтрок.Добавить(Сред(_Параметр1, _МинПозРазделителя, _Поз - _МинПозРазделителя)); _Параметр1 = Сред(_Параметр1, _Поз); Прервать; КонецЕсли; КонецЦикла; КонецЦикла; 
		
	ИначеЕсли _Параметр0 = "_ПривестиПоДлинеИРегистру" Тогда
		
		_ИсходнаяСтрока 	= _Параметр1;
		_Образец		 	= _Параметр2;
		
		_Результат = ?(Лев(_Образец, 1) = "-", Лев(_ИсходнаяСтрока, 1), ?(Лев(_Образец, 1) <> НРег(Лев(_Образец, 1)), ВРег(Лев(_ИсходнаяСтрока, 1)), НРег(Лев(_ИсходнаяСтрока, 1))));
		Если НЕ Сред(_Образец, 2, 1) = "" Тогда
			_Результат = _Результат + ?(Сред(_Образец, 2, 1) = "-", Сред(_ИсходнаяСтрока, 2), ?(Сред(_Образец, 2, 1) <> НРег(Сред(_Образец, 2, 1)), ВРег(Сред(_ИсходнаяСтрока, 2)), НРег(Сред(_ИсходнаяСтрока, 2))));
		КонецЕсли;

		Возврат _Результат;
		
	ИначеЕсли _Параметр0 = "_ПросклонятьСлово" Тогда
		
		_СтрокаСлово	= _Параметр3; 
		
		Если _СтрокаСлово.Склонение = "-" ИЛИ _СтрокаСлово.Склонение = "!" Тогда 
			Возврат "";
		КонецЕсли;
		
		_ИсходнаяСтрока = _СтрокаСлово.Значение;
		_Метод = ?(Найти("ФИО", _СтрокаСлово.Субметод) > 0, "ФИО", _СтрокаСлово.Субметод);
		_СтрокаПадежи	= ?(Найти("ЧВ", _Метод) > 0, "ИРДВТПО", "РДВТП");
		
		_ПраваяЧасть = "";
		
		_ТаблицаПравила = Вычислить("_Правила" + _СтрокаСлово.Субметод);
		Для _НомСтр = 1 По СтрЧислоСтрок(_ТаблицаПравила) Цикл
			
			_СтрокаПравила = СтрПолучитьСтроку(_ТаблицаПравила, _НомСтр);
			
			Если Найти(_СтрокаПравила, ВРег(Прав(_ИсходнаяСтрока, 1)) + "/") = 0 Тогда Продолжить; КонецЕсли; 
			
			_РодПравила = СокрЛП(daСклонение("_РазделитьСтроку", _СтрокаПравила, ";", _ПраваяЧасть)); 
			Если (Найти(" МЖС", _Род) > 1 И НЕ ПустаяСтрока(_РодПравила) И Найти(_РодПравила, _Род) = 0 И _РодПравила <> "Р") Тогда Продолжить; КонецЕсли;
			
			_ЛеваяЧасть = daСклонение("_РазделитьСтроку", _ПраваяЧасть, ";", _ПраваяЧасть);
			_МассивОкончания = daСклонение("_ВМассивБезРазделителей", СокрЛП(_ЛеваяЧасть), "/");
			Для _Инд = 0 По _МассивОкончания.ВГраница() - 1 Цикл
				
				_СтрокаОкончание = _МассивОкончания[_Инд];
				
				Если НЕ ((ВРег(Прав(_ИсходнаяСтрока, СтрДлина(_СтрокаОкончание))) = ВРег(_СтрокаОкончание)) 
					ИЛИ (Лев(_СтрокаОкончание, 1) = "*" И ВРег(_ИсходнаяСтрока) = ВРег(Сред(_СтрокаОкончание, 2)))
					ИЛИ (Лев(_СтрокаОкончание, 1) = "+" И ВРег(Прав(_ИсходнаяСтрока, СтрДлина(_СтрокаОкончание) - 1)) = Сред(ВРег(_СтрокаОкончание), 2) И _СтрокаСлово.Тег = "Н")) Тогда 
					Продолжить;
				КонецЕсли;
				
				Если _Метод = "Д" ИЛИ _Метод = "Ч" Тогда 
					_ТегПравило = СокрЛП(daСклонение("_РазделитьСтроку", _ПраваяЧасть, ";", _ПраваяЧасть));
					_ТегПравило = ?(_Метод = "Ч" И СтрДлина(_ТегПравило) = 0, Сред("51222", Найти("1234", Прав(_ИсходнаяСтрока, 1)) + 1, 1), _ТегПравило); 
					
					Если СтрДлина(_ТегПравило) > 0 И ПустаяСтрока(_СтрокаСлово.Тег) Тогда
						_СтрокаСлово.Тег = _ТегПравило;
						_СтрокаСлово.Склонение = ?(_ТегПравило = "П", "!", _СтрокаСлово.Склонение); 
						Возврат "";
					КонецЕсли;
				КонецЕсли;
				
				Если _РодПравила = "Р" Тогда 
					_РодНайденный = Сред("МЖСН", _Инд + 1, 1);
					_СтрокаСлово.Тег = "Р"; 
				Иначе
					_РодНайденный = ?(СтрДлина(_РодПравила) = 1, _РодПравила, "");
				КонецЕсли;
				
				_СтрокаСлово.Род = _РодНайденный;
				
				Если _Метод = "ФИО" И ПустаяСтрока(_Род) И ПустаяСтрока(_РодНайденный) Тогда 
					Возврат ""; 
				КонецЕсли;
				
				Если _Метод = "В" И _СтрокаСлово.Склонение = "?" Тогда 
					_СтрокаСлово.Склонение = "";
					Возврат ""; 
				КонецЕсли;
				
				Если Найти(_СтрокаПадежи, _Падеж) = 0 Тогда 
					_СтрокаСлово.Склонение = "!";
					Возврат "";
				КонецЕсли;
				
				_Обрезка = СокрЛП(daСклонение("_РазделитьСтроку", _ПраваяЧасть, ";", _ПраваяЧасть));
				_Обрезка = Число(?(СтрДлина(_Обрезка) = 1, _Обрезка, Сред(_Обрезка, _Инд + 1, 1)));
				
				_МассивСклонения = daСклонение("_ВМассивБезРазделителей", СокрЛП(_ПраваяЧасть), ";");
				_Окончание = СокрЛП(_МассивСклонения[Найти(_СтрокаПадежи, _Падеж) - 1]);
				Если _Метод = "В" Тогда 
					_МассивОкончания = daСклонение("_ВМассивБезРазделителей", _Окончание, "/");
					_ИндОкончания = Число(Сред(?(_РодПравила = "Р", "00123", "00001"), Найти("МЖСН", ?(ПустаяСтрока(_Род), _РодНайденный, _Род)) + 1, 1));
					_Окончание = _МассивОкончания[_ИндОкончания];
				КонецЕсли;
				_СтрокаСлово.Значение = Лев(_ИсходнаяСтрока, СтрДлина(_ИсходнаяСтрока) - _Обрезка) + daСклонение("_ПривестиПоДлинеИРегистру", _Окончание, Прав(_ИсходнаяСтрока, 1) + Прав(_ИсходнаяСтрока, 1)); 
				_СтрокаСлово.Склонение = "!";
				Возврат "";
				
			КонецЦикла;
			
		КонецЦикла;
		
		Если _Метод = "Ч" Тогда
			_СтрокаСлово.Субметод = "В"; 
			_СтрокаСлово.Склонение = "?";
			Возврат daСклонение("_ПросклонятьСлово", _Падеж, "", _СтрокаСлово);
		Иначе
			_СтрокаСлово.Склонение = "!"; 
			Возврат  ""; 
		КонецЕсли;
		
	ИначеЕсли _Параметр0 = "_ПроверкаТипов" Тогда
		
		_ИсходнаяСтрока 	= _Параметр1;
		
		_СтруктураТипы = Новый Структура("ЕстьЦифры, ЕстьНеЦифры, ЕстьВРег, ЕстьНРег, Аббревиатура", Ложь, Ложь, Ложь, Ложь, Ложь);
		_СтрокаЦифры 				= "0123456789";
		_СтрокаЦифрыИРазделители 	= "0123456789. "; 
		_КолНРег = 0;
		
		Для _Поз = 1 По СтрДлина(_ИсходнаяСтрока) Цикл
			_ТекСимвол = Сред(_ИсходнаяСтрока, _Поз, 1);
			_СтруктураТипы.ЕстьЦифры 	= _СтруктураТипы.ЕстьЦифры ИЛИ Найти(_СтрокаЦифры, _ТекСимвол) > 0;
			_СтруктураТипы.ЕстьНеЦифры 	= _СтруктураТипы.ЕстьНеЦифры ИЛИ Найти(_СтрокаЦифрыИРазделители, _ТекСимвол) = 0;
			_СтруктураТипы.ЕстьВРег 	= _СтруктураТипы.ЕстьВРег ИЛИ _ТекСимвол <> НРег(_ТекСимвол);
			_СтруктураТипы.ЕстьНРег 	= _СтруктураТипы.ЕстьНРег ИЛИ _ТекСимвол <> ВРег(_ТекСимвол);
			_КолНРег = _КолНРег + (_ТекСимвол <> ВРег(_ТекСимвол));
		КонецЦикла; 
		
		_СтруктураТипы.Аббревиатура = _СтруктураТипы.ЕстьНеЦифры И (_КолНРег < Макс(СтрДлина(_ИсходнаяСтрока) - 1, 2) ИЛИ _СтруктураТипы.ЕстьЦифры);
		
		Возврат _СтруктураТипы;
		
	ИначеЕсли _Параметр0 = "?" Тогда 
		
		Возврат _Версия;
		
	КонецЕсли;
	
	_РежимЗапуска = ?(ПустаяСтрока(_Режим), "ФИО", ВРег(СокрЛП(_Режим))); 
	
	Если Найти("ФИО", Лев(_РежимЗапуска, 1)) > 0 Тогда
		_РегистрыШаблона 	= Новый Структура("ФАМИЛИЯ, ИМЯ, ОТЧЕСТВО, Ф, И, О", , , , "--", "--", "--"); 
		_Метод	 			= "ФИО";
	ИначеЕсли Найти("ДЧВ", _РежимЗапуска) > 0 Тогда
		_РегистрыШаблона 	= Новый Структура("А, Б, В, Г", "-", "-", "-", "-"); 
		_Метод	 			= _РежимЗапуска;
	Иначе
		Возврат "";
	КонецЕсли;
	_Разделители = " -+.,()/"""; 
	
	_МакросИзШаблона = _ФорматнаяСтрока;
	Если НЕ ПустаяСтрока(_ФорматнаяСтрока) Тогда
		
		Для Каждого _ЭлементРегистрыШаблона Из _РегистрыШаблона Цикл
			_Поз = Найти(ВРег(_МакросИзШаблона), _ЭлементРегистрыШаблона.Ключ);
			Если _Поз = 0 Тогда
				Продолжить;
			КонецЕсли;
			
			_СимволМакроса 		= Лев(_ЭлементРегистрыШаблона.Ключ, 1); 
			_НайденныйШаблон 	= Сред(_МакросИзШаблона, _Поз, СтрДлина(_ЭлементРегистрыШаблона.Ключ)); 
			_РегистрыШаблона[_СимволМакроса] = _НайденныйШаблон; 
			
			Если _Метод = "ФИО" Тогда
				_ПриведенныйМакрос = "%" + Найти("ФИО", _СимволМакроса); 
				_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, _НайденныйШаблон, _ПриведенныйМакрос);
			КонецЕсли;
		КонецЦикла;
		
		Если _Метод = "ФИО" Тогда
			Для _Ном = 1 По 3 Цикл
				_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, "%" + _Ном, "%" + Сред("ФИО", _Ном, 1));
			КонецЦикла; 
		КонецЕсли;
			
	КонецЕсли;
	
	_ТаблицаСлова = Новый ТаблицаЗначений;
	_ТаблицаСлова.Колонки.Добавить("Значение");
	_ТаблицаСлова.Колонки.Добавить("Субметод");
	_ТаблицаСлова.Колонки.Добавить("Род");
	_ТаблицаСлова.Колонки.Добавить("Тег");
	_ТаблицаСлова.Колонки.Добавить("Регистр");
	_ТаблицаСлова.Колонки.Добавить("Склонение");
	_ТаблицаСлова.Колонки.Добавить("Порядок", Новый ОписаниеТипов("Число"));
	
	_ПадежИтоговый	= Сред("ИИРДВТПОИРДВТПО", Найти("ИРДВТПО1234567", ВРег(_Падеж)) + 1, 1); 
	_РодИтоговый	= СокрЛП(Сред("  МЖСНМЖСН", Найти("?МЖСН1234", ВРег(_Род)) + 1, 1)); 
	_МакросПоУмолчанию = "";
	_ПозШаблонВход = 1;
	_ПозЧастиСтроки = 0;
	_СоставноеСлово = Ложь;
	_РодСклонения	= ?(_Метод = "Ч", "", _РодИтоговый); 
	
	_МассивЧастиСтроки = daСклонение("_ВМассивСРазделителями", _Выражение, _Разделители);
	Пока _ПозЧастиСтроки  0 И СтрДлина(_ТаблицаСлова[_ТаблицаСлова.Количество() - 1].Регистр) > 1 Тогда
			_ТаблицаСлова[_ТаблицаСлова.Количество() - 1].Тег = "."; 
		КонецЕсли;
			
		Если Найти(_Разделители, Лев(_ЧастьСтроки, 1)) > 0 ИЛИ (_Метод = "ФИО" И _ПозШаблонВход > СтрДлина(_РежимЗапуска)) Тогда 
			_МакросПоУмолчанию = _МакросПоУмолчанию + ?(_СоставноеСлово, "", _ЧастьСтроки); 
		Иначе
			_СтрокаСлово = _ТаблицаСлова.Добавить();
			
			Если Лев(_ЧастьСтроки, 1) = "\" Тогда
				_ЧастьСтроки = Сред(_ЧастьСтроки, 2);
				_СтрокаСлово.Склонение = "-";
			ИначеЕсли Лев(_ЧастьСтроки, 1) = "^" Тогда  
				_ЧастьСтроки = Сред(_ЧастьСтроки, 2);
				_СтрокаСлово.Склонение = "+"; 
			КонецЕсли; 
			
			_СтруктураТипы = daСклонение("_ПроверкаТипов", _ЧастьСтроки);
			
			Если _Метод = "Ч" И _СтрокаСлово.Склонение <> "-" И _СтрокаСлово.Склонение <> "+" И _СтруктураТипы.ЕстьЦифры И НЕ _СтруктураТипы.ЕстьНеЦифры Тогда 
				_МассивЧастиСубСтроки = daСклонение("_ВМассивСРазделителями", СокрЛП(ЧислоПрописью(_ЧастьСтроки, "Л = ru_RU", ",,,,,,,,0")), " ");
				_МассивЧастиСтроки.Удалить(_ПозЧастиСтроки);
				Для _ПозЧастиСубСтроки = 0 По _МассивЧастиСубСтроки.ВГраница() Цикл
					_МассивЧастиСтроки.Вставить(_ПозЧастиСтроки, _МассивЧастиСубСтроки[_МассивЧастиСубСтроки.ВГраница() - _ПозЧастиСубСтроки]);
				КонецЦикла; 
				_ЧастьСтроки = _МассивЧастиСтроки[_ПозЧастиСтроки];
			КонецЕсли;
			
			Если СтрДлина(_ЧастьСтроки)  0)) Тогда
					_СтруктураТипы.Аббревиатура = Истина; 
				КонецЕсли;
				
				Если _СтруктураТипы.Аббревиатура Тогда
					_СтрокаСлово.Регистр = _РегистрыШаблона.Г + _РегистрыШаблона.Г;
					_СтрокаСлово.Склонение = "-"; 
				Иначе
					_СтрокаСлово.Регистр = ?(_ПозШаблонВход = 1, _РегистрыШаблона.А, _РегистрыШаблона.Б) + _РегистрыШаблона.В;
				КонецЕсли;
				
				daСклонение("_ПросклонятьСлово", _ПадежИтоговый, _РодСклонения, _СтрокаСлово);
			КонецЕсли;
			
			Если НЕ _СоставноеСлово Тогда
				_ПозШаблонВход = _ПозШаблонВход + 1;
				_МакросПоУмолчанию = _МакросПоУмолчанию + "%" + _СимволМакроса;
			КонецЕсли;
			
		КонецЕсли;
		
		_ПозЧастиСтроки = _ПозЧастиСтроки + 1;
		
	КонецЦикла;
	
	_МакросИзШаблона = ?(_Метод = "ФИО" И НЕ ПустаяСтрока(_МакросИзШаблона), _МакросИзШаблона, _МакросПоУмолчанию);
	
	Если _Метод = "ФИО" Тогда
		Пока _ПозШаблонВход  0 Тогда
					_РодСклонения = "Н";
					_ПадежСклонения = "Р";
				Иначе	
					_РодСклонения = "Н";
					_ПадежСклонения = _ПадежИтоговый;
				КонецЕсли;
			Иначе 
				_РодСклонения = _СтрокаСлово.Род; 
				_ПадежСклонения = _ПадежИтоговый;
			КонецЕсли; 
			
		ИначеЕсли _СтрокаСлово.Субметод = "Д" И _СтрокаСлово.Тег = "К" Тогда 
			
			_ТекИндекс = _ТаблицаСлова.Индекс(_СтрокаСлово);
			Пока ИСТИНА Цикл 
				_СледИндекс = _ТекИндекс + 1;
				Если _ТекИндекс + 1 > _ТаблицаСлова.Количество() - 1 ИЛИ ПустаяСтрока(_ТаблицаСлова[_ТекИндекс + 1].Тег) Тогда 
					Прервать;
				Иначе
					Если _ТаблицаСлова[_СледИндекс].Тег = "П" Тогда 
						_СтрокаСлово.Склонение = "-"; 
						Прервать;
					КонецЕсли; 
					_ТекИндекс = _ТекИндекс + 1;
				КонецЕсли; 
			КонецЦикла;
			
		КонецЕсли;
		
		daСклонение("_ПросклонятьСлово", _ПадежСклонения, _РодСклонения, _СтрокаСлово);
		
		_РодНайденный = ?(НЕ ПустаяСтрока(_СтрокаСлово.Род), _СтрокаСлово.Род, _РодНайденный);
		_РодСклонения = ?(_Метод = "ФИО" И НЕ ПустаяСтрока(_РодНайденный), _РодНайденный, _РодСклонения); 
		
	КонецЦикла;
	
	Если _Род = "?" Тогда 
		_Род = ?(ПустаяСтрока(_РодНайденный), "?", _РодНайденный);
	КонецЕсли; 
	
	_РодИтоговый = ?(ПустаяСтрока(_РодИтоговый), ?(ПустаяСтрока(_РодНайденный), "М", _РодНайденный), _РодИтоговый); 
	_РезультатСклонения = "";
	
	Для Каждого _СтрокаСлово Из _ТаблицаСлова Цикл
		
		daСклонение("_ПросклонятьСлово", _ПадежИтоговый, _РодИтоговый, _СтрокаСлово); 
		_СтрокаСлово.Значение = daСклонение("_ПривестиПоДлинеИРегистру", _СтрокаСлово.Значение, _СтрокаСлово.Регистр);
		
		Если _СтрокаСлово.Тег = "Н" Тогда 
			_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Значение + "-";
			Продолжить;
		КонецЕсли;
		
		_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Значение;
		
		Если _Метод = "ФИО" Тогда
			_ЭлементШаблона = "%" + _СтрокаСлово.Субметод;
			Если НЕ ЗначениеЗаполнено(_СтрокаСлово.Значение) Тогда 
				_Поз = Найти(_МакросИзШаблона, _ЭлементШаблона);
				_ЭлементШаблона = ?(_Поз > 1 И Сред(_МакросИзШаблона, _Поз - 1, 1) = " ", " ", "") + _ЭлементШаблона + ?(_Поз <> 0 И Сред(_МакросИзШаблона, _Поз + 2, 1) = ".", ".", ""); 
			КонецЕсли;
			_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Тег; 
		Иначе
			_ЭлементШаблона = "%С" + Формат(_ТаблицаСлова.Индекс(_СтрокаСлово) + 1, "ЧЦ=2; ЧВН=");
		КонецЕсли;
		
		_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, _ЭлементШаблона, _РезультатСклонения);
		
		_РезультатСклонения = "";
		
	КонецЦикла;
	
	Возврат _МакросИзШаблона;
		
КонецФункции  // daСклонение
#КонецОбласти
#Область XML
Функция СериализоватьXML(Данные)	
    ЗаписьXML	= Новый ЗаписьXML; 
    ЗаписьXML.УстановитьСтроку();
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Данные); 
    Возврат ЗаписьXML.Закрыть();	
КонецФункции  // СериализоватьXML()
Функция ДесериализоватьXML(СтрокаXML)
    ЧтениеXML    = Новый ЧтениеXML();
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
	Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
КонецФункции  // ДесериализоватьXML()
#КонецОбласти
#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Заполнение_переменных
ЦветВыделенияПараметров	= "red";
#КонецОбласти
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
#Область Комментарии

#КонецОбласти
//////////////////////////////////////////////////////////////


#КонецЕсли

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

TODO:

  • Добавить работу с таблицами.
  • Добавить работу с "обычными формами".
  • Вынести некоторые захардкоженные переменные в переменные модуля объекта
  • Доработать форматирование и склонение из параметров в docx макете
  • Опционально хранить настройки пользователя

 

Postscriptum:

Обработку выкладываю бесплатно. В надеждах на дальнейшее её развитие и помощь сообщества в этом (банально не хватает времени на все).

Связаться со мной можно через Инфостарт 

Любая помощь приветсвуется.

18

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

Наименование Файл Версия Размер
Пример подключаемой печатной формы.
.epf 53,19Kb
24.07.18
17
.epf 1.1 53,19Kb 17 Скачать

См. также

Лучшие комментарии
13. 🅵🅾️🆇 201 15.11.18 18:12 Сейчас в теме
Исправил "исчезновение" пробелов рядом с переменными
Оно возникало от того, что пропадали пробелы в содержимом "w:r/w:t[@xml:space='preserve']" блоков.

Пример модуля обработки:
http://git.pfx.pw/snippets/1

Обратите внимание на область Работа_с_word
и в частности на добавленную функцию: ЗаполнитьПробелы()
и закоменченное добавление неразрывных пробелов в функции ЗаполнитьПараметрМакета()
Остальные комментарии
Избранное Подписка Сортировка: Древо
1. newold2 123 25.07.18 12:31 Сейчас в теме
1 стартмани - это бесплатно?
2. 🅵🅾️🆇 25.07.18 12:36 Сейчас в теме
(1) Вы пропустили в публиции следующий абзац:
UPD: К сожалению Инфостарт не дает бесплатно выложить обработку, поэтому прикрепляю листинг (ну или напишите мне):


И вы всегда можете написать мне, Я обязательно отвечу, если в телегу - то практически моментально :3
Адрес в профиле, редактор не позволил мне прикрепить бесплатно и указать контактные данные.
Также инфостарт не разрешает давать линк на гитхаб :c
jONES1979; +1 Ответить
9. jONES1979 15.08.18 08:35 Сейчас в теме
Здравствуйте!
А этот проект есть на гитхаб? Можно ссылку или идентификатор для поиска?
10. 🅵🅾️🆇 15.08.18 11:58 Сейчас в теме
(9) Привет. Да, есть.
Ссылки на гит тут, вроде как, запрещено прикреплять.
Но в отдельный репозиторий не выносил, а также никак не могу заставить себя выкладывать на гит именно исходный код, а не бинарники.

Давайте попробуем так, оставлю свой никнейм: PlugFox
И некий относительный путь: ones/Обработки и отчеты/Обработки/RMR СоглашениеОНеразглашенииИнформации.epf

Если что - всегда отвечу в личку.
jONES1979; +1 Ответить
3. newold2 123 25.07.18 17:53 Сейчас в теме
Каюсь, извиняюсь - действительно пропустил. Подход понравился, сам делал нечто подобное.
4. 🅵🅾️🆇 25.07.18 18:10 Сейчас в теме
(3) Можете написать в личку - обязательно поделюсь)
Если есть желание поучаствовать - с радостью приму помощь, нереализованный фичи и улучшения описал в статье.

Обработочку сделал недавно, когда поймал себя на мысли, что каждый раз при создании новой печатной формы, Я делаю одно и тоже) Посему аккуратно все оформил, и преследовал некую модульность и простоту разработки.

По сути чтоб создать на её основе новую печатную форму - потребуется изменить шаблон и подправить код всего в одной функции. Причем если новая печатная форма также будет касаться сотрудника - можно ограничится только редактированием макета.

ЗЫ: есть еще подключаемая, самозаполняемая печатная форма по справкам по сотруднику.
Но код там местами не очень, поэтому выложить могу только обфусцированной, иначе мне будет слегка неуютно)
Прикрепленные файлы:
5. spy-83 183 26.07.18 09:20 Сейчас в теме
картинки из 1с можно вставить в макет word с помощью вашей обработки?
к примеру вывести основное изображение номенклатуры
6. 🅵🅾️🆇 26.07.18 09:36 Сейчас в теме
(5) Пока нельзя, но технически в этом нет ничего сложного.
Вордовский файл это по сути архив с xml файлами и вложениями.
Если вставить в шаблон картинку, то она окажется в отдельном каталоге и её можно будет заменить.
7. spy-83 183 26.07.18 10:07 Сейчас в теме
если выводить таблицу из 1с, то заранее неизвестно количество строк, значит заранее не получится вставить саму картинку.
8. 🅵🅾️🆇 26.07.18 10:40 Сейчас в теме
(7)
заранее неизвестно количество строк

Исходные файлы xml ворда толком ничем не отличаются от html документа.
Вы же не будете утверждать, что невозможно сверстать веб страничку в 1с?)

заранее не получится вставить саму картинку

Ну как вы обычно выводите картинки в табличный документ?
Вы вставляете некую заготовку, а потом заменяете её на нужное изображение.

Так и здесь. При разархивировании docx получаете изображение которое вставили в документ шаблоном ранее.
Просто заменяете его на двоичные данные из вашего справочника номенклатур/файлов.

Вообще xml документы имеют ссылки между собой и вполне ясно говорят, что и как они подключают.
Если тут есть гуру XDTO - то в теории можно будет научить 1с'ку читать ворд довольно изящно.

Я с радостью бы это все сделал, но у меня очень много другой работы, поэтому данный функционал мной будет реализован в удобной для использования форме, как только это потребуется по работе.
11. Sanek_159 1 30.10.18 11:29 Сейчас в теме
Добрый день.

Подскажите, в обработке при замене параметров и их разделения используется неразрывный пробел. Можно как то сделать обычный пробел?
Если в Процедуре "ЗаполнитьПараметрМакета" где устанавливается "ПараметрМакета" заменить Символы.НПП на " " (пробел), то параметры все открываются слитно с соседними словами.

Неразрывный пробел не подходит, т.к. параметров может быть много и ворд распределяет текст не корректно.
12. 🅵🅾️🆇 201 30.10.18 11:32 Сейчас в теме
(11) Привет, насколько помню, можно подредактировать и сделать более удобно.
Насколько помню, это связано с тем, что редактируя макет Word в Word'е он вставляет туда кучу лишнего мусора и без неразрывного пробела, в некоторых случаях, слова могут слипаться.

Я постараюсь сделать более удобно в дальнейшем, но не в ближайшее время, тк сильно загружен, да еще и пишу огромную статью про inline webhook telegram бота.
13. 🅵🅾️🆇 201 15.11.18 18:12 Сейчас в теме
Исправил "исчезновение" пробелов рядом с переменными
Оно возникало от того, что пропадали пробелы в содержимом "w:r/w:t[@xml:space='preserve']" блоков.

Пример модуля обработки:
http://git.pfx.pw/snippets/1

Обратите внимание на область Работа_с_word
и в частности на добавленную функцию: ЗаполнитьПробелы()
и закоменченное добавление неразрывных пробелов в функции ЗаполнитьПараметрМакета()
Оставьте свое сообщение