gifts2017

daСклонение: склонение ФИО, должностей, чисел, прилагательных, существительных на языке 1С + ТестЦентр

Опубликовал Михаил Андропов (daMaster) в раздел Программирование - Универсальные функции

Функция предназначена для склонения выражений, которые часто требуется при формировании печатных форм договоров и прочих печатных форм. Функция склоняет по падежам ФИО, должности, числительные, валюты, единицы измерения, предметы. Также функция склоняет глаголы и прилагательные по числам и родам и существительные по числам. Имеется режим определения рода переданного выражения. Поддержка форматной строки для вывода результата. Функция не использует внешние библиотеки и веб-сервисы, написана на чистом языке 1С, и поэтому легко встраивается в любую конфигурацию или внешнюю обработку. Правила склонения оформлены в виде таблицы и могут быть легко изменены при необходимости.

На данный момент существует минимум 10 подобных функций для склонения ФИО, не считая стандартной, которые можно вызывать из кода . Зачем написана еще одна, и чем она лучше остальных? Была протестирована каждая из найденных функций, но ни одна из них не подошла - либо большое количество ошибок при склонении, либо неудобство использования, либо и то и другое.

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

Все функции склонения были проверены на рабочих данных - это справочники сотрудников и контрагентов реальной организации. Ошибки, причем зачастую для ФИО, которые трудно отнести к экзотическим, возникали у КАЖДОЙ протестированной функции, в том числе и у веб-сервиса "Морфер", который оперативнее всего поддерживается и показывает лучшие результаты. Очень много ошибок у любимой многими функции "Крохотулька" - 30%, немного лучшие результаты у функции "Коган" - 26%. Поэтому не стоит испытывать иллюзий - ошибки есть и в данном алгоритме, даже после тысяч тестовых прогонов. Важная особенность этой функции - все правила склонения описаны в таблицах простого формата, поэтому при обнаружении ошибок или расхождений в написании имен и фамилий, нет необходимости ждать обновления функции - нетрудно самостоятельно исправить некорректное правило или добавить новое в таблицу.

Таблица правил склонения

Для вывода результата можно использовать форматную строку в максимально понятном формате, вида "Фамилия Имя Отчество" или "И.О. Фамилия". При отутствии форматной строки, функция старается максимально сохранить формат исходной строки. При нестандартном порядке следования частей ФИО, порядок можно указать в параметре вызова функции, например "ФИО", "ИОФ", "ИФ". Род выражения не всегда известен заранее, поэтому есть возможность автоматического определения рода. Определение происходит сначала по Отчеству, при неудаче - по Фамилии, затем по Имени

Функция также склоняет должности, причем из-за меньшей вариативности склонений, чем для ФИО, склонение должностей происходит практически без ошибок, что было подтверждено множеством различных тестов.

Имеется возможность склонения по падежам и по родам числительных, причем в виде прописи ("два") либо числового значения (2). Вместе с числительным в функцию может быть передано исчислимое в начальной форме (именительный падеж, единственное число), например "8 доска" -> "Т - восемью досками", "15 рубль" -> "Р - пятнадцати рублей". Добавлена особая форма винительного падежа для склонения одушевленных существительных: "В - про сорок один мешок", "О - про сорок одного маляра".

Также склоняются по падежам, родам и числам прилагательные, существительные и их сочетания из начальной формы: "Генеральная доверенность" -> "Р - Генеральных доверенностей". Глаголы можно склонять по родам и числам: "Утвердило ответственное лицо" -> "Н - Утвердили ответственные лица". Более подробные примеры использования - в комментариях в листинге функции.

Если функция оказалась полезной для вас, скачайте тест-центр!

Код функции:

//(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Склонение("_ВМассивСРазделителями", _Выражение, _Разделители);
	Пока _ПозЧастиСтроки <= _МассивЧастиСтроки.ВГраница() Цикл
		
		_ЧастьСтроки = _МассивЧастиСтроки[_ПозЧастиСтроки];
		
		Если _Метод = "ФИО" И НЕ ПустаяСтрока(_МакросИзШаблона) И Лев(_ЧастьСтроки, 1) = "." И _ТаблицаСлова.Количество() > 0 И СтрДлина(_ТаблицаСлова[_ТаблицаСлова.Количество() - 1].Регистр) > 1 Тогда
			_ТаблицаСлова[_ТаблицаСлова.Количество() - 1].Тег = "."; 
		КонецЕсли;
			
		Если Найти(_Разделители, Лев(_ЧастьСтроки, 1)) > 0 ИЛИ (_Метод = "ФИО" И _ПозШаблонВход > СтрДлина(_РежимЗапуска)) Тогда 
			_МакросПоУмолчанию = _МакросПоУмолчанию + ?(_СоставноеСлово, "", _ЧастьСтроки); 
		Иначе
			_СтрокаСлово = _ТаблицаСлова.Добавить();
			
			Если Лев(_ЧастьСтроки, 1) = "\" Тогда
				_ЧастьСтроки = Сред(_ЧастьСтроки, 2);
				_СтрокаСлово.Склонение = "-";
			ИначеЕсли Лев(_ЧастьСтроки, 1) = "^" Тогда  
				_ЧастьСтроки = Сред(_ЧастьСтроки, 2);
				_СтрокаСлово.Склонение = "+"; 
			КонецЕсли; 
			
			_СтруктураТипы = daСклонение("_ПроверкаТипов", _ЧастьСтроки);
			
			Если _Метод = "Ч" И _СтрокаСлово.Склонение <> "-" И _СтрокаСлово.Склонение <> "+" И _СтруктураТипы.ЕстьЦифры И НЕ _СтруктураТипы.ЕстьНеЦифры Тогда 
				_МассивЧастиСубСтроки = daСклонение("_ВМассивСРазделителями", СокрЛП(ЧислоПрописью(_ЧастьСтроки, "Л = ru_RU", ",,,,,,,,0")), " ");
				_МассивЧастиСтроки.Удалить(_ПозЧастиСтроки);
				Для _ПозЧастиСубСтроки = 0 По _МассивЧастиСубСтроки.ВГраница() Цикл
					_МассивЧастиСтроки.Вставить(_ПозЧастиСтроки, _МассивЧастиСубСтроки[_МассивЧастиСубСтроки.ВГраница() - _ПозЧастиСубСтроки]);
				КонецЦикла; 
				_ЧастьСтроки = _МассивЧастиСтроки[_ПозЧастиСтроки];
			КонецЕсли;
			
			Если СтрДлина(_ЧастьСтроки) <= 1 И НЕ _СтруктураТипы.ЕстьЦифры Тогда 
				_СтрокаСлово.Склонение = "-";
			КонецЕсли;
			_СтрокаСлово.Значение = _ЧастьСтроки;
			
			Если _Метод = "ФИО" Тогда
				Если _ПозЧастиСтроки <= _МассивЧастиСтроки.ВГраница() - 2 И _МассивЧастиСтроки[_ПозЧастиСтроки + 1] = "-" Тогда 
					_СтрокаСлово.Тег = "Н"; 
					_СоставноеСлово = Истина;
				Иначе
					_СоставноеСлово = Ложь;
				КонецЕсли; 
				_СимволМакроса = Сред(_РежимЗапуска, _ПозШаблонВход, 1);
				_СтрокаСлово.Регистр = _РегистрыШаблона[_СимволМакроса];
				_СтрокаСлово.Субметод = Сред(_РежимЗапуска, _ПозШаблонВход, 1); 
				_СтрокаСлово.Порядок = Найти("ОФИ", _СтрокаСлово.Субметод) * 100 + _ПозЧастиСтроки; 
			Иначе
				_СтрокаСлово.Субметод = _Метод;
				_СимволМакроса = "С" + Формат(_ПозШаблонВход, "ЧЦ=2; ЧВН="); 
				
				Если _Метод = "Ч" И ((_ПозЧастиСтроки + 1 <= _МассивЧастиСтроки.ВГраница() И Найти("/-.", Лев(_МассивЧастиСтроки[_ПозЧастиСтроки + 1], 1)) > 0)
					ИЛИ (_ПозЧастиСтроки - 1 >= 0 И Найти("/-.", Лев(_МассивЧастиСтроки[_ПозЧастиСтроки - 1], 1)) > 0)) Тогда
					_СтруктураТипы.Аббревиатура = Истина; 
				КонецЕсли;
				
				Если _СтруктураТипы.Аббревиатура Тогда
					_СтрокаСлово.Регистр = _РегистрыШаблона.Г + _РегистрыШаблона.Г;
					_СтрокаСлово.Склонение = "-"; 
				Иначе
					_СтрокаСлово.Регистр = ?(_ПозШаблонВход = 1, _РегистрыШаблона.А, _РегистрыШаблона.Б) + _РегистрыШаблона.В;
				КонецЕсли;
				
				daСклонение("_ПросклонятьСлово", _ПадежИтоговый, _РодСклонения, _СтрокаСлово);
			КонецЕсли;
			
			Если НЕ _СоставноеСлово Тогда
				_ПозШаблонВход = _ПозШаблонВход + 1;
				_МакросПоУмолчанию = _МакросПоУмолчанию + "%" + _СимволМакроса;
			КонецЕсли;
			
		КонецЕсли;
		
		_ПозЧастиСтроки = _ПозЧастиСтроки + 1;
		
	КонецЦикла;
	
	_МакросИзШаблона = ?(_Метод = "ФИО" И НЕ ПустаяСтрока(_МакросИзШаблона), _МакросИзШаблона, _МакросПоУмолчанию);
	
	Если _Метод = "ФИО" Тогда
		Пока _ПозШаблонВход <= СтрДлина(_РежимЗапуска) Цикл 
			_СтрокаСлово = _ТаблицаСлова.Добавить();
			_СтрокаСлово.Субметод = Сред(_РежимЗапуска, _ПозШаблонВход, 1);
			_СтрокаСлово.Склонение = "-"; 
			_ПозШаблонВход = _ПозШаблонВход + 1;
		КонецЦикла;
		_ТаблицаСлова.Сортировать("Порядок");
	КонецЕсли;
	
	_РодНайденный	= ""; 
	
	Для Каждого _СтрокаСлово Из _ТаблицаСлова Цикл
		
		_ПадежСклонения = _ПадежИтоговый;
		
		Если _СтрокаСлово.Субметод = "Ч" Тогда 
			
			_СледИндекс = _ТаблицаСлова.Индекс(_СтрокаСлово) + 1;
			_РодСклонения = _РодИтоговый;
			Если _СледИндекс <= _ТаблицаСлова.Количество() - 1 И НЕ ПустаяСтрока(_ТаблицаСлова[_СледИндекс].Род) Тогда
				_РодСклонения = _ТаблицаСлова[_СледИндекс].Род;
			КонецЕсли;
			
		ИначеЕсли _СтрокаСлово.Субметод = "В" Тогда 
			
			_ТипСклонения = "";
			_ПредИндекс = _ТаблицаСлова.Индекс(_СтрокаСлово) - 1;
			Пока ИСТИНА Цикл 
				Если _ПредИндекс < 0 Тогда
					Прервать;
				ИначеЕсли _ТаблицаСлова[_ПредИндекс].Субметод = "Ч" Тогда
					_ТипСклонения = _ТаблицаСлова[_ПредИндекс].Тег; 
					Прервать;
				Иначе
					_ПредИндекс = _ПредИндекс - 1;
				КонецЕсли;
			КонецЦикла;
			
			Если _ТипСклонения = "1" Тогда 
				_РодСклонения = "";
				_ПадежСклонения = _ПадежИтоговый;
			ИначеЕсли _ТипСклонения = "2" Тогда 
				Если Найти("ИВ", _ПадежИтоговый) > 0 Тогда
					_РодСклонения = ?(_СтрокаСлово.Тег = "Р", "Н", ""); 
					_ПадежСклонения = "Р";
				Иначе	
					_РодСклонения = "Н";
					_ПадежСклонения = _ПадежИтоговый;
				КонецЕсли; 
			ИначеЕсли _ТипСклонения = "5" Тогда 
				Если Найти("ИВ", _ПадежИтоговый) > 0 Тогда
					_РодСклонения = "Н";
					_ПадежСклонения = "Р";
				Иначе	
					_РодСклонения = "Н";
					_ПадежСклонения = _ПадежИтоговый;
				КонецЕсли;
			Иначе 
				_РодСклонения = _СтрокаСлово.Род; 
				_ПадежСклонения = _ПадежИтоговый;
			КонецЕсли; 
			
		ИначеЕсли _СтрокаСлово.Субметод = "Д" И _СтрокаСлово.Тег = "К" Тогда 
			
			_ТекИндекс = _ТаблицаСлова.Индекс(_СтрокаСлово);
			Пока ИСТИНА Цикл 
				_СледИндекс = _ТекИндекс + 1;
				Если _ТекИндекс + 1 > _ТаблицаСлова.Количество() - 1 ИЛИ ПустаяСтрока(_ТаблицаСлова[_ТекИндекс + 1].Тег) Тогда 
					Прервать;
				Иначе
					Если _ТаблицаСлова[_СледИндекс].Тег = "П" Тогда 
						_СтрокаСлово.Склонение = "-"; 
						Прервать;
					КонецЕсли; 
					_ТекИндекс = _ТекИндекс + 1;
				КонецЕсли; 
			КонецЦикла;
			
		КонецЕсли;
		
		daСклонение("_ПросклонятьСлово", _ПадежСклонения, _РодСклонения, _СтрокаСлово);
		
		_РодНайденный = ?(НЕ ПустаяСтрока(_СтрокаСлово.Род), _СтрокаСлово.Род, _РодНайденный);
		_РодСклонения = ?(_Метод = "ФИО" И НЕ ПустаяСтрока(_РодНайденный), _РодНайденный, _РодСклонения); 
		
	КонецЦикла;
	
	Если _Род = "?" Тогда 
		_Род = ?(ПустаяСтрока(_РодНайденный), "?", _РодНайденный);
	КонецЕсли; 
	
	_РодИтоговый = ?(ПустаяСтрока(_РодИтоговый), ?(ПустаяСтрока(_РодНайденный), "М", _РодНайденный), _РодИтоговый); 
	_РезультатСклонения = "";
	
	Для Каждого _СтрокаСлово Из _ТаблицаСлова Цикл
		
		daСклонение("_ПросклонятьСлово", _ПадежИтоговый, _РодИтоговый, _СтрокаСлово); 
		_СтрокаСлово.Значение = daСклонение("_ПривестиПоДлинеИРегистру", _СтрокаСлово.Значение, _СтрокаСлово.Регистр);
		
		Если _СтрокаСлово.Тег = "Н" Тогда 
			_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Значение + "-";
			Продолжить;
		КонецЕсли;
		
		_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Значение;
		
		Если _Метод = "ФИО" Тогда
			_ЭлементШаблона = "%" + _СтрокаСлово.Субметод;
			Если НЕ ЗначениеЗаполнено(_СтрокаСлово.Значение) Тогда 
				_Поз = Найти(_МакросИзШаблона, _ЭлементШаблона);
				_ЭлементШаблона = ?(_Поз > 1 И Сред(_МакросИзШаблона, _Поз - 1, 1) = " ", " ", "") + _ЭлементШаблона + ?(_Поз <> 0 И Сред(_МакросИзШаблона, _Поз + 2, 1) = ".", ".", ""); 
			КонецЕсли;
			_РезультатСклонения	= _РезультатСклонения + _СтрокаСлово.Тег; 
		Иначе
			_ЭлементШаблона = "%С" + Формат(_ТаблицаСлова.Индекс(_СтрокаСлово) + 1, "ЧЦ=2; ЧВН=");
		КонецЕсли;
		
		_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, _ЭлементШаблона, _РезультатСклонения);
		
		_РезультатСклонения = "";
		
	КонецЦикла;
	
	Возврат _МакросИзШаблона;
		
КонецФункции

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

Наименование Файл Версия Размер
Тест-центр для проверки склонений и набор тестов (v.17.06.15) 51
.ZIP 638,32Kb
17.06.15
51
.ZIP 17.06.2015 638,32Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Марина Чирина (chmv) 16.02.15 10:22
2. Александр Савченко (invertercant) 16.02.15 12:12
Тоже была недавно задача склонения произвольных словосочетаний. Воспользовался готовой dll.
Как заполнял и систематизировал таблицу правил? Сидел и склонял подряд все имена?
3. Михаил Андропов (daMaster) 16.02.15 12:38
(1) chmv,

Я в статье уже писал, какие недостатки у .dll, распишу подробнее:
    - .dll необходимо регистрировать на каждом компьютере, где должен работать механизм склонений, если таких компьютеров много - это не самая простая и быстрая работа
    - политика IT-безопасности компании может запрещать подобные действия, например у нас 1С работает на ферме терминальных серверов, и на эти сервера вообще не подобраться
    - если планируется написать универсальную обработку, использующую механизм склонений, которая будет широко распространяться, в дистрибутив потребуется включать эту .dll с инструкциями, как ее зарегистрировать
    - .dll имеет закрытый исходный код, и в случае обнаружения ошибочных склонений (а ошибки, повторюсь, есть в каждом из существующих алгоритмов склонений), вы не сможете исправить ошибки самостоятельно, придется ждать выпуска новой версии .dll, которого можно и не дождаться
Кстати, во время тестирования на реальных данных библиотека padeg.dll при некоторых входных значениях у меня намертво зависала, приходилось перезапускать сеанс 1С.
opx; and-blag; dedkov; maXon777; UralKIT; molodoi1sneg; +6 Ответить 1
4. Михаил Андропов (daMaster) 16.02.15 12:50
(2) invertercant, я нашел в сети исходные коды около десятка процедур склонения, причем не только на языке 1С (например, "NamecaseLib" и "Петрович"), и первоначальные правила набрал оттуда. Затем прогонял различные тесты - как специальные тесты от авторов процедур склонения, так и импортированные справочники из реальных конфигураций, и по результатам тестов дополнял правила. Если вы скачаете архив из статьи - обнаружите некоторые из этих тестов, а также ТестЦентр, чтобы тесты прогонять и самостоятельно создавать свои)
5. Яков Коган (Yashazz) 16.02.15 19:20
Баян. Смотрите все сюда: http://infostart.ru/public/16470/ - и не столько на саму публикацию, хотя тоже неплоха, но и на комментарии к ней, там много полезного приведено, в т.ч. на регулярных выражениях.
6. Михаил Андропов (daMaster) 16.02.15 20:08
(5) Yashazz, я как бы и не скрывал, что баян, но зато баян-то - новый! А функция "Коган", написанная "студентом-программистом и студентом-лингвистом", есть в моем тест-центре, среди 11-ти прочих функций, можете ее протестировать. Если вам нравится алгоритм, который склоняет типа "Петров Юрий Васильевич -> Петрове Юрие Васильевиче", "Басинских Иван Семенович -> Басинскиха Ивана Семеновича", "Бережной Сергей Иванович -> Бережним Сергеем Ивановичем", то пользуйтесь ей на здоровье!
Результат теста на реальном справочнике сотрудников нашей организации: "Алгоритм: Коган (Я. и С. Коган); Вызовов: 7 225; Ошибок: 587 (8,12%)". Как по мне, то 8% ошибок - это слишком много.
7. Константин Юрин (kostyaomsk) 16.02.15 20:47
(3) daMaster, верно говорите в dll исключения не добавить :)
(5) Yashazz, не проверял, но видно автор текущей разработки взял за основу и добавил очень мощный редактор исключений для окончаний слов.
8. Михаил Андропов (daMaster) 17.02.15 00:00
(7) kostyaomsk, в качестве редактора как раз подойдет любой текстовый) Здесь более важен принцип,согласно которому правила склонения для всех окончаний не разбросаны по разным участкам кода в бесконечных ветвях "Если..Иначе", а объединены в наглядную табличку, которую можно поправить даже и не зная языка 1С!
9. Павел (Yimaida) 17.02.15 00:14
Видно, что проделана огромная работа. Автору большой +. Но читать и дорабатывать код, который пестрит нижними подчеркиваниями не совсем удобно (маленькая ложечка дегтя).
Я тоже как то искал в инете алгоритмы для склонений, но не видел, чтобы они склоняли составные должности и тем более глаголы (пока не тестировал но +). Плюс за возможность вносить исключения. То что автор собрал наиболее известные алгоритмы в одной обработке тоже +, только вот я бы добавил ссылки на первоисточники (авторам будет приятно). Для ЗУП просто незаменимая функция, из разряда must have.
10. Михаил Андропов (daMaster) 17.02.15 00:43
(9) Yimaida, все переменные начинаются с _НижнихПодчеркиваний сознательно! Предполагается, что функция должна беспроблемно встраиваться в любой модуль, в любую форму, и при этом не портить значения реквизитов и глобальных переменных - вдруг на форме тоже окажется реквизит типа "Род" или "Метод"? В отличие от C++, в 1С с подчеркиваний именовать переменные не принято, поэтому вероятность конфликтов гораздо ниже. Ну и предполагается, что код обычный пользователь менять не будет, разве только не захочет добавить какой-нибудь более продвинутый функционал, в таком случае придется уже поразбираться в логике) А чтобы добавить исключение или исправить ошибочное правило, программировать не нужно - редактируйте таблицы склонений! Ну а ссылки на первоисточники я добавлю в credits для следующей версии.
корум; CratosX; +2 Ответить
11. Константин Юрин (kostyaomsk) 17.02.15 08:47
Такие вещи со склонением и списком исключений для серьезных внедрений. Даже нужно продумывать кто будет и как вносить исключения по словам. Это не для внешнего отчета по формированию печатных форм из ЗУП в холдинге например. Кадровики ругаются на некоторые ФИО, которые приходится ручками корректировать, а что делать. Тут более простая доработка нужна для хранения ислючений, причем где-то во внешнем "листке"
12. DAnry (DAnry) 18.02.15 11:56
Спасибо автору за труд. Подход к проблемы, я б сказал, фундаментальный. Особой похвалы заслуживает то, что сама функция выложена открыто.
13. Максим *** (premier) 18.02.15 13:42
Впечатляет! Особенно результаты тестов. И скорость обработки неплохая. Поставлю "+" и возьму на вооружение.
P.S. Когда использовал компоненту склонения из типовой ЗиУП, долго смеялся, как она должности склоняет, а здесь, вроде бы, вполне корректно.
14. Сергей Сомов (sssomov@mail.ru) 18.02.15 15:28
Спасибо автору! Действительно гигантский труд. Даже должности через тире правильно склоняет.
15. Михаил Андропов (daMaster) 18.02.15 15:49
(11) kostyaomsk, я хотел отойти от списков исключений - зачем городить исключения, если можно модифицировать правила? Но вы правы насчет тех ситуаций, когда обрабатывать ошибки склонений будет не слишком продвинутый пользователь. Я подумаю насчет "добавления очень мощного редактора исключений" в будущих версиях.
16. Яков Коган (Yashazz) 18.02.15 19:54
(6) daMaster, вы мои сообщения читайте-то внимательно, прежде чем проценты ошибок приводить. Я вам про что говорил, разве про нашу с женой? Я вам про те, что в комментариях там, а именно, про супермонстра от Jurer'а, каковой ещё никто не превзошёл, полагаю, и вы тоже.
А просто тупо расписать всё в табличку - значит по сути хардкодить в заданных условиях, а не делать универсал. Jurer сделал иначе, и за то ему мегареспекты.
17. rasswet (rasswet) 19.02.15 11:04
благодарю, видно что работа проведена огромная! Спасибо за ваш труд.
18. Марина Чирина (chmv) 19.02.15 13:51
Должности плохо склоняются
19. Михаил Андропов (daMaster) 22.02.15 11:43
(18) chmv, вы бы привели примеры ошибок, я постараюсь исправить
20. Михаил Андропов (daMaster) 03.03.15 19:34
(16) Yashazz, а вы, походу, и есть тот самый Яков Коган, студент-филолог, тогда понятно, почему у вас так подгорело))
Алгоритм "Крохотулька" от Юрия Железнякова не только старейший для 1С, но и действительно выдающийся среди прочих, соотношение длины кода к функционалу поражает воображение 1С-ников. Уверен, на каком-нибудь конкурсе-олимпиаде среди программистов 1С он бы взял главный приз. Но реальная жизнь - это не олимпиада. От рабочей функции требуется высокая точность работы и минимальное количество ошибок. У "Крохотульки", к сожалению, процент ошибок слишком высок. Я сам долго пользовался "Крохотулькой" для формирования печатных форм договоров, но когда от менеджеров посыпались жалобы о многочисленных ошибках, пришлось написать свою функцию. Доработка "Крохотульки", чтобы исправить эти ошибки - занятие слишком трудоемкое, поскольку ее код не предназначен для чтения другим человеком, сокращение длины кода привело по сути к полной и безоговорочной обфускации. Юрию летит от меня плотный респект, но в работе "Крохотульку" больше не использую.
По сути ваших нелепых предъяв про "тупо расписать всё в табличку" - это вы здесь в комментариях "тупо" набрасываете. А "табличка" сделана в максимально наглядном виде специально, чтобы любой программист мог самостоятельно, не напрягаясь сверх меры, исправить ошибки или добавить свои правила.
herfis; Somebody1; dgolovanov; +3 Ответить
21. Иван Титов (Ibrogim) 10.03.15 10:59
(0) + за функцию. Можно ли вашу функцию использовать в коммерческих разработках (с указанием ссылки на вас в коде и в самой публикации) ?
22. Михаил Андропов (daMaster) 10.03.15 14:29
(21) Ibrogim, то, что выложено в интернет с исходниками, сложно запретить использовать) Так что, пользуйтесь на здоровье, естественно, с указанием ссылок и копирайтов. На данном этапе я заинтересован в обратной связи - поэтому буду благодарен за описание найденных ошибок и за конструктивные замечания и пожелания к функционалу.
dgolovanov; teflon; +2 Ответить
23. Александр Бочкарев (iiiaiiika) 21.05.15 15:53
Спасибо за функцию. Столкнулся только с одним глюком - когда в должности есть и мужской и женский род - получается фигня. В моем случае Начальник отдела транспортной логистики - при передаче параметра Мужской род в функцию первую половину склоняет корректно - Начальника отдела, потом транспортной - уже не склоняет, логистики - правильно. Но все равно гранд мерси.
24. Иван Пантелеев (RailMen) 28.05.15 11:26
Давно и много создаю печатные формы в различных форматах. С первого дня считал, что готовый макет должен быть максимально полно заполнен. Со склонениями, падежами и окончаниями. Пользователь не должен редактировать макет вообще т.к. это время/деньги - это очень важное требование. И как много копий было сломано и шишек набито по поводу склонений ФИО, должностей и подразделений, с окончаниями в зависимости от рода вообще беда. 100% решения нет. Но вот теперь есть идея (почему я сам не додумался???) и инструмент как ПРОТЕСТИРОВАТЬ различные варианты и выбрать лучший, а потом допиливать и перепиливать его, делая "самурайский меч" ))) Автору СПАСИБО!
25. Михаил Андропов (daMaster) 17.06.15 16:28
(23) iiiaiiika, благодарю за обнаруженную ошибку! Но ошибка была не мужском и женском родах - здесь все в порядке, дело в том, что слово "транспортной" оканчивается на "портной", а профессию "портной" склонять надо) Дело решилось добавлением одной звездочки (*) в таблицу правил, теперь "начальник отдела транспортной логистики" склоняется верно, а слово "портной" - только если слово встретилось целиком. В новой версии алгоритма еще несколько исправлений мелких ошибок.
dgolovanov; +1 Ответить
26. vlad Sa (1pioner) 01.07.15 08:48
Большое Спасибо. Мы работаем удаленно и через терминалы. dll - нет возможности использовать. Стандартный механизм глючный. и если ФИО более менее, то с названием должностей полная ... труба. Делал всякие исключения и т.д. Это обрабатывать, это слово нет и т.д. Разрастается алгоритм сильно, но всё равно ошибки. У вашего их пока не обнаружил, но посмотрим дальше... :-) Еще раз спасибо.
27. Гость 24.08.15 16:33
daMaster,

неправильно склоняет "Департамент", возможно решается? :
|М; ОРУБ/ДУВ/КЛАД/ВЕД/ЕВОД/ОВОД/ОХОД/ЛАЗ/ВАЛ/ДЕЛ/СОЛ/ОКОЛ/КОП/ВА­Р/ОПАР/ВЕС/МЕС/НОС/ТЕС/МЕНТ/; ; 0; а; у; а; ом; е;

неправильно склоняет "Дирекция", возможно решается? :
|Ж; ЦИЯ/; ; 3; ции; ции; цию ; цией; ции;

28. Гость 24.08.15 16:53
daMaster,
в должностях не склоняется "Редакция", "Служба", "Управление делами", "Отдела политика", "Канцелярия"
29. Иван Иванчиков (Dr.ZIG) 27.08.15 12:17
Нашёл выражение, которое никак не могу добавить в таблицу правил: "Кафедра бизнес-процессов". Нужно получить родительный падеж, т.е. "Кафедры бизнес-процессов". Если добавить "бизнес" в список исключений, то не будет склоняться просто бизнес, а "бизнес-процессов" не добавляется.
30. Михаил Андропов (daMaster) 28.08.15 17:58
(27) Гость, "Департамент", "Редакция", "Канцелярия" - это не должности, это наименования подразделений. Данный алгоритм склоняет должности, если они переданы в процедуру в начальной форме - в таком виде отдел имеет форму родительного падежа: "Секретарь дирекции", "Начальник управления делами", а не "Секретарь дирекция", "Начальник управление делами". В этой форме процедура отрабатывает корректно. Если же вы хотите склонять подразделения отдельно, из формы именительного падежа, следует использовать режим "В" (выражение).
31. Михаил Андропов (daMaster) 28.08.15 18:07
(29) Dr.ZIG, в данном случае вам стоит использовать режим склонения должностей "daСклонение("Кафедра бизнес-процессов", "Р", , "Д")", только в таблицу _ПравилаД добавьте правило для слова "кафедра":
Ж; СЕСТРА/ССА/КАФЕДРА/; ; 1; ы; е; у; ой; е; //Сестра, Стюардесса, Поэтесса
Dr.ZIG; virus2; +2 Ответить
32. Антонио (Fragster) 27.10.15 15:50
как мне получить из "доверенность номер 17 от 12 января 15 года" результат "действующего на основании доверенности номер 17 от 12 января 15 года"? Или как лучше подставлять в договоры данные?
33. Михаил Андропов (daMaster) 29.10.15 16:34
(32) Fragster, из первого вашего выражения второе вы никак не получите, алгоритм пока не обладает функцией телепатии) А если внимательно прочитать описание, то станет понятно, как алгоритм использовать. Преамбула договора действительно, часто содержит фразу наподобие "ООО "Ромашка" в лице <Пиотровского И.И./Пиотровской А.А.>, <действующего/действующей> на основании <устава/доверенности> № 66 от 14.08.2008 г.", где отдельные фразы изменяются в зависимости от рода и падежа.
Сначала мы определяем род представителя контрагента, заодно просклоняем его в родительный падеж:

ПоискРода = "?"; ПредставительКонтрагентаРП = daСклонение("Пиотровский И.И.", "Р", ПоискРода, "ФИО"); // ПредставительКонтрагентаРП = "Пиотровского И.И."

Затем глагол "действующий" склоняем в родительный падеж, а род склонения подставим тот, который определился по ФИО представителя контрагента:

ГлаголРП = daСклонение("действующий", "Р", ПоискРода, "В"); // ГлаголРП = "действующего"

Также просклоняем тип документа, это может быть "Устав" или "доверенность", род не указываем, он определится автоматически:

ТипДокументаРП = daСклонение("доверенность", "Р", , "В"); // ТипДокументаРП = "доверенности"

Теперь нам остается соединить строку:

СтрокаПреамбула = ИмяКонтрагента + " в лице " + ПредставительКонтрагентаРП + ", " + ГлаголРП + " на основании " + ТипДокументаРП + " № " + НомерДокумента + " от " + ДатаДокумента;
Fragster; +1 Ответить
34. romhik romhika (romhika) 09.12.15 17:09
Похоже "Глава представительства фирмы" спотыкается на Р. (от кого, чего?).

Правильного ответа ни дал ни кто.

Не правильно Крохотулька, daСклонение, finix, Плаха и Jack19.
Остальные результата не дали....
35. Михаил Андропов (daMaster) 10.12.15 15:32
(34) romhika, возможно, вы неправильно указали параметры вызова функции, для склонения должностей используется режим "Д". Проверил для версии от 17.06.2015, все правильно:
daСклонение("Глава представительства фирмы", "Р", , "Д", ) = "Главы представительства фирмы"
36. Максим *** (premier) 24.12.15 22:06
(0) daMaster, использую на работе Вашу функцию склонения вместо стандартной 1С-ной библиотеки склонений.
А если я буду внедрять печатные формы, к примеру, у своих заказчиков, это не будет нарушением авторских прав, если я укажу Ваше авторство?
37. Михаил Андропов (daMaster) 25.12.15 19:40
(36) premier, нет, нарушением не будет. А если вы укажете мое авторство - то мне приятно будет! )
корум; +1 Ответить
38. Максим *** (premier) 26.12.15 13:12
Спасибо. Жаль второй плюс поставить нельзя. Я бы поставил )))
daMaster; +1 Ответить
39. Сергей Смирнов (milanse) 13.01.16 19:24
Вставил, использовал, работает.
40. Андрей Казанцев (ander_) 27.01.16 13:03
(5) Yashazz,
что за "процедуры Jurer'а"? ссылочкой не поделитесь?
41. Михаил Андропов (daMaster) 27.01.16 16:43
(40) ander_,
Jurer - это Юрий Железняков. "процедуры Jurer'а" - это пресловутая "крохотулька". Вам нужно склонение цехов?
42. Андрей Казанцев (ander_) 28.01.16 08:06
(41) daMaster,
Спасибо за пояснение.
Нет, склонение цехов мне не нужно. Я почему-то решил что "процедуры Jurer'а" это какая-то библиотека для морфологического анализа ЕЯ, в т.ч. включающая в себя и склонение.
43. Кирилл Тюрин (turinx) 05.04.16 09:45
Большое спасибо, очень пригодилась функция!
44. Павел (virus2) 07.04.16 19:50
А как высшее образование склонять?
45. Оксана Мартынова (OksDallas) 01.08.16 06:38
Спасибо, пригодилось! Изменения можно внести без проблем.
46. Николай Гончаров (JohnConnor) 10.08.16 05:29
попробуйте просклонять слово - участок , получаем участока, участоку и т.д.
47. Оксана Мартынова (OksDallas) 12.08.16 07:40
Повторюсь, изменения можно внести без проблем
Например, про слово "участок":

_ПравилаВ = //Выражение
//Род; Окончания; Обрезка; И; Р; Д; В; Т; П; О;
"С; ЕНИЕ/; 1; е/я; я/й; ю/ям; е/я; ем/ями; и/ях; е/й;
//"Р" в колонке "Род" означает, слово родоизменяемое, и порядок окончания в списке определяет род слова

............................................

|М; ШОК/; 2; ок/ки; ка/ков; ку/кам; ок/ки; ком/ками; ке/ках; ка/ков;


можно изменить на

_ПравилаВ = //Выражение
//Род; Окончания; Обрезка; И; Р; Д; В; Т; П; О;
"С; ЕНИЕ/; 1; е/я; я/й; ю/ям; е/я; ем/ями; и/ях; е/й;
//"Р" в колонке "Род" означает, слово родоизменяемое, и порядок окончания в списке определяет род слова

..........................................

|М; ШОК/ТОК/; 2; ок/ки; ка/ков; ку/кам; ок/ки; ком/ками; ке/ках; ка/ков;
daMaster; +1 Ответить
48. Николай Овчинников (gkoles010) 25.08.16 14:23
Добрый день!
Есть ли возможность просклонять Порядковые числительные из введенного числа?
1 - Первый, Первого, Первому ...
20 - Двадцатый, Двадцатого, Двадцатому ...
49. Вячеслав (slawa) 27.08.16 05:43
Если склонять "Горобец" без указания рода, тогда срабатывает правило "М-; ОВЕЦ/БЕЦ/АМЕЦ/НЕЦ/ТЕЦ/; 2; ца; цу; ца; цом; це; Горовец"
Это специально сделано?
Мне кажется, правильней было-бы чтоб срабатывало правило без рода "; "
50. Михаил Андропов (daMaster) 19.10.16 12:10
(46) JohnConnor, склонение корней с беглыми гласными - сложный вопрос, по окончанию слова невозможно понять, беглая гласная или нет. Например: для "СТОК " - "участок/участка", но "водосток/водостока". Чтобы корректно склонять максимальное количество слов, необходимо значительно увеличивать словарь окончаний. Поэтому в данном случае правильным решением будет самостоятельная модификация таблицы правил.
51. Михаил Андропов (daMaster) 19.10.16 12:26
(49) slawa, в комментарии к таблице правил написано:
"М-" в колонке "Род" означает, что по окончанию род не определить, но правило действует только для рода "М" ("Воробей" склоняется только для "М", для "Ж" - не склоняется)
Поэтому если вы будет склонять "Горобец" с указанием мужского рода, данное правило сработает, фамилия будет склоняться, если укажете женский род - не сработает. Если вы при вызове род не указали, алгоритм попытается определить род по отчеству и имени. Когда это не удалось (например, были указаны только инициалы), алгоритм будет по умолчанию считать, что род - мужской (да, это такой синтаксический шовинизм). Если вы считаете, что при неопределенном роде склонять ФИО не следует вовсе, то добавьте сначала вызов функции в режиме определения рода, если род не определился - то не вызывайте функцию в режиме склонения.
52. Михаил Андропов (daMaster) 19.10.16 12:37
(48) gkoles010, пока такой возможности нет, мне сложно придумать ситуацию, где это было бы необходимо. В "канцелярском языке", для которого был разработан данный алгоритм, почти всегда можно вместо "товар находится в двадцать первом ящике" написать "товар находится в ящике двадцать один".