Склонение ФИО

Опубликовал e.kogan в раздел Программирование - Универсальные функции

Склонение ФИО в виде небольшой процедуры. Писалось студентом-программистом и студентом-лингвистом.

В файле - процедуры для 7.7 и для 8.х. В процедуру передаётся строка в формате Фамилия Имя Отчество.

 

UPD 26.11.10: с благодарностью Александру Смоленскому  - новая версия функции. Я - не тестировала! Вопросы по работе этой версии - к нему, выкладывать сам почему-то не хочет :)


	 Функция ПадежФИО(Знач ФИО,Падеж=1,ТолькоИнициалы=Ложь, Знач пРазделитель=".") 
    Если ТипЗнч(ФИО)<>Тип("Строка") Тогда
        Сообщить("Неверная строка передана ""падежу ФИО!"""); Возврат ФИО;
    КонецЕсли;

    // уберем множественные пробелы
    Пока 1=1 Цикл
        ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));
        Если Найти(ФИО," ")=0 Тогда Прервать КонецЕсли;
    КонецЦикла;

    Если ТипЗнч(Падеж)=Тип("Строка") Тогда
        пад=СокрЛП(НРег(Лев(Падеж,1)));
        Если Найти("ирдвтп",пад)=0 Тогда
            Сообщить("Неверный падеж передан ""падежу ФИО""!"); Возврат ФИО;
        КонецЕсли;
    ИначеЕсли ТипЗнч(Падеж)=Тип("Число") Тогда
        Если (Падеж<1) или (Падеж>6) Тогда
            Сообщить("Неверный падеж передан ""падежу ФИО""!"); Возврат ФИО;
        КонецЕсли;
        пад=Падеж-1;
    КонецЕсли;

    ФИО=СокрЛП(НРег(ФИО)); // так удобнее

    // свой анализатор состава
    Фамилия="";
    Для й=1 По СтрДлина(ФИО) Цикл
        символс=Сред(ФИО,й,1);
        Если символс=" " Тогда Прервать КонецЕсли;
        Фамилия=Фамилия+символс;
    КонецЦикла;
    ы=й+1; // перешли пробел
    Имя="";
    Для й=ы По СтрДлина(ФИО) Цикл
        символс=Сред(ФИО,й,1);
        Если символс=" " Тогда Прервать КонецЕсли;
        Имя=Имя+символс;
    КонецЦикла;
    ы=й+1; // перешли второй пробел
    Отчество="";
    Для й=ы По СтрДлина(ФИО) Цикл
        символс=Сред(ФИО,й,1);
        Если символс=" " Тогда Прервать КонецЕсли;
        Отчество=Отчество+символс;
    КонецЦикла;

    // теперь имеем раздельно Фамилию, Имя и Отчество.
    // начинается собственно блок анализа содержания и падежей

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


    // проанализируем пол М/Ж
    Если Прав(Отчество,1)="а" Тогда Пол="Ж" Иначе Пол="М" КонецЕсли;

    // создадим структуру таблицы, хранящей окончания слов
    ток=Новый ТаблицаЗначений;
    ТипСтроки=Новый ОписаниеТипов("Строка",Новый КвалификаторыСтроки(3));
    ТипЧисла=Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(1,0));
    ток.Колонки.Добавить("СтарОк",ТипСтроки); // старое окончание 2 символа
    // колонки, хранящие новые окончания слов
    ток.Колонки.Добавить("р"); // родительный
    ток.Колонки.Добавить("д"); // дательный
    ток.Колонки.Добавить("в"); // винительный
    ток.Колонки.Добавить("т"); // творительный
    ток.Колонки.Добавить("п"); // предложный
    // для указания, сколько букв с конца слова отсечь,
    ток.Колонки.Добавить("КолвоСрез",ТипЧисла); // кол-во срезаемых букв

    Гласные="аеэоуиыяюьъ"; // список гласных букв в виде строки

    // ======== обработаем фамилию ==========
    // заполним таблицу данными для фамилии

    Если пол="М" Тогда
        строток=ток.Добавить(); // иванов
        строток.СтарОк="*s";
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ым"; строток.п="е";
        строток.КолвоСрез=0;

        строток=ток.Добавить(); // красинский
        строток.СтарОк="*й";
        строток.р="ого"; строток.д="ому"; строток.в="ого"; строток.т="им"; строток.п="ом";
        строток.КолвоСрез=2;

        строток=ток.Добавить(); // всемогущий
        строток.СтарОк="щий";
        строток.р="его"; строток.д="ему"; строток.в="его"; строток.т="им"; строток.п="ем";
        строток.КолвоСрез=2;

        строток=ток.Добавить(); // белый
        строток.СтарОк="ый";
        строток.р="ого"; строток.д="ому"; строток.в="ого"; строток.т="ым"; строток.п="ом";
        строток.КолвоСрез=2;

        строток=ток.Добавить(); // палей
        строток.СтарОк="*й";
        строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
        строток.КолвоСрез=1;

        строток=ток.Добавить(); // рабинович
        строток.СтарОк="*ч";
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ем"; строток.п="е";
        строток.КолвоСрез=0;

        строток=ток.Добавить(); // починок, зализняк
        строток.СтарОк="*к";
        строток.р="ка"; строток.д="ку"; строток.в="ка"; строток.т="ком"; строток.п="ке";
        строток.КолвоСрез=2;

        строток=ток.Добавить(); // шинкарь
        строток.СтарОк="*ь";
        строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
        строток.КолвоСрез=1;

        строток=ток.Добавить(); // перельман, оганесян
        строток.СтарОк="*н";
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ом"; строток.п="е";
        строток.КолвоСрез=0;

        строток=ток.Добавить(); // баранкин
        строток.СтарОк="ин";
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ым"; строток.п="е";
        строток.КолвоСрез=0;

    ИначеЕсли Пол="Ж" Тогда
        строток=ток.Добавить(); // склодовская
        строток.СтарОк="ая";
        строток.р="ой"; строток.д="ой"; строток.в="ую"; строток.т="ой"; строток.п="ой";
        строток.КолвоСрез=2;

        строток=ток.Добавить(); // иванова
        строток.СтарОк="*а";
        строток.р="ой"; строток.д="ой"; строток.в="у"; строток.т="ой"; строток.п="ой";
        строток.КолвоСрез=1;
    КонецЕсли;

    // таблица заполнена. считаем 2 последних буквы и поищем их
    Если не ПустаяСтрока(Фамилия) Тогда
        пб=Прав(Фамилия,3); кол="СтарОк"; // ищем по ней
        новФамилия=Фамилия; // если ничего не изменится, так и будет
        стро=ток.Найти(пб,кол);
        Если стро<>Неопределено Тогда // нашли строгое сразу
            Основа=Лев(Фамилия,СтрДлина(Фамилия)-стро.КолвоСрез);
            новФамилия=Основа+СокрЛП(стро[пад]);
        Иначе
            // строго не нашли по трем последним символам, ищем по двум символам только по последней
            пб=Прав(Фамилия,2);
            стро=ток.Найти(пб,кол);
            Если стро<>Неопределено Тогда
                Основа=Лев(Фамилия,СтрДлина(Фамилия)-стро.КолвоСрез);
                новФамилия=Основа+СокрЛП(стро[пад]);
            Иначе // если по двум не нашли, ищем по одному
                пб="*"+Прав(пб,1);
                стро=ток.Найти(пб,кол);
                Если стро<>Неопределено Тогда // нашли по последней
                    Основа=Лев(Фамилия,СтрДлина(Фамилия)-стро.КолвоСрез);
                    новФамилия=Основа+СокрЛП(стро[пад]);
                Иначе // по последней не нашли, ищем по виду буквы
                    пб="*"+?(Найти(Гласные,Прав(пб,1))=0,"s","g");
                    стро=ток.Найти(пб,кол);
                    Если стро<>Неопределено Тогда // нашли по виду
                        Основа=Лев(Фамилия,СтрДлина(Фамилия)-стро.КолвоСрез);
                        новФамилия=Основа+СокрЛП(стро[пад]);
                    КонецЕсли;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    Иначе
        новФамилия="";
    КонецЕсли;

    // ======== обработаем имя ==========
    // заполним таблицу данными для имени
    ток.Очистить();

    Если Пол="М" Тогда
        // обработаем исключения
        Если Имя="лев" Тогда Имя="льв" КонецЕсли;
        Если Имя="павел" Тогда Имя="павл" КонецЕсли;

        строток=ток.Добавить(); // сергей
        строток.старок="*й";
        строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // иван + лев + павел
        строток.старок="*s";
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ом"; строток.п="е";
        строток.колвосрез=0;

        строток=ток.Добавить(); // никита
        строток.старок="*а";
        строток.р="ы"; строток.д="е"; строток.в="у"; строток.т="ой"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // лука
        строток.старок="ка";
        строток.р="и"; строток.д="е"; строток.в="у"; строток.т="ой"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // иеремия
        строток.старок="ия";
        строток.р="и"; строток.д="и"; строток.в="ю"; строток.т="ей"; строток.п="и";
        строток.колвосрез=1;

        строток=ток.Добавить(); // илья
        строток.старок="*я";
        строток.р="и"; строток.д="е"; строток.в="ю"; строток.т="ей"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // игорь
        строток.старок="*ь";
        строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
        строток.колвосрез=1;

    ИначеЕсли Пол="Ж" Тогда
        // обработаем исключения
        //Если Имя="ольга" Тогда Имя="ольгь" КонецЕсли;

        строток=ток.Добавить(); // ирина
        строток.старок="*а";
        строток.р="ы"; строток.д="е"; строток.в="у"; строток.т="ой"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // инга, ольга
        строток.старок="га";
        строток.р="и"; строток.д="е"; строток.в="у"; строток.т="ой"; строток.п="е";
        строток.колвосрез=1;

        строток=ток.Добавить(); // эсфирь
        строток.старок="*ь";
        строток.р="и"; строток.д="и"; строток.в="ь"; строток.т="ью"; строток.п="и";
        строток.колвосрез=1;

        строток=ток.Добавить(); // мария
        строток.старок="ия";
        строток.р="и"; строток.д="и"; строток.в="ю"; строток.т="ей"; строток.п="и";
        строток.колвосрез=1;

        строток=ток.Добавить(); // софья
        строток.старок="*я";
        строток.р="и"; строток.д="е"; строток.в="ю"; строток.т="ей"; строток.п="е";
        строток.колвосрез=1;
    КонецЕсли;

    // таблица заполнена. считаем 2 последних буквы и поищем их
    Если не ПустаяСтрока(Имя) Тогда
        пб=Прав(Имя,2); кол="СтарОк"; // ищем по ней
        новИмя=Имя; // если ничего не изменится, так и будет
        стро=ток.Найти(пб,кол);
        Если стро<>Неопределено Тогда // нашли строгое сразу
            Основа=Лев(Имя,СтрДлина(Имя)-стро.КолвоСрез);
            новИмя=Основа+СокрЛП(стро[пад]);
        Иначе // строго не нашли, ищем только по последней
            пб="*"+Прав(пб,1);
            стро=ток.Найти(пб,кол);
            Если стро<>Неопределено Тогда // нашли по последней
                Основа=Лев(Имя,СтрДлина(Имя)-стро.КолвоСрез);
                новИмя=Основа+СокрЛП(стро[пад]);
            Иначе // по последней не нашли, ищем по виду буквы
                пб="*"+?(Найти(Гласные,Прав(пб,1))=0,"s","g");
                стро=ток.Найти(пб,кол);
                Если стро<>Неопределено=1 Тогда // нашли по виду
                    Основа=Лев(Имя,СтрДлина(Имя)-стро.КолвоСрез);
                    новИмя=Основа+СокрЛП(стро[пад]);
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    Иначе
        новИмя="";
    КонецЕсли;

    // ======== обработаем отчество, тут проще ==========
    ток.Очистить();

    Если Пол="М" Тогда
        строток=ток.Добавить();
        строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ем"; строток.п="е";
        строток.колвосрез=0;
    ИначеЕсли Пол="Ж" Тогда
        строток=ток.Добавить();
        строток.р="ы"; строток.д="е"; строток.в="у"; строток.т="ой"; строток.п="е";
        строток.колвосрез=1;
    КонецЕсли;
    Если не ПустаяСтрока(Отчество) Тогда
        Основа=Лев(Отчество,СтрДлина(Отчество)-ток[0].КолвоСрез);
        новОтчество=Основа+СокрЛП(ток[0][пад]);
    Иначе
        новОтчество="";
    КонецЕсли;

    Если ТолькоИнициалы Тогда
        новИмя=Лев(новИмя,1); новОтчество=Лев(новОтчество,1);
    КонецЕсли;

    // установим первые буквы верхним регистром
    новФамилия=ВРег(Лев(новФамилия,1))+Сред(новФамилия,2);
    новИмя=ВРег(Лев(новИмя,1))+Сред(новИмя,2);
    новОтчество=ВРег(Лев(новОтчество,1))+Сред(новОтчество,2);

    // и теперь всё вместе
    Если ТолькоИнициалы Тогда // если задан формат инициалов
        новФИО=новФамилия+" "+новИмя+пРазделитель+новОтчество+пРазделитель;
    Иначе
        новФИО=новФамилия+" "+новИмя+" "+новОтчество;
    КонецЕсли;

    Если Найти(ФИО, ".") Тогда // На тот случай, если входной параметр Фамилию с инициалами. Инициалы не трогаем
        новФИО = новФамилия + " " + ТРег(Имя) + Трег(Отчество);
    КонецЕсли;

    Возврат СокрЛП(новФИО);
КонецФункции

 

Файлы

Наименование Файл Дата Размер Кол. Скачив.
-
.1222867795 113,50Kb
31.08.14
1603
.1222867795 31.08.14 113,50Kb 1603 Скачать
Только для 8.1 (обновлено 17.08.09)
.1250495317 16,52Kb
31.08.14
230
.1250495317 31.08.14 16,52Kb 230 Бесплатно

См. также

Лучшие комментарии

10. halushka 02.10.2008 04:39
Хотел посмотреть, ан рейтингом не вышел. :( Жаль.
Ответили: (12) (11)
# Ответить
7. Abadonna 01.10.2008 18:22
(6) Да просто уже забодали любители "простых" решений ;)
А уж если меряться, у кого раньше, то вот: http://1c.proclub.ru/modules/mydownloads/personal.php?cid=111&lid=254
Написана КучерОМ Аркадием Арнольдовием в 2000 году. Чуток коряво, ибо это было первое, что я написал на 1С ваще. Однако КацА МойшУ АбрамовичА склоняла вполне корректно ;)))
Ответили: (9) (8)
# Ответить
43. Abadonna 08.10.2008 08:05
(42)>зря потратили время, в документах достаточно именительного падежа
Ну ежели тебе нравится "Доверенность выдана: Иванов Иван Иванович" - тогда достаточно
А мне нравится, когда "Доверенность выдана: ИвановУ ИванУ ИвановичУ" ;)
+ 2 [ RailMen; hame1e00n; ]
# Ответить

Комментарии

1. Ёпрст 01.10.2008 17:32
Наш ответ чемберлену...

http://www.forum.mista.ru/topic.php?id=355066
# Ответить
2. Ёпрст 01.10.2008 17:33
Гораздо лаконичнее код..и написан задолго до 2003 года...
# Ответить
3. e.kogan 01.10.2008 17:56
Лаконичнее. И сумбурнее.

Кому что нравится.
# Ответить
4. Ёпрст 01.10.2008 18:00
Не вижу там никакого сумбура. Код гораздо приятнее. Даже у Рупора проще.
+ должности отрабатывает
+ специфические фамилии
+ каменты
+ примеры использования
+ 1 [ Fedos; ]
# Ответить
5. Abadonna 01.10.2008 18:04
(1,2) Слабенький ответик-то получился ;)
Сообщить(ПадежС("Кучер",3,1,1) ); // дательный, мужик, склонять фамилию
Возвращет: Кучер
А вот фигушки! КучерУ, ЛебедЮ, Кушниру, КоганУ если речь идет о мужике. А вот для женщины подобные не склоняются.
А вот у автора вернула в дательном:
Кучеру Аркадию Арнольдовичу - я
Кучер Антонине Алексеевне - моя мама
т.е. абсолютно правильно
Ответили: (15) (14) (6)
# Ответить
6. e.kogan 01.10.2008 18:11
(5) Спасибо, хотела сама потестировать предложенное, теперь тратить время не буду.
Ответили: (7)
# Ответить
7. Abadonna 01.10.2008 18:22
(6) Да просто уже забодали любители "простых" решений ;)
А уж если меряться, у кого раньше, то вот: http://1c.proclub.ru/modules/mydownloads/personal.php?cid=111&lid=254
Написана КучерОМ Аркадием Арнольдовием в 2000 году. Чуток коряво, ибо это было первое, что я написал на 1С ваще. Однако КацА МойшУ АбрамовичА склоняла вполне корректно ;)))
Ответили: (9) (8)
# Ответить
8. e.kogan 01.10.2008 19:23
(7) Ну, если уж говорить про Мойш, то правильно - МойшЕ. Или уж Моисей. Уменьшительно-ласкательные склонять задачи не ставилось, всё-таки официальные документы, ага )
# Ответить
9. Abadonna 02.10.2008 02:55
(7) Здрасте! Склоняла КОГО? Мойше??? Я не про дательный, а про винительный в данном случае говорил. Что касается какие еврейские уменьшительные, а какие полные - то тут, сорри, я не спец :)))
Ответили: (17)
# Ответить
10. halushka 02.10.2008 04:39
Хотел посмотреть, ан рейтингом не вышел. :( Жаль.
Ответили: (12) (11)
# Ответить
11. Abadonna 02.10.2008 05:05
(10) Ну держи один плюсик ;) Щас гляну еще где твои комменты
# Ответить
12. O-Planet 02.10.2008 05:10
(10) "Рейтингом не вышел" - это зачОООт! ))))))
# Ответить
13. Lomok 02.10.2008 08:49
Доступ C рейтингом не меньше 3 - FAIL.
Ответили: (17)
# Ответить
14. Ёпрст 02.10.2008 09:04
(5) Не вопрос. Там есть второй вариант, от Рупора.. там правильнее. :)
# Ответить
15. Ёпрст 02.10.2008 09:13
(5) И Самое Главное, ВАША неправда:

Сообщить(Падеж("Кучер" ,3,1,"1" )) = "Кучеру"
Ответили: (20)
# Ответить
16. Ёпрст 02.10.2008 09:14
Так что, решение правильное, хотя и простое, и не писано "на основании серьёзного лингвистического исследования"
:)
# Ответить
17. e.kogan 02.10.2008 10:26
(9) МойшА - это некорректно. Это уменьшительное, да к тому же и, скажем так, русифицированное.
(13) Доступ открыт. Промахнулась с переключателем.
Ответили: (18)
# Ответить
18. Ёпрст 02.10.2008 10:30
(17) И всё же потести предложенное, оно рабочее.
Ответили: (23)
# Ответить
19. Abadonna 02.10.2008 10:33
Честно признаюсь, что всегда думал что "Мойша" нормальное еврейское имя :))) Без уменьшительного, русифицированного и т.д.
# Ответить
20. Abadonna 02.10.2008 10:34
(15) И самое главное, что я тестил Сообщить(ПадежС("Кучер",3,1,1) );
Падеж и еще буковка "С", а не просто Падеж. Когда мне их там сортировать было ;)
Ответили: (21)
# Ответить
21. Ёпрст 02.10.2008 10:37
(20) Там же примеры есть в каментах! :)
# Ответить
22. Abadonna 02.10.2008 10:49
2Ёпрст. Ты завязывай фладить, а давай начинай писать про Dialog Stream и Moxel :))))
# Ответить
23. e.kogan 03.10.2008 11:26
(18) Потестила. Хорошооо... Спасибо.
# Ответить
24. e.kogan 03.10.2008 15:27
О!

Меч в творительном - мечЕм, ага ) Нашли-таки мы не ловящееся )
Ответили: (25)
# Ответить
25. Ёпрст 03.10.2008 16:23
(24) А вот и фигушки :)

Падеж("Меч",5,1,"1") = "Мечем"
Ответили: (26)
# Ответить
26. e.kogan 03.10.2008 16:26
(25) А правильно-то - мечОм!
Ответили: (27)
# Ответить
27. Ёпрст 03.10.2008 16:28
(26) Угу, тепереча тестим ваше творение - МечЕм ...
# Ответить
28. Ёпрст 03.10.2008 16:29
+27 так что ничья... :)
Ответили: (29)
# Ответить
29. e.kogan 03.10.2008 16:31
(28) Дык я и не спорю ;) Но предлагали потестить - я и потестила )
# Ответить
30. Ёпрст 03.10.2008 16:35
Хотя...

Мечем Иваным Ивановичем альтернатива
Мечем Иваном Ивановичем ваш метод

тоже глюкаво... В общем, есть куда расти.
Даешь правильные алгоритмы!
Ответили: (31)
# Ответить
31. e.kogan 03.10.2008 16:38
(30) Слуушайте... Так это он Ивана неправильно склоняет? Тц-тц-тц... А я-то уж губы раскатала, что хоть кто-то эту титаническую задачу решил на 99%...

Будем дорабатывать.
Ответили: (32)
+ 1 [ diteco; ]
# Ответить
32. Ёпрст 03.10.2008 16:43
(31) Ну да...:)
Хотя, кому нужен творительный падеж в 1с-ине ? :)
Ответили: (34) (33)
# Ответить
33. e.kogan 03.10.2008 16:48
(32) "Договор заключён с Мечом Иваном Ивановичем", например )
# Ответить
34. e.kogan 03.10.2008 16:55
(32) Пофиксено: имена, оканчивающиеся на "ан", склоняет неправильно для творительного. Буду разбираться в этой перловке )))
Ответили: (35)
# Ответить
35. Ёпрст 03.10.2008 17:44
(34) ...Эээ.. в какой обработке пофиксено ? В вашей ? Так там и так было правильно ...
Ответили: (36)
# Ответить
36. e.kogan 03.10.2008 17:48
(35) Да нет, в предложенной как раз. Но так как собираюсь и её использовать, собираюсь и доводить её до полного блеска.
Ответили: (37)
# Ответить
37. Ёпрст 03.10.2008 17:54
(36) Не забудьте выложить потом для тестинга.
# Ответить
38. e.kogan 05.10.2008 14:59
Слово "паяц" альтернатива склоняет совсем неправильно. В общем, есть куды ростить.
# Ответить
39. Abadonna 05.10.2008 15:51
Как почему-то и думал, так и оказалось ;)
Сообщить(ПадежФИО("Черных Петр Петрович",2));
Сообщить(ПадежФИО("Берия Лаврентий Павлович",2));
Черныха Петра Петровича
// как раз случай, когда склонять не надо! А таких фамилий море - сибирские фамилии
Берия Лаврентия Павловича // а туточки надо БериЮ
Не надейся на универсальный алгоритм для фамилий, его нет!
Ответили: (41)
# Ответить
40. Abadonna 05.10.2008 15:58
А вот как сделано у меня:
Код
   Если ДвеПоследних="УА" Тогда
      Винительный=Фамилия;//фамилии типа Стуруа
      Дательный=Фамилия;
   КонецЕсли;
   
   Если ДвеПоследних="ИА" Тогда
      Винительный=Фамилия;//фамилии типа Туташхиа
      Дательный=Фамилия;
   КонецЕсли;
   
   Если (ДвеПоследних="ЖА") И (Пол="Ж") Тогда
      Винительный=Фамилия;// женские фамилии типа Ганжа
      Дательный=Фамилия;
   КонецЕсли;
   
   Если ТриПоследних="ДЗЕ" Тогда
      Винительный=Фамилия;//грузинские фамилии типа Гогадзе
      Дательный=Фамилия;
      Перейти ~выход;
   КонецЕсли;
   
   Если ТриПоследних="ИЛИ" Тогда
      Винительный=Фамилия;//грузинские фамилии типа Габошвили
      Дательный=Фамилия;
   КонецЕсли;
          Если (ДвеПоследних="ИХ") ИЛИ  (ДвеПоследних="ЫХ") Тогда
      Винительный=Фамилия;//сибирские фамилии
      Дательный=Фамилия;
   КонецЕсли;
Показать полностью
Ответили: (46)
# Ответить
41. Abadonna 05.10.2008 16:14
+(39) Так что лингвист - действительно студент :)))))
# Ответить
42. andrew87 08.10.2008 07:52
зря потратили время, в документах достаточно именительного падежа
Ответили: (43)
# Ответить
43. Abadonna 08.10.2008 08:05
(42)>зря потратили время, в документах достаточно именительного падежа
Ну ежели тебе нравится "Доверенность выдана: Иванов Иван Иванович" - тогда достаточно
А мне нравится, когда "Доверенность выдана: ИвановУ ИванУ ИвановичУ" ;)
+ 2 [ RailMen; hame1e00n; ]
# Ответить
44. crush 08.10.2008 11:52
ЗагрузитьВнешнююКомпоненту("NameDecl.dll");
КомпонентаСклоненияФамилий = СоздатьОбъект("AddIn.NameDeclension");
Слово = "Гадя Петрович Хренова"
НомерПадежа = 2; //Родительный
Сообщить(КомпонентаСклоненияФамилий.Просклонять(Слово,НомерПадежа));
//получаем ГадИ Петрович Хреновой


Компонента есть на диске ИТС, расчитана под восьмёрку, но и в 7.7 нормально работает
Ответили: (45)
# Ответить
45. crush 08.10.2008 12:00
(44) Пропустил точку с запятой, простите :)
У метода "просклонять" есть еще и 30-ий параметр - пол
# Ответить
46. O-Planet 08.10.2008 12:05
(40) Мде... Про иначеесли в 2000-м ты похоже не знал ;) Оно ж даже если нашло ДвеПоследних="УА", то все остальные тоже станет проверять...
Ответили: (47)
# Ответить
47. Abadonna 08.10.2008 12:26
(46) Планет слышал звон, да не знает, где он.
Не обратил внимание на строку, которую я в одном месте не удалил, а она стоит во ВСЕХ блоках:
Перейти ~выход;
И как раз спецом было сделано, чтобы эти блоки тупо копировать, вставлять и изменять, не добавляя ИначеЕсли.
Лично мне так больше нравится
# Ответить
49. hame1e00n 13.07.2009 22:53
Процедура очень интересная, только скачать не могу - рейтинга маловато... плюсик поставил)
# Ответить
50. Diktis 12.08.2009 02:09
Для имени "Ольга" в родительном падеже получаем "Ольгы"
Ответили: (52)
# Ответить
51. CheBurator 12.08.2009 02:15
а чем Падеж "Крохотулька" с проклаба не нравится?
Ответили: (54) (52)
# Ответить
52. e.kogan 12.08.2009 10:19
(50) Приведите ФИО полностью. На "Иванова Ольга Юрьевна" склоняет нормально.
(51) Дело не в том, что нравится или не нравится. Эта процедура была написана совершенно отдельно.
Ответили: (53)
# Ответить
53. Diktis 13.08.2009 01:08
(52) ПадежФИО("Иванова Ольга Юрьевна", 2) = "Ивановой Ольгы Юрьевны"
Может я чего-то не понимаю, но откуда взяться другому результату?
"...
ИначеЕсли Пол="Ж" Тогда
строток=ток.Добавить(); // ирина
строток.старок="*а";
строток.р="ы";
..."
Ответили: (55)
# Ответить
54. Yashazz 17.08.2009 02:03
(51) Этой процедуре уж лет 8, не меньше...
Насчёт ОльгЫ посмотрим.
# Ответить
55. e.kogan 17.08.2009 11:48
(53) Проверяла специально - получается "Ивановой Ольги Юрьевны". Чесслово. Если вводить без отчества - возможно.

Поправила, теперь Ольга, Инга и т.д. склоняются нормально.
# Ответить
56. nelli_dream 17.08.2009 12:28
спасибо автору. мне очень помогла обработочка!
осталось решить вопрос со склонением профессий и цехов! ::)
Ответили: (57)
# Ответить
57. e.kogan 17.08.2009 12:29
(56) Пользуйтесь процедурами Jurer'а. Они это вроде бы умеют.
# Ответить
58. ARL 13.08.2010 11:08
Авторам спасибо! Все реальные случаи функция отработала прекрасно. Добавил только точки к инициалам.
# Ответить
59. Andrew_flyer 27.08.2010 12:34
Спасибо, молодцы!
+ 1 [ Alexander; ]
# Ответить
60. Поручик 01.09.2011 11:50
Раскрасить бы статью.
# Ответить
61. ELInfinito 23.09.2011 07:12
Спасибо за алгоритм!
Ответили: (62)
# Ответить
62. e.kogan 23.09.2011 16:32
(61) Я передам мужу :)
# Ответить
63. kiros 28.09.2011 12:04
Спасибо, небольшой тюнинг, если фамилия и.о. определение Ж рода по "а" и "я" в фамилии. Доработал и в работу.
Еще раз спасибо!
p.s. А косячки они у всех есть, как можно жить без косячков ;)
# Ответить
64. eli1984 04.10.2011 06:56
Сейчас вроде нормально все работает. Спасибо за обработку. пользуюсь.
# Ответить
65. avavadim 17.10.2011 02:41
Спасибо за текст обработки, все нормально работает...
# Ответить
66. Joker 03.01.2012 10:55
Спасибо, вставил в конфу, все работает
# Ответить
67. fixin 04.04.2012 18:07
(0) А теперь проверьте ее моей тестилкой: http://infostart.ru/public/115909/, поищите ошибки.
А вообще нужно конечно писать склонение на технологии регистров правил, пусть и виртуальных, а не хранящихся в базе. Это будет прорыв. Но за попытку плюсую.
+ 1 [ ИНТЕГРА; ]
# Ответить
69. IRLes 21.12.2012 10:28
Прокопчук Сергей Сергеевич - в родительном падеже получается Прокопчка Сергея Сергеевича
по идее должно быть Прокопчука Сергея Сергеевича!
# Ответить
70. IRLes 21.12.2012 11:06
Удалено
# Ответить
71. fr.myha 10.07.2013 14:05
Делюсь функцией, возвращающая инициалы в дательном падеже:

// функция в зависимости от переданного параметра возвращает ФИО
//
// Параметры:
// ФИО - строка. Если Можно вводить только Фамилию или Фимилия Имя или полное ФИО,
// разделитель пробел.
// Пол - Перечисления.Пол
// ТипВывода - числа 1: полное ФИО
// 2: Фамилия И.О.
// 3: И.О. Фамилия
// Возвращаемое значение:
// строка - результат форматирования
Функция обДательныйПадежНаСервере(ФИО,Пол,ТипВывода=0) Экспорт

ФИО_Падеж="";
Фамилия="";
Имя="";
Отчество="";
ФамилияПадеж="";
ИмяПадеж="";
ОтчествоПадеж="";
ФИО=СокрЛП(ФИО);
Длина=0;

Если СтрЧислоВхождений(ФИО," ") = 0 Тогда
Фамилия = ФИО;
Длина = 1;
ИначеЕсли СтрЧислоВхождений(ФИО," ") = 1 Тогда
Фамилия = Лев(ФИО,Найти(ФИО," ")-1);
Имя = СтрЗаменить(ФИО,Фамилия+" ","");
Длина = 2;
ИначеЕсли СтрЧислоВхождений(ФИО," ") = 2 Тогда
Фамилия = Лев(ФИО,Найти(ФИО," ")-1);
Имя = Лев(СтрЗаменить(ФИО,Фамилия+" ",""),Найти(СтрЗаменить(ФИО,Фамилия+" ","")," ")-1);
Отчество = СтрЗаменить(СтрЗаменить(ФИО,Фамилия+" ",""),Имя+" ","");
Длина = 3;
Иначе
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Предупреждение! Неправильно записано ФИО. Проверьте пробелы!" + Символы.ПС + "(обДательныйПадежНаСервере)";
Сообщение.Сообщить();
КонецЕсли;

Если (Нрег(Прав(Отчество,1))="ч") Тогда
ТекПол = Перечисления.Пол.Муж;
ИначеЕсли (Нрег(Прав(Отчество,1))="а") Тогда
ТекПол = Перечисления.Пол.Жен;
КонецЕсли;

Если ТекПол = Перечисления.Пол.Муж Тогда
КонецФамилии = Прав(Фамилия,1);
Если Нрег(КонецФамилии)="е"
ИЛИ Нрег(КонецФамилии) = "и"
ИЛИ Нрег(КонецФамилии) = "о"
ИЛИ Нрег(КонецФамилии) = "у"
ИЛИ Нрег(КонецФамилии) = "э"
ИЛИ Нрег(КонецФамилии) = "ю"
Тогда
ФамилияПадеж = Фамилия;
ИначеЕсли Нрег(КонецФамилии) = "я" Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "е";
ИначеЕсли Нрег(КонецФамилии) = "а" Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "е";
ИначеЕсли Нрег(КонецФамилии) = "й"
ИЛИ Нрег(КонецФамилии) = "ь"
Тогда
Если Нрег(Прав(Фамилия,2)) = "ий"
ИЛИ Нрег(Прав(Фамилия,2)) = "ый"
Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-2) + "ому";
Иначе
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "ю";
КонецЕсли
Иначе
Если Нрег(Прав(Фамилия,2)) = "ец" Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-2) + "цу";
Иначе
ФамилияПадеж = Фамилия + "у";
КонецЕсли
КонецЕсли;

Если Имя = "Лев" Тогда
ИмяПадеж = "Льву";
ИначеЕсли Имя="Павел" Тогда
ИмяПадеж = "Павлу";
ИначеЕсли Имя = "Пётр" Тогда
ИмяПадеж = "Петру";
ИначеЕсли Нрег(Прав(Имя,1)) = "й"
ИЛИ Нрег(Прав(Имя,1)) = "ь"
Тогда
ИмяПадеж = Лев(Имя,СтрДлина(Имя)-1) + "ю";
ИначеЕсли Нрег(Прав(Имя,1)) = "и" Тогда
ИмяПадеж = Имя;
ИначеЕсли Нрег(Прав(Имя,1)) = "а" Тогда
ИмяПадеж = Лев(Имя,СтрДлина(Имя)-1) + "е";
Иначе
ИмяПадеж = Имя + "у";
КонецЕсли;
ОтчествоПадеж = Отчество + "у";
ИначеЕсли ТекПол = Перечисления.Пол.Жен Тогда
КонецФамилии = Прав(Фамилия,1);

Если Нрег(КонецФамилии) = "а" Тогда
Если Нрег(Прав(Фамилия,3)) = "ова"
ИЛИ Нрег(Прав(Фамилия,3))="ева"
Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "ой";
Иначе
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "е";
КонецЕсли
ИначеЕсли Нрег(КонецФамилии) = "я" Тогда
Если Нрег(Прав(Фамилия,2)) = "ая" Тогда
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-2) + "ой";
Иначе
ФамилияПадеж = Лев(Фамилия,СтрДлина(Фамилия)-1) + "е";
КонецЕсли
Иначе
ФамилияПадеж = Фамилия;
КонецЕсли;

Если Нрег(Прав(Имя,1)) = "а" Тогда
ИмяПадеж = Лев(Имя,СтрДлина(Имя)-1) + "е";
ИначеЕсли Нрег(Прав(Имя,1)) = "я" Тогда
Если Нрег(Прав(Имя,2)) = "ия" Тогда
ИмяПадеж = Лев(Имя,СтрДлина(Имя)-1) + "и";
Иначе
ИмяПадеж = Лев(Имя,СтрДлина(Имя)-1) + "е";
КонецЕсли
Иначе
ИмяПадеж = Имя;
КонецЕсли;
ОтчествоПадеж = Лев(Отчество,СтрДлина(Отчество)-1) + "е";
Иначе
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Предупреждение! Неправильно задан Пол. Проверьте!" + Символы.ПС + "(обДательныйПадежНаСервере)";
Сообщение.Сообщить();
КонецЕсли;

Если Длина = 1 Тогда
ФИО_Падеж = "" + ФамилияПадеж;
ИначеЕсли Длина = 2 Тогда
Если ТипВывода = 1 Тогда
ФИО_Падеж = "" + ИмяПадеж + " " + ФамилияПадеж;
ИначеЕсли ТипВывода = 2 Тогда
ФИО_Падеж = "" + ФамилияПадеж + " " + Лев(ИмяПадеж,1) + ".";
ИначеЕсли ТипВывода = 3 Тогда
ФИО_Падеж = "" + Лев(ИмяПадеж,1) + "." + " " + ФамилияПадеж;
Иначе
ФИО_Падеж = "" + ФамилияПадеж + " " + ИмяПадеж;
КонецЕсли
ИначеЕсли Длина = 3 Тогда
Если ТипВывода = 1 Тогда
ФИО_Падеж = "" + ИмяПадеж + " " + ОтчествоПадеж + " " + ФамилияПадеж;
ИначеЕсли ТипВывода = 2 Тогда
ФИО_Падеж = "" + ФамилияПадеж + " " + Лев(ИмяПадеж,1) + "." + " " + Лев(ОтчествоПадеж,1) + ".";
ИначеЕсли ТипВывода=3 Тогда
ФИО_Падеж = "" + Лев(ИмяПадеж,1) + "." + " " + Лев(ОтчествоПадеж,1) + "." + " " + ФамилияПадеж;
Иначе
ФИО_Падеж = "" + ФамилияПадеж + " " + ИмяПадеж + " " + ОтчествоПадеж;
КонецЕсли
Иначе
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Предупреждение! Это не ФИО. Проверьте!" + Символы.ПС + "(обДательныйПадежНаСервере)";
Сообщение.Сообщить();
КонецЕсли;
Возврат ФИО_Падеж;
КонецФункции
# Ответить
72. Stradivari 05.09.2013 16:04
Спасибо, огромное)
# Ответить
73. DoctorRoza 17.10.2013 15:29
Спасибо, классная штука! :)
# Ответить
74. fish249 26.11.2014 14:06
Больно уж громоздкий алгоритм. Склоняет всё без ошибок?
# Ответить
75. Horsy 16.12.2014 15:20
Огромное спасибо за обработку - это было просто спасением для меня!
# Ответить
76. pvlunegov 28.10.2015 10:43
не работает функция в данной статье - происходит зацикливание при попытке удалить множественные пробелы.
Автор тестировал собственное творение то?
# Ответить
77. pvlunegov 28.10.2015 10:46
Исправил в начале функции так:

// уберем множественные пробелы
Пока 1=1 Цикл
ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));
Если Найти(ФИО," ")=0 Тогда Прервать КонецЕсли;
КонецЦикла;

После этого все стало работать. Спасибо!
# Ответить
78. pvlunegov 28.10.2015 10:48
При напечатке сообщения в инфостарт два пробела заменяются на один.
В итоге функция, скопированная из текста статьи, не работает!

Так что в предыдущем моем комментарии СтрЗаменить(ФИО," "," "). В первом " " следует видеть ДВА пробела!
Ответили: (79)
# Ответить
79. e.kogan 28.10.2015 18:16
(78) pvlunegov, сами всё поняли :) потому отдельно и прикреплены были файлы.
# Ответить
80. ИНТЕГРА 28.10.2015 19:40
В начале сразу не понравилось:

Пока 1=1 Цикл
             ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));
             Если Найти(ФИО," ")=0 Тогда Прервать КонецЕсли;
 КонецЦикла;


Заменить на:

Пока Найти(ФИО," ") Цикл
             ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));
КонецЦикла;


А чем типовой вызов склонения из общего модуля не устраивает? :)
Ответили: (81)
# Ответить
81. e.kogan 29.10.2015 02:04
(80) ИНТЕГРА, да, такой вариант даже был где-то реализован... Писалась эта штука тогда, когда никакого "типового" варианта ещё в помине не было, ну и почитайте комменты выше.
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл