На данный момент существует минимум 10 подобных функций для склонения ФИО, не считая стандартной, которые можно вызывать из кода 1С. Зачем написана еще одна, и чем она лучше остальных? Была протестирована каждая из найденных функций, но ни одна из них не подошла — либо большое количество ошибок при склонении, либо неудобство использования, либо и то и другое.
Многие функции для своей работы используют внешние библиотеки — перед началом использования требуется зарегистрировать библиотеку под администраторскими правами на каждом компьютере, откуда будет выполняться запуск функции, а это не всегда возможно из-за политики безопасности предприятия. Похожие проблемы возникают при использовании внешних веб-сервисов, к тому же не везде в наличии стабильный и надежный интернет. Данный алгоритм написан на чистом языке 1С и весь код для всех режимов работы содержится в пределах одной функции, поэтому ее легко можно добавить в общий модуль конфигурации или, например, в модуль внешней печатной формы или отчета.
Все функции склонения были проверены на рабочих данных — это справочники сотрудников и контрагентов реальной организации. Ошибки, причем зачастую для ФИО, которые трудно отнести к экзотическим, возникали у КАЖДОЙ протестированной функции, в том числе и у веб-сервиса «Морфер«, который оперативнее всего поддерживается и показывает лучшие результаты. Очень много ошибок у любимой многими функции «Крохотулька» — 30%, немного лучшие результаты у функции «Коган» — 26%. Поэтому не стоит испытывать иллюзий — ошибки есть и в данном алгоритме, даже после тысяч тестовых прогонов. Важная особенность этой функции — все правила склонения описаны в таблицах простого формата, поэтому при обнаружении ошибок или расхождений в написании имен и фамилий, нет необходимости ждать обновления функции — нетрудно самостоятельно исправить некорректное правило или добавить новое в таблицу.
Для вывода результата можно использовать форматную строку в максимально понятном формате, вида «Фамилия Имя Отчество» или «И.О. Фамилия«. При отутствии форматной строки, функция старается максимально сохранить формат исходной строки. При нестандартном порядке следования частей ФИО, порядок можно указать в параметре вызова функции, например «ФИО«, «ИОФ«, «ИФ«. Род выражения не всегда известен заранее, поэтому есть возможность автоматического определения рода. Определение происходит сначала по Отчеству, при неудаче — по Фамилии, затем по Имени.
Функция также склоняет должности, причем из-за меньшей вариативности склонений, чем для ФИО, склонение должностей происходит практически без ошибок, что было подтверждено множеством различных тестов.
Имеется возможность склонения по падежам и по родам числительных, причем в виде прописи («два«) либо числового значения (2). Вместе с числительным в функцию может быть передано исчислимое в начальной форме (именительный падеж, единственное число), например «8 доска» -> «Т — восемью досками«, «15 рубль» -> «Р — пятнадцати рублей«. Добавлена особая форма винительного падежа для склонения одушевленных существительных: «В — про сорок один мешок«, «О — про сорок одного маляра«.
Также склоняются по падежам, родам и числам прилагательные, существительные и их сочетания из начальной формы: «Генеральная доверенность» -> «Р — Генеральных доверенностей«. Глаголы можно склонять по родам и числам: «Утвердило ответственное лицо» -> «Н — Утвердили ответственные лица«. Более подробные примеры использования — в комментариях в листинге функции.
Если функция оказалась полезной для вас, скачайте тест-центр!
Код функции:
//(c) daMaster 2024
//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 копейки"
//если перед числом поставить символ "#k8SjZc9Dxk", данное слово будет склоняться без преобразования в пропись:
// daСклонение("#k8SjZc9Dxk25 страница", "П", , "Ч") = "25-ти страницах"
//для получения формы винительного падежа одушевленных существительных, используется специальный падеж "О" (винительный Одушевленный):
// daСклонение("41 мешок", "В", , "Ч") = "Сорок один мешок"
// daСклонение("41 маляр", "О", , "Ч") = "Сорок одного маляра"
//
Функция daСклонение(_Выражение, _Падеж = "И", _Род = "", _Режим = "ФИО", _ФорматнаяСтрока = "")
_Версия = "17.06.2024";
//ТАБЛИЦЫ ПРАВИЛ СКЛОНЕНИЯ
//в колонке "Окончания" указывается перечень окончаний, для которых действует данное правило, разделитель "/", в конце также ставится разделитель
//алгоритм ищет строки с окончаниями последовательно, при совпадении останавливается, поэтому более узкое правило ("РВИН") должно следовать выше, чем широкое ("ИН")
//если окончание не найдено в таблице правил - такое слово не склоняется
//колонка "Обрезка" определяет, сколько символов с конца слова обрезать, перед добавлением окончания из колонки падежа ("Р", "Д", "В", "Т", "П")
_ПравилаФ = //Фамилия
//Род; Окончания; Обрезка; Р; Д; В; Т; П; Комментарий
//символ "*" перед окончанием означает, что данное окончание сравнивается не с концом слова, а с целым словом ("*ГРИН" сработает только на Грин, а "ГРИН" - и на "Грин", и на "Багрин")
"М-; *ГРИН/*ЧАПЛИН/РВИН/*БИН/; 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) = "#k8SjZc9Dxk" Тогда
_ЧастьСтроки = Сред(_ЧастьСтроки, 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; ЧВН=");
КонецЕсли;
_МакросИзШаблона = СтрЗаменить(_МакросИзШаблона, _ЭлементШаблона, _РезультатСклонения);
_РезультатСклонения = "";
КонецЦикла;
Возврат _МакросИзШаблона;
КонецФункции
а чем не устраивает dll
Тоже была недавно задача склонения произвольных словосочетаний. Воспользовался готовой dll.
Как заполнял и систематизировал таблицу правил? Сидел и склонял подряд все имена?
(1) chmv,
Я в статье уже писал, какие недостатки у .dll, распишу подробнее:
— .dll необходимо регистрировать на каждом компьютере, где должен работать механизм склонений, если таких компьютеров много — это не самая простая и быстрая работа
— политика IT-безопасности компании может запрещать подобные действия, например у нас 1С работает на ферме терминальных серверов, и на эти сервера вообще не подобраться
— если планируется написать универсальную обработку, использующую механизм склонений, которая будет широко распространяться, в дистрибутив потребуется включать эту .dll с инструкциями, как ее зарегистрировать
— .dll имеет закрытый исходный код, и в случае обнаружения ошибочных склонений (а ошибки, повторюсь, есть в каждом из существующих алгоритмов склонений), вы не сможете исправить ошибки самостоятельно, придется ждать выпуска новой версии .dll, которого можно и не дождаться
Кстати, во время тестирования на реальных данных библиотека padeg.dll при некоторых входных значениях у меня намертво зависала, приходилось перезапускать сеанс 1С.
(2) invertercant, я нашел в сети исходные коды около десятка процедур склонения, причем не только на языке 1С (например, «NamecaseLib» и «Петрович»), и первоначальные правила набрал оттуда. Затем прогонял различные тесты — как специальные тесты от авторов процедур склонения, так и импортированные справочники из реальных конфигураций, и по результатам тестов дополнял правила. Если вы скачаете архив из статьи — обнаружите некоторые из этих тестов, а также ТестЦентр, чтобы тесты прогонять и самостоятельно создавать свои)
(5) Yashazz, я как бы и не скрывал, что баян, но зато баян-то — новый! А функция «Коган», написанная «студентом-программистом и студентом-лингвистом», есть в моем тест-центре, среди 11-ти прочих функций, можете ее протестировать. Если вам нравится алгоритм, который склоняет типа «Петров Юрий Васильевич -> Петрове Юрие Васильевиче», «Басинских Иван Семенович -> Басинскиха Ивана Семеновича», «Бережной Сергей Иванович -> Бережним Сергеем Ивановичем», то пользуйтесь ей на здоровье!
Результат теста на реальном справочнике сотрудников нашей организации: «Алгоритм: Коган (Я. и С. Коган); Вызовов: 7 225; Ошибок: 587 (8,12%)». Как по мне, то 8% ошибок — это слишком много.
(3) верно говорите в dll исключения не добавить 🙂
(5) Yashazz, не проверял, но видно автор текущей разработки взял за основу и добавил очень мощный редактор исключений для окончаний слов.
(7) kostyaomsk, в качестве редактора как раз подойдет любой текстовый) Здесь более важен принцип,согласно которому правила склонения для всех окончаний не разбросаны по разным участкам кода в бесконечных ветвях «Если..Иначе», а объединены в наглядную табличку, которую можно поправить даже и не зная языка 1С!
Видно, что проделана огромная работа. Автору большой +. Но читать и дорабатывать код, который пестрит нижними подчеркиваниями не совсем удобно (маленькая ложечка дегтя).
Я тоже как то искал в инете алгоритмы для склонений, но не видел, чтобы они склоняли составные должности и тем более глаголы (пока не тестировал но +). Плюс за возможность вносить исключения. То что автор собрал наиболее известные алгоритмы в одной обработке тоже +, только вот я бы добавил ссылки на первоисточники (авторам будет приятно). Для ЗУП просто незаменимая функция, из разряда must have.
(9) Yimaida, все переменные начинаются с _НижнихПодчеркиваний сознательно! Предполагается, что функция должна беспроблемно встраиваться в любой модуль, в любую форму, и при этом не портить значения реквизитов и глобальных переменных — вдруг на форме тоже окажется реквизит типа «Род» или «Метод»? В отличие от C++, в 1С с подчеркиваний именовать переменные не принято, поэтому вероятность конфликтов гораздо ниже. Ну и предполагается, что код обычный пользователь менять не будет, разве только не захочет добавить какой-нибудь более продвинутый функционал, в таком случае придется уже поразбираться в логике) А чтобы добавить исключение или исправить ошибочное правило, программировать не нужно — редактируйте таблицы склонений! Ну а ссылки на первоисточники я добавлю в credits для следующей версии.
Такие вещи со склонением и списком исключений для серьезных внедрений. Даже нужно продумывать кто будет и как вносить исключения по словам. Это не для внешнего отчета по формированию печатных форм из ЗУП в холдинге например. Кадровики ругаются на некоторые ФИО, которые приходится ручками корректировать, а что делать. Тут более простая доработка нужна для хранения ислючений, причем где-то во внешнем «листке»
Спасибо автору за труд. Подход к проблемы, я б сказал, фундаментальный. Особой похвалы заслуживает то, что сама функция выложена открыто.
Впечатляет! Особенно результаты тестов. И скорость обработки неплохая. Поставлю «+» и возьму на вооружение.
P.S. Когда использовал компоненту склонения из типовой ЗиУП, долго смеялся, как она должности склоняет, а здесь, вроде бы, вполне корректно.
Спасибо автору! Действительно гигантский труд. Даже должности через тире правильно склоняет.
(11) kostyaomsk, я хотел отойти от списков исключений — зачем городить исключения, если можно модифицировать правила? Но вы правы насчет тех ситуаций, когда обрабатывать ошибки склонений будет не слишком продвинутый пользователь. Я подумаю насчет «добавления очень мощного редактора исключений» в будущих версиях.
(6) вы мои сообщения читайте-то внимательно, прежде чем проценты ошибок приводить. Я вам про что говорил, разве про нашу с женой? Я вам про те, что в комментариях там, а именно, про супермонстра от Jurer’а, каковой ещё никто не превзошёл, полагаю, и вы тоже.
А просто тупо расписать всё в табличку — значит по сути хардкодить в заданных условиях, а не делать универсал. Jurer сделал иначе, и за то ему мегареспекты.
благодарю, видно что работа проведена огромная! Спасибо за ваш труд.
Должности плохо склоняются
(18) chmv, вы бы привели примеры ошибок, я постараюсь исправить
(16) Yashazz, а вы, походу, и есть тот самый Яков Коган, студент-филолог, тогда понятно, почему у вас так подгорело))
Алгоритм «Крохотулька» от Юрия Железнякова не только старейший для 1С, но и действительно выдающийся среди прочих, соотношение длины кода к функционалу поражает воображение 1С-ников. Уверен, на каком-нибудь конкурсе-олимпиаде среди программистов 1С он бы взял главный приз. Но реальная жизнь — это не олимпиада. От рабочей функции требуется высокая точность работы и минимальное количество ошибок. У «Крохотульки», к сожалению, процент ошибок слишком высок. Я сам долго пользовался «Крохотулькой» для формирования печатных форм договоров, но когда от менеджеров посыпались жалобы о многочисленных ошибках, пришлось написать свою функцию. Доработка «Крохотульки», чтобы исправить эти ошибки — занятие слишком трудоемкое, поскольку ее код не предназначен для чтения другим человеком, сокращение длины кода привело по сути к полной и безоговорочной обфускации. Юрию летит от меня плотный респект, но в работе «Крохотульку» больше не использую.
По сути ваших нелепых предъяв про «тупо расписать всё в табличку» — это вы здесь в комментариях «тупо» набрасываете. А «табличка» сделана в максимально наглядном виде специально, чтобы любой программист мог самостоятельно, не напрягаясь сверх меры, исправить ошибки или добавить свои правила.
(0) + за функцию. Можно ли вашу функцию использовать в коммерческих разработках (с указанием ссылки на вас в коде и в самой публикации) ?
(21) Ibrogim, то, что выложено в интернет с исходниками, сложно запретить использовать) Так что, пользуйтесь на здоровье, естественно, с указанием ссылок и копирайтов. На данном этапе я заинтересован в обратной связи — поэтому буду благодарен за описание найденных ошибок и за конструктивные замечания и пожелания к функционалу.
Спасибо за функцию. Столкнулся только с одним глюком — когда в должности есть и мужской и женский род — получается фигня. В моем случае Начальник отдела транспортной логистики — при передаче параметра Мужской род в функцию первую половину склоняет корректно — Начальника отдела, потом транспортной — уже не склоняет, логистики — правильно. Но все равно гранд мерси.
Давно и много создаю печатные формы в различных форматах. С первого дня считал, что готовый макет должен быть максимально полно заполнен. Со склонениями, падежами и окончаниями. Пользователь не должен редактировать макет вообще т.к. это время/деньги — это очень важное требование. И как много копий было сломано и шишек набито по поводу склонений ФИО, должностей и подразделений, с окончаниями в зависимости от рода вообще беда. 100% решения нет. Но вот теперь есть идея (почему я сам не додумался???) и инструмент как ПРОТЕСТИРОВАТЬ различные варианты и выбрать лучший, а потом допиливать и перепиливать его, делая «самурайский меч» ))) Автору СПАСИБО!
(23) iiiaiiika, благодарю за обнаруженную ошибку! Но ошибка была не мужском и женском родах — здесь все в порядке, дело в том, что слово «транспортной» оканчивается на «портной», а профессию «портной» склонять надо) Дело решилось добавлением одной звездочки (*) в таблицу правил, теперь «начальник отдела транспортной логистики» склоняется верно, а слово «портной» — только если слово встретилось целиком. В новой версии алгоритма еще несколько исправлений мелких ошибок.
Большое Спасибо. Мы работаем удаленно и через терминалы. dll — нет возможности использовать. Стандартный механизм глючный. и если ФИО более менее, то с названием должностей полная … труба. Делал всякие исключения и т.д. Это обрабатывать, это слово нет и т.д. Разрастается алгоритм сильно, но всё равно ошибки. У вашего их пока не обнаружил, но посмотрим дальше… 🙂 Еще раз спасибо.
daMaster,
неправильно склоняет «Департамент», возможно решается? :
Р/ОПАР/ВЕС/МЕС/НОС/ТЕС/МЕНТ/; ; 0; а; у; а; ом; е;
|М; ОРУБ/ДУВ/КЛАД/ВЕД/ЕВОД/ОВОД/ОХОД/ЛАЗ/ВАЛ/ДЕЛ/СОЛ/ОКОЛ/КОП/ВА
неправильно склоняет «Дирекция», возможно решается? :
|Ж; ЦИЯ/; ; 3; ции; ции; цию ; цией; ции;
daMaster,
в должностях не склоняется «Редакция», «Служба», «Управление делами», «Отдела политика», «Канцелярия»
Нашёл выражение, которое никак не могу добавить в таблицу правил: «Кафедра бизнес-процессов». Нужно получить родительный падеж, т.е. «Кафедры бизнес-процессов». Если добавить «бизнес» в список исключений, то не будет склоняться просто бизнес, а «бизнес-процессов» не добавляется.
(27) Гость, «Департамент», «Редакция», «Канцелярия» — это не должности, это наименования подразделений. Данный алгоритм склоняет должности, если они переданы в процедуру в начальной форме — в таком виде отдел имеет форму родительного падежа: «Секретарь дирекции», «Начальник управления делами», а не «Секретарь дирекция», «Начальник управление делами». В этой форме процедура отрабатывает корректно. Если же вы хотите склонять подразделения отдельно, из формы именительного падежа, следует использовать режим «В» (выражение).
(29) Dr.ZIG, в данном случае вам стоит использовать режим склонения должностей «daСклонение(«Кафедра бизнес-процессов», «Р», , «Д»)», только в таблицу _ПравилаД добавьте правило для слова «кафедра»:
Ж; СЕСТРА/ССА/КАФЕДРА/; ; 1; ы; е; у; ой; е; //Сестра, Стюардесса, Поэтесса
как мне получить из «доверенность номер 17 от 12 января 15 года» результат «действующего на основании доверенности номер 17 от 12 января 15 года»? Или как лучше подставлять в договоры данные?
(32) Fragster, из первого вашего выражения второе вы никак не получите, алгоритм пока не обладает функцией телепатии) А если внимательно прочитать описание, то станет понятно, как алгоритм использовать. Преамбула договора действительно, часто содержит фразу наподобие «ООО «Ромашка» в лице <Пиотровского И.И./Пиотровской А.А.>, <действующего/действующей> на основании <устава/доверенности> № 66 от 14.08.2008 г.», где отдельные фразы изменяются в зависимости от рода и падежа.
Сначала мы определяем род представителя контрагента, заодно просклоняем его в родительный падеж:
ПоискРода = «?»; ПредставительКонтрагентаРП = daСклонение(«Пиотровский И.И.», «Р», ПоискРода, «ФИО»); // ПредставительКонтрагентаРП = «Пиотровского И.И.»
Затем глагол «действующий» склоняем в родительный падеж, а род склонения подставим тот, который определился по ФИО представителя контрагента:
ГлаголРП = daСклонение(«действующий», «Р», ПоискРода, «В»); // ГлаголРП = «действующего»
Также просклоняем тип документа, это может быть «Устав» или «доверенность», род не указываем, он определится автоматически:
ТипДокументаРП = daСклонение(«доверенность», «Р», , «В»); // ТипДокументаРП = «доверенности»
Теперь нам остается соединить строку:
СтрокаПреамбула = ИмяКонтрагента + » в лице » + ПредставительКонтрагентаРП + «, » + ГлаголРП + » на основании » + ТипДокументаРП + » № » + НомерДокумента + » от » + ДатаДокумента;
Похоже «Глава представительства фирмы» спотыкается на Р. (от кого, чего?).
Правильного ответа ни дал ни кто.
Не правильно Крохотулька, daСклонение, finix, Плаха и Jack19.
Остальные результата не дали….
(34) romhika, возможно, вы неправильно указали параметры вызова функции, для склонения должностей используется режим «Д». Проверил для версии от 17.06.2015, все правильно:
daСклонение(«Глава представительства фирмы», «Р», , «Д», ) = «Главы представительства фирмы»
(0) использую на работе Вашу функцию склонения вместо стандартной 1С-ной библиотеки склонений.
А если я буду внедрять печатные формы, к примеру, у своих заказчиков, это не будет нарушением авторских прав, если я укажу Ваше авторство?
(36) premier, нет, нарушением не будет. А если вы укажете мое авторство — то мне приятно будет! )
Спасибо. Жаль второй плюс поставить нельзя. Я бы поставил )))
Вставил, использовал, работает.
(5) Yashazz,
что за «процедуры Jurer’а»? ссылочкой не поделитесь?
(40) ander_,
Jurer — это Юрий Железняков. «процедуры Jurer’а» — это пресловутая «крохотулька». Вам нужно склонение цехов?
(41)
Спасибо за пояснение.
Нет, склонение цехов мне не нужно. Я почему-то решил что «процедуры Jurer’а» это какая-то библиотека для морфологического анализа ЕЯ, в т.ч. включающая в себя и склонение.
Большое спасибо, очень пригодилась функция!
А как высшее образование склонять?
Спасибо, пригодилось! Изменения можно внести без проблем.
попробуйте просклонять слово — участок , получаем участока, участоку и т.д.
Повторюсь, изменения можно внести без проблем
Например, про слово «участок»:
//Род; Окончания; Обрезка; И; Р; Д; В; Т; П; О;
«С; ЕНИЕ/; 1; е/я; я/й; ю/ям; е/я; ем/ями; и/ях; е/й;
//»Р» в колонке «Род» означает, слово родоизменяемое, и порядок окончания в списке определяет род слова
……………………………………..
|М; ШОК/; 2; ок/ки; ка/ков; ку/кам; ок/ки; ком/ками; ке/ках; ка/ков;
можно изменить на
//Род; Окончания; Обрезка; И; Р; Д; В; Т; П; О;
«С; ЕНИЕ/; 1; е/я; я/й; ю/ям; е/я; ем/ями; и/ях; е/й;
//»Р» в колонке «Род» означает, слово родоизменяемое, и порядок окончания в списке определяет род слова
……………………………………
|М; ШОК/ТОК/; 2; ок/ки; ка/ков; ку/кам; ок/ки; ком/ками; ке/ках; ка/ков;
Добрый день!
Есть ли возможность просклонять Порядковые числительные из введенного числа?
1 — Первый, Первого, Первому …
20 — Двадцатый, Двадцатого, Двадцатому …
Если склонять «Горобец» без указания рода, тогда срабатывает правило «М-; ОВЕЦ/БЕЦ/АМЕЦ/НЕЦ/ТЕЦ/; 2; ца; цу; ца; цом; це; Горовец»
Это специально сделано?
Мне кажется, правильней было-бы чтоб срабатывало правило без рода «; »
(46) JohnConnor, склонение корней с беглыми гласными — сложный вопрос, по окончанию слова невозможно понять, беглая гласная или нет. Например: для «СТОК » — «участок/участка», но «водосток/водостока». Чтобы корректно склонять максимальное количество слов, необходимо значительно увеличивать словарь окончаний. Поэтому в данном случае правильным решением будет самостоятельная модификация таблицы правил.
(49) slawa, в комментарии к таблице правил написано:
«М-» в колонке «Род» означает, что по окончанию род не определить, но правило действует только для рода «М» («Воробей» склоняется только для «М», для «Ж» — не склоняется)
Поэтому если вы будет склонять «Горобец» с указанием мужского рода, данное правило сработает, фамилия будет склоняться, если укажете женский род — не сработает. Если вы при вызове род не указали, алгоритм попытается определить род по отчеству и имени. Когда это не удалось (например, были указаны только инициалы), алгоритм будет по умолчанию считать, что род — мужской (да, это такой синтаксический шовинизм). Если вы считаете, что при неопределенном роде склонять ФИО не следует вовсе, то добавьте сначала вызов функции в режиме определения рода, если род не определился — то не вызывайте функцию в режиме склонения.
(48) gkoles010, пока такой возможности нет, мне сложно придумать ситуацию, где это было бы необходимо. В «канцелярском языке», для которого был разработан данный алгоритм, почти всегда можно вместо «товар находится в двадцать первом ящике» написать «товар находится в ящике двадцать один».
За склонение числительных — отдельный гигантский плюсище!
Большое спасибо за Ваш труд! То, что нужно)
Спасибо))
Огромная благодарность!!!!)
Штука отличная.
«41 метр» склоняет как положено «41 метра» а вот «55 метров» — «55 метрова» в РП
(57) идея алгоритма не в том, чтобы сделать универсальный менеджер склонений из любой формы в любую форму — это вызвало бы значительное увеличение объема кода и таблиц склонений. Основной смысл разработки — сделать удобный и компактный инструмент для склонения тех выражений и в тех грамматических формах, которые встречаются при генерации печатных форм из базы данных 1С. Я исходил из того, что при склонении единиц измерений, валют и т. п., программисту доступна начальная форма слова — в которой это слово обычно хранится где-нибудь в справочнике либо перечислении, то есть «метр», а не «метров» или «метра». Прочитайте еще раз комментарии с примерами:
//возможно склонение сочетания числа и исчислимого (валюты, единицы измерения, прочих существительных)
// daСклонение(«32 доска», «Р», , «Ч») = «Тридцати двух досок»
//исчислимое должно быть в начальной форме (именительный падеж, единственное число):
// daСклонение(«23 австралийский доллар», «Р», , «Ч») = «Двадцати трех австралийских долларов»
В вашем случае также надо передавать в качестве исходной строки «41 метр», «55 метр», «62 метр»
Понятно, спасибо.
действующего на основании приказа №1 ота 01.04.2017 г.
«ота» получилось. наверное «от» склонять не надо… или я не так вызвал?
за функцию огромное спасибо. азиз вставил в общий модуль конфы
(60) алгоритм не предназначен для морфологического анализа фраз перед их склонением! Это бы значительно усложнило код и увеличило его размер. Не ленись, помоги функции — раздели сам те слова, которые надо склонять, и те, которые склонять не надо, а потом собирай их по частям. Смотри внимательнее примеры. Азизу — привет!
(61) да уже тогда сделал. выделил первое слово и все ок. As is очень рад получить от тебя привет :))
Помогите получить из «бригада транспортного обеспечения производственной деятельности» -> «бригады транспортного обеспечения производственной деятельности», т.е. надо получить родительный падеж, инструкция бригады транспортного обеспечения производственной деятельности.
У меня получается «бригады транспортногО обеспечения производственноИ деятельности» (большими буквами указаны ошибки.
Спасибо за функцию. Можно ли получить из множественного числа единственное (наоборот можно) именительного падежа существительного? Например: «Товары»->»Товар», «Сумки»->»Сумка»?
Добрый день!
Если не сложно — помогите с двумя вопросами:
1) Первая ситуация:
Если использовать конструкцию — daСклонение(«#k8SjZc9Dxk1500 рубль», «Р», , «Ч», «абвГ»);
то получается — 1500-сот рублей
А если написать — daСклонение(«#k8SjZc9Dxk1500 рубль», «Р», , «Ч», «абвГ»);
то получается — 1500 рубля
А нужно — 1500 рублей
Как этого добиться?
Может есть возможность каким то префиксом указать что переводить число в слова не надо, но при это склонять валюту надо по числительному.
Или может есть возможность отдельно для слова указать использовать множественное число при склонении или нет?
2) Вторая ситуация:
У меня почему то неправильно склоняется конструкция
daСклонение(«(1000) рубль», «Р», , «Ч», «абвГ»);
В моём понимании должно получиться — (одной тысячи) рублей.
А получается — (одной тысячи) рубля.
Что я делаю не так?
Очень надеюсь на ответы.
Работа весьма серьёзная, Автору спасибо. Скачал, пока не проверял, но подход нравиться. Также нравиться возможность тестирования.
Автору спасибо)
Простите за глупые вопросы, но как эту функцию использовать, «подключить» к своей конфигурации?
Может, пора выложить на GIT?
Автору огромное спасибо! Понимаю, что обработка написана давно, но в качестве пожелания: можно ли включить еще и анализ числа (множественное или единственное) ?
А то к примеру «Один санки» в родительном падеже выглядит как «Одного санки», вместо «Одних санок» ))
(38) а ставьте плюсы на всех комментария автора )))
(69) @daMaster может и в правду уже разместить на каком нибудь гит сервисе Вашу работы.
https://infostart.ru/public/789442/
Меня уже ни раз выручала эта функция.
но в последнее время появилась необходимость добавлять правила
(72) Надо бы время найти, допилить новую версию, несколько идей появилось, но руки пока не доходят. А с чем связана необходимость в новых правилах? На каких лексических конструкциях она спотыкается? И в чем прикол гита, неужели кто-то там будет связываться с 1С-ной разработкой и допиливать ее?
(73) склоняю подразделения
УПРАВЛЕНИЕ
ОБРАЗОВАНИЕ
спотыкаются об правилоД = |; Е/И/Ы/Ю/; П; 0; ; ; ; ; ;
пришлось решать предправилом
«; *УПРАВЛЕНИЕ/*ОБРАЗОВАНИЕ/; ; 1; я; ю; е; ем; и;
БУХГАЛТЕРИЯ
АДМИНИСТРАЦИЯ
Вывел в предправило из за того что потом Начальник управления склонялся не правильно
|; *БУХГАЛТЕРИЯ/*АДМИНИСТРАЦИЯ/; ; 1; и; и; ю; ей; ей»;
ТЕЛЕКАНАЛ
«; АЛ/; ; 0; а; у; ; ом; е;
СЛУЖБА
|; ЖБА/; ; 1; ы; е; у; ой; е;»;
(73) И в чем прикол гита, неужели кто-то там будет связываться с 1С-ной разработкой и допиливать ее?
будут
https://github.com/xDrivenDevelopment
https://github.com/silverbulleters
https://github.com/oscript-library
https://github.com/BlizD/Tasks
вот примеры
(74) Да, про подразделения во время создания первой версии я даже не задумывался, следовательно, не тестировал правила склонения для них. Сделать нормальные правила для подразделений как раз в планах на новую версию. В гит не хочется сырую версию выкладывать, постараюсь сам допилить сначала, но если, скажем, за год с даты данного поста я так и не найду время, то любой заинтересованный может сам выложить туда)
Огромный труд, автор!
(68) Попросите программиста 1С, он без труда сможет это сделать.
Спасибо, помогло.
(76) выложилhttps://github.com/pallid/daSklonenie правда переделал немного чтоб и на oscript работало
daСклонение(«доверенность №5 на право подписи от 5 мая 2018 года», «Р», , «В»);
Результат в мужском роде: «доверенности №5 на права подписи ота 5 мой 2018 годы»
Результат в женском роде: «доверенности №5 на право подписи от 5 мой 2018 годы»
Что делать?
(64)
Подскажите пожалуйста, Вам удалось найти решение?
(81) Данная функция — все-таки не искусственный интеллект, она не может разбирать сложное предложение на составляющие — это слишком бы усложнило алгоритмы. Морфер это может делать, но вы видели его исходный код и словарную базу?) Вы должны сами помочь функции в разборе фразы, передавая для склонения только нужные части предложения. В вашем случае это будет выглядеть так:
Результат = daСклонение(«доверенность», «Р», , «В») + » №5 на право подписи от 5 мая 2018 года»;
(66)
*нравится
Автору огромное спасибо!
Заморочился же автор)) Но респект и уважуха! И громаднейшее спасибо от всех, думаю многим она будет полезна!)
Спасибо !