На данный момент существует минимум 10 подобных функций для склонения ФИО, не считая стандартной, которые можно вызывать из кода 1С. Зачем написана еще одна, и чем она лучше остальных? Была протестирована каждая из найденных функций, но ни одна из них не подошла - либо большое количество ошибок при склонении, либо неудобство использования, либо и то и другое.
Многие функции для своей работы используют внешние библиотеки - перед началом использования требуется зарегистрировать библиотеку под администраторскими правами на каждом компьютере, откуда будет выполняться запуск функции, а это не всегда возможно из-за политики безопасности предприятия. Похожие проблемы возникают при использовании внешних веб-сервисов, к тому же не везде в наличии стабильный и надежный интернет. Данный алгоритм написан на чистом языке 1С и весь код для всех режимов работы содержится в пределах одной функции, поэтому ее легко можно добавить в общий модуль конфигурации или, например, в модуль внешней печатной формы или отчета.
Все функции склонения были проверены на рабочих данных - это справочники сотрудников и контрагентов реальной организации. Ошибки, причем зачастую для ФИО, которые трудно отнести к экзотическим, возникали у КАЖДОЙ протестированной функции, в том числе и у веб-сервиса "Морфер", который оперативнее всего поддерживается и показывает лучшие результаты. Очень много ошибок у любимой многими функции "Крохотулька" - 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; ЧВН=");
КонецЕсли;
_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, _ЭлементШаблона, _РезультатСклонения);
_РезультатСклонения = "";
КонецЦикла;
Возврат _МакросИзШаблона;
КонецФункции