Добрый день, подскажите, как просклонять должности, в которых есть слова в "()"? 8.3 управляемая. Пока только вариант ввести самому на форме склонения.
&НаСервереБезКонтекста
Функция ПолучитьСклоненияСтрокиНаСервере(Знач ИсходнаяСтрока, Знач Падеж=1)
МассивСлов = СтрРазделить(ИсходнаяСтрока, " ", Ложь);
Если Падеж=1 Тогда
ФорматнаяСтрока = "ПД=Именительный";
ИначеЕсли Падеж=2 Тогда
ФорматнаяСтрока = "ПД=Родительный";
// сюда добавить описание всех падежей
иначе
ФорматнаяСтрока="";
КонецЕсли;
СтрокаРезультат = "";
Для каждого Слово Из МассивСлов Цикл
ПерваяСкобка = "";
ПоследняяСкобка="";
Склоняемое = Слово;
// при жедании можно сделать проверку и на другие типы скобок
Если СтрНачинаетсяС(Склоняемое, "(") Тогда
Склоняемое = СтрЗаменить(Склоняемое, "(", "");
ПерваяСкобка = "(";
КонецЕсли;
Если СтрЗаканчиваетсяНа(Склоняемое, ")") Тогда
Склоняемое = СтрЗаменить(Склоняемое, ")", "");
ПоследняяСкобка = ")";
КонецЕсли;
РезультатыСклонения = ПолучитьСклоненияСтроки(Склоняемое, ,ФорматнаяСтрока);
СтрокаРезультат = СтрокаРезультат + " "+ПерваяСкобка+РезультатыСклонения[0]+ПоследняяСкобка;
КонецЦикла;
Возврат СокрЛП(СтрокаРезультат);
КонецФункции
&НаКлиенте
Процедура ИсходнаяСтрокаПриИзменении(Элемент)
Родительный = ПолучитьСклоненияСтрокиНаСервере(ИсходнаяСтрока, 2);
КонецПроцедуры
Вопрос уточните. В чем конкретно проблема? Как склоняете должности без "()"? Пока единственная мысль вытаскивать данные из скобок, склонять их отдельно и возвращать назад.
(4) Ясно. Ну вернусь к своему первому предложению: Делите строку с должностью на две строки т.е. собственно на должность и на то, что у вас в скобках. Склоняйте отдельно, потом опять склеивайте в одну строку.
В качестве дополнения. Всегда всё склоняю вот этой функцией. Костяк публикация http://infostart.ru/public/16470/ + мои мелкие доработки. Должности всегда склоняла на ура.
// Функция возвращает фамилию, имя и отчество в нужном падеже
//
// ФИО - строка формата Фамилия Имя Отчество (через пробел), можно опускать Имя и/или Отчество
// Падеж - название падежа (хоть первая буква) или его № 1-6
// ТолькоИнициалы - если истина, то будут только первые буквы вида Фамилия И.О.
//
// Яков и Софья Коган, 2003-2007 (с)
// http://infostart.ru/public/16470/
Функция ПадежФИО(Знач ФИО,Падеж=1,ТолькоИнициалы=Ложь) Экспорт
//Если ТипЗнч(ФИО)<>Тип("Строка") Тогда
// Сообщить("Неверная строка передана ""падежу ФИО!"""); Возврат ФИО;
//КонецЕсли;
//
//// уберем множественные пробелы
//Пока 1=1 Цикл
// ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));
// Если Найти(ФИО," ")=0 Тогда Прервать КонецЕсли;
//КонецЦикла;
// вернем, если сам именительный
Если (Лев(Падеж,1)="И") или (Падеж=1) Тогда Возврат ФИО КонецЕсли;
// Исключения
Если Нрег(ФИО) = "ип" Тогда
Возврат "";
КонецЕсли;
Если ТипЗнч(Падеж)=Тип("Строка") Тогда
пад=СокрЛП(НРег(Лев(Падеж,1)));
Если Найти("рдвтп",пад)=0 Тогда
Сообщить("Неверный падеж передан ""падежу ФИО""!"); Возврат ФИО;
КонецЕсли;
ИначеЕсли ТипЗнч(Падеж)=Тип("Число") Тогда
Если (Падеж<1) или (Падеж>6) Тогда
Сообщить("Неверный падеж передан ""падежу ФИО""!"); Возврат ФИО;
КонецЕсли;
пад=Падеж-1;
КонецЕсли;
ФИО=СокрЛП(НРег(ФИО)); // так удобнее
// свой анализатор состава
//Фамилия="";
//Для й=1 По СтрДлина(ФИО) Цикл
// символс=Сред(ФИО,й,1);
// Если символс=" " Тогда Прервать КонецЕсли;
// Фамилия=Фамилия+символс;
//КонецЦикла;
//ы=й+1; // перешли пробел
//Имя="";
//Для й=ы По СтрДлина(ФИО) Цикл
// символс=Сред(ФИО,й,1);
// Если символс=" " Тогда Прервать КонецЕсли;
// Имя=Имя+символс;
//КонецЦикла;
//ы=й+1; // перешли второй пробел
//Отчество="";
//Для й=ы По СтрДлина(ФИО) Цикл
// символс=Сред(ФИО,й,1);
// Если символс=" " Тогда Прервать КонецЕсли;
// Отчество=Отчество+символс;
//КонецЦикла;
СтрРазбора = СтрЗаменить(ФИО," ", Символы.ПС);
Фамилия = СокрЛП(СтрПолучитьСтроку(СтрРазбора,1));
Имя = СокрЛП(СтрПолучитьСтроку(СтрРазбора,2));
Отчество = СокрЛП(СтрПолучитьСтроку(СтрРазбора,3));
// теперь имеем раздельно Фамилию, Имя и Отчество.
// начинается собственно блок анализа содержания и падежей
// проанализируем пол М/Ж
Если Прав(Отчество,1)="а" Тогда Пол="Ж" Иначе Пол="М" КонецЕсли;
// создадим структуру таблицы, хранящей окончания слов
ток=Новый ТаблицаЗначений;
ТипСтроки=Новый ОписаниеТипов("Строка",Новый КвалификаторыСтроки(2));
ТипЧисла=Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(1,0));
ток.Колонки.Добавить("СтарОк",ТипСтроки); // старое окончание 2 символа
// колонки, хранящие новые окончания слов
ток.Колонки.Добавить("р"); // родительный
ток.Колонки.Добавить("д"); // дательный
ток.Колонки.Добавить("в"); // винительный
ток.Колонки.Добавить("т"); // творительный
ток.Колонки.Добавить("п"); // предложный
// для указания, сколько букв с конца слова отсечь,
ток.Колонки.Добавить("КолвоСрез",ТипЧисла); // кол-во срезаемых букв
Гласные="аеэоуиыяюьъ"; // список гласных букв в виде строки
// ======== обработаем фамилию ==========
// заполним таблицу данными для фамилии
Если Прав(Фамилия,1) <> "х" тогда // Фамилии с окончанием на х такие не склоняются
Если пол="М" Тогда
строток=ток.Добавить(); // иванов
строток.СтарОк="*s";
строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ым"; строток.п="е";
строток.КолвоСрез=0;
строток=ток.Добавить(); // красинский
строток.СтарОк="*й";
строток.р="ого"; строток.д="ому"; строток.в="ого"; строток.т="им"; строток.п="ом";
строток.КолвоСрез=2;
строток=ток.Добавить(); // белый
строток.СтарОк="ый";
строток.р="ого"; строток.д="ому"; строток.в="ого"; строток.т="ым"; строток.п="ом";
строток.КолвоСрез=2;
строток=ток.Добавить(); // палей
строток.СтарОк="*й";
строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
строток.КолвоСрез=1;
строток=ток.Добавить(); // рабинович
строток.СтарОк="*ч";
строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ем"; строток.п="е";
строток.КолвоСрез=0;
строток=ток.Добавить(); // починок, зализняк
строток.СтарОк="*к";
строток.р="ка"; строток.д="ку"; строток.в="ка"; строток.т="ком"; строток.п="ке";
строток.КолвоСрез=2;
строток=ток.Добавить(); // шинкарь
строток.СтарОк="*ь";
строток.р="я"; строток.д="ю"; строток.в="я"; строток.т="ем"; строток.п="е";
строток.КолвоСрез=1;
строток=ток.Добавить(); // перельман, оганесян
строток.СтарОк="*н";
строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ом"; строток.п="е";
строток.КолвоСрез=0;
строток=ток.Добавить(); // баранкин
строток.СтарОк="ин";
строток.р="а"; строток.д="у"; строток.в="а"; строток.т="ым"; строток.п="е";
строток.КолвоСрез=0;
ИначеЕсли Пол="Ж" Тогда
строток=ток.Добавить(); // склодовская
строток.СтарОк="ая";
строток.р="ой"; строток.д="ой"; строток.в="ую"; строток.т="ой"; строток.п="ой";
строток.КолвоСрез=2;
строток=ток.Добавить(); // иванова
строток.СтарОк="*а";
строток.р="ой"; строток.д="ой"; строток.в="у"; строток.т="ой"; строток.п="ой";
строток.КолвоСрез=1;
КонецЕсли; // Пол
// таблица заполнена. считаем 2 последних буквы и поищем их
Если не ПустаяСтрока(Фамилия) Тогда
пб=Прав(Фамилия,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);
// и теперь всё вместе
новФИО=новФамилия+" "+новИмя+" "+новОтчество;
Возврат новФИО;
КонецФункции
(6) спасибо за ссылку
Но есть другой вопрос, я не знаю какое следующее слово будет в (). И как мне делить на строки, функцией СтрРазделить? должность может состоять и из 2 слов и из 5.
&НаСервереБезКонтекста
Функция ПолучитьСклоненияСтрокиНаСервере(Знач ИсходнаяСтрока, Знач Падеж=1)
МассивСлов = СтрРазделить(ИсходнаяСтрока, " ", Ложь);
Если Падеж=1 Тогда
ФорматнаяСтрока = "ПД=Именительный";
ИначеЕсли Падеж=2 Тогда
ФорматнаяСтрока = "ПД=Родительный";
// сюда добавить описание всех падежей
иначе
ФорматнаяСтрока="";
КонецЕсли;
СтрокаРезультат = "";
Для каждого Слово Из МассивСлов Цикл
ПерваяСкобка = "";
ПоследняяСкобка="";
Склоняемое = Слово;
// при жедании можно сделать проверку и на другие типы скобок
Если СтрНачинаетсяС(Склоняемое, "(") Тогда
Склоняемое = СтрЗаменить(Склоняемое, "(", "");
ПерваяСкобка = "(";
КонецЕсли;
Если СтрЗаканчиваетсяНа(Склоняемое, ")") Тогда
Склоняемое = СтрЗаменить(Склоняемое, ")", "");
ПоследняяСкобка = ")";
КонецЕсли;
РезультатыСклонения = ПолучитьСклоненияСтроки(Склоняемое, ,ФорматнаяСтрока);
СтрокаРезультат = СтрокаРезультат + " "+ПерваяСкобка+РезультатыСклонения[0]+ПоследняяСкобка;
КонецЦикла;
Возврат СокрЛП(СтрокаРезультат);
КонецФункции
&НаКлиенте
Процедура ИсходнаяСтрокаПриИзменении(Элемент)
Родительный = ПолучитьСклоненияСтрокиНаСервере(ИсходнаяСтрока, 2);
КонецПроцедуры
(12)А мыши кололись, плакали, но продолжали есть кактус... Ведь переделать документ на использование данных только в именительном падеже намного сложнее...