В файле - процедуры для 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);
// и теперь всё вместе
Если ТолькоИнициалы Тогда // если задан формат инициалов
новФИО=новФамилия+" "+новИмя+пРазделитель+новОтчество+пРазделитель;
Иначе
новФИО=новФамилия+" "+новИмя+" "+новОтчество;
КонецЕсли;
Если Найти(ФИО, ".") Тогда // На тот случай, если входной параметр Фамилию с инициалами. Инициалы не трогаем
новФИО = новФамилия + " " + ТРег(Имя) + Трег(Отчество);
КонецЕсли;
Возврат СокрЛП(новФИО);
КонецФункции