Склонение ФИО в 1С:Предприятие 8.2

Комментарии

10 комментария(ев)
аватар: DrBlack
DrBlack
Дата: Втр, 07/02/2012 - 16:21
Звание: Мастер
Сообщений: 1786

Цитировать
я решил воспользоваться компонентой 1С-ников: библиотекой NameDecl.dll из ЗУПа. Опыт оказался неудачным. Криво работает и всё тут.

х.з., х.з., у меня все работает четко, приведу мой код, основанный на данной библиотеке:

Функция ПросклонятьФамилиюРодительныйПадеж(ФИО)
 
	МассивФИО = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СокрЛП(ФИО)," ");                    
    КоличествоПодстрок = МассивФИО.Количество();
    Фамилия  = ?(КоличествоПодстрок > 0, МассивФИО[0], "");	
	Имя      = ?(КоличествоПодстрок > 1, МассивФИО[1], "");
	Имя		 = ?(НЕ ПустаяСтрока(Имя), " " + Имя, "");
    Отчество = ?(КоличествоПодстрок > 2, МассивФИО[2], "");
	Отчество = ?(НЕ ПустаяСтрока(Отчество), " " + Отчество, "");
 
	Фамилия = Просклонять(Фамилия, 2);
	Возврат Фамилия + Имя + Отчество;
 
КонецФункции
 
Функция Просклонять(Знач Фраза = "", Падеж = 1, Пол = Неопределено)
 
	Попытка
		ПодключитьВнешнююКомпоненту("AddIn.NameDecl");
	Исключение 
	КонецПопытки;
 
	Компонента = Новый ("AddIn.NameDeclension"); 
 
	// Если подключить не удалось, склонять не будем
	Если Компонента = Неопределено Тогда
		Возврат Фраза;
	КонецЕсли;
 
	Результат = "";
 
	#Если Клиент Тогда
 
	//Получим массив строк
	МассивСтрок = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(Фраза, " ");
 
	Для Каждого СтрокаМассива Из МассивСтрок Цикл
 
		// Пустые строки склонять не надо
		Если ПустаяСтрока(СтрокаМассива) Тогда
			Результат = Результат + СтрокаМассива + " ";
			Продолжить;
		КонецЕсли;
 
		Попытка
 
			// Склоняем в зависимости от пола
			Если Пол = Перечисления.ПолФизическихЛиц.Мужской Тогда
				Результат = Результат + Компонента.Просклонять(СтрокаМассива, Падеж, 1) + " ";
			ИначеЕсли Пол = Перечисления.ПолФизическихЛиц.Женский Тогда
				Результат = Результат + Компонента.Просклонять(СтрокаМассива, Падеж, 2) + " ";
			Иначе
				Результат = Результат + Компонента.Просклонять(СтрокаМассива, Падеж) + " ";
			КонецЕсли;
 
		Исключение
 
			// В случае ошибки, вернем все как было
			Возврат Фраза;
 
		КонецПопытки;     
	КонецЦикла;
 
	Результат = СокрЛП(Результат);
 
	Возврат Результат;
 
	#Иначе
 
	Возврат Фраза;
 
	#КонецЕсли
 
КонецФункции

аватар: Spider_NET
Spider_NET
Дата: Втр, 07/02/2012 - 16:27
Звание: Мастер
Сообщений: 2455

Пожалуй, главный минус библиотеки - ее нужно поставлять пользователям.

аватар: Lord_of_fear
Lord_of_fear
Дата: Втр, 07/02/2012 - 16:29
Звание: Мастер
Сообщений: 2213

2DrBlack
Я сечил форумы по этой проблеме. Все разделились на 2 больших клана. У половины работает, у половины нет. =) И никто не может четко сказать, почему именно не работает...

аватар: DrBlack
DrBlack
Дата: Втр, 07/02/2012 - 16:30
Звание: Мастер
Сообщений: 1786

Жесть... Laughing out loud

аватар: plaha
plaha
Дата: Втр, 07/02/2012 - 18:22
Звание: Энтузиаст
Сообщений: 159

Функция склонения.

Функция Склонять(Слово,Падеж = "И",Пол = неопределено,ПризнакФамилии = Ложь,НеСклонять = Истина) Экспорт
Перем СС,ПБукв1,ПБукв2,ПБукв3,Падеж,ВерхРег,ДлСС;
СС=СокрЛП(Слово);
Падеж = ВРЕГ(Лев(Строка(Падеж),1));
Если Не ЗначениеЗаполнено(Падеж) Тогда
Падеж = "И";
КонецЕсли;
Если НеСклонять Тогда
Возврат СС;
КонецЕсли;
Если Падеж = "И" Тогда
Возврат СС;
КонецЕсли;
ПБукв1 = Прав(СС,1);
ВерхРег = ?((КодСимвола(ПБукв1)>=192) И (КодСимвола(ПБукв1)<=223) , 1, 0);
ДлСС = СтрДлина(СС);
ПБукв1 = ВРег(Прав(СС,1));
ПБукв2 = ВРег(Сред(СС,ДлСС-1,1));
ПБукв3 = ВРег(Сред(СС,ДлСС-2,1));

Если ВРег(СС)="ЛЕВ" Тогда
СС = Лев(СС,1) + ?(Падеж="Р", ?(ВерхРег=1,"ЬВА","ьва"), ?(Падеж="Д", ?(ВерхРег=1,"ЬВУ","ьву"), ?(Падеж="В", ?(ВерхРег=1,"ЬВА","ьва"), ?(Падеж="Т", ?(ВерхРег=1,"ЬВОМ","ьвом"), ?(Падеж="П", ?(ВерхРег=1,"ЬВЕ","ьве"), "")))));
Возврат СС;
ИначеЕсли ВРег(СС)="ПАВЕЛ" Тогда
СС = Лев(СС,3) + ?(Падеж="Р", ?(ВерхРег=1,"ЛА","ла"), ?(Падеж="Д", ?(ВерхРег=1,"ЛУ","лу"), ?(Падеж="В", ?(ВерхРег=1,"ЛА","ла"), ?(Падеж="Т", ?(ВерхРег=1,"ЛОМ","лом"), ?(Падеж="П", ?(ВерхРег=1,"ЛЕ","ле"), "")))));
Возврат СС;
КонецЕсли;

Если ПБукв1="А" Тогда
Если ПБукв2="К" или ПБукв2="Г" Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"И","и"), ?(Падеж="Д", ?(ВерхРег=1,"Е","е"), ?(Падеж="В", ?(ВерхРег=1,"У","у"), ?(Падеж="Т", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
ИначеЕсли ПБукв2="Ц" Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"Ы","ы"), ?(Падеж="Д", ?(ВерхРег=1,"Е","е"), ?(Падеж="В", ?(ВерхРег=1,"У","у"), ?(Падеж="Т", ?(ВерхРег=1,"ЕЙ","ей"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
Иначе
Если (ПризнакФамилии) и (Не Пол = Неопределено и Пол = Перечисления.Пол.Ж) Тогда
Если (ПБукв2="В") или (ПБукв2="Н") Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="Д", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="В", ?(ВерхРег=1,"У","у"), ?(Падеж="Т", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="П", ?(ВерхРег=1,"ОЙ","ой"), "")))));
Иначе
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"Ы","ы"), ?(Падеж="Д", ?(ВерхРег=1,"Е","е"), ?(Падеж="В", ?(ВерхРег=1,"У","у"), ?(Падеж="Т", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
Иначе
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"Ы","ы"), ?(Падеж="Д", ?(ВерхРег=1,"Е","е"), ?(Падеж="В", ?(ВерхРег=1,"У","у"), ?(Падеж="Т", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
КонецЕсли;
ИначеЕсли ПБукв1="Б" Тогда
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ОМ","ом"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
ИначеЕсли ПБукв1="В" Тогда
Если (ПБукв2="А") ИЛИ (ПризнакФамилии) Тогда
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ОМ","ом"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
Иначе
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ЫМ","ым"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
ИначеЕсли (ПБукв1 = "Г") ИЛИ (ПБукв1 = "Д") ИЛИ (ПБукв1 = "Ж") ИЛИ
(ПБукв1 = "З") ИЛИ (ПБукв1 = "К") ИЛИ (ПБукв1 = "Л") ИЛИ
(ПБукв1 = "М") ИЛИ (ПБукв1 = "Н") И (ПБукв2 <> "И") И (ПБукв2 <> "Ы") ИЛИ
(ПБукв1 = "П") ИЛИ (ПБукв1 = "Р") ИЛИ (ПБукв1 = "С") ИЛИ
(ПБукв1 = "Т") ИЛИ (ПБукв1 = "Ф") ИЛИ
(ПБукв1 = "Х") И (ПБукв2 <> "И") И (ПБукв2 <> "Ы") ИЛИ
(ПБукв1 = "Щ") Тогда
Если (ПризнакФамилии) и (Не Пол = Неопределено и Пол = Перечисления.Пол.Ж) Тогда
Возврат СС;
Иначе
Если Прав(СС,2) = "ок" Тогда
СС = ЛЕВ(СС, СтрДлина(СС)- 2) + "к";
КонецЕсли;
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ОМ","ом"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
ИначеЕсли ПБукв1 = "Й" Тогда
Если (ПризнакФамилии) и (Не Пол = Неопределено и Пол = Перечисления.Пол.Ж) Тогда
Возврат(СС);
ИначеЕсли (ПБукв2="И") И (ПБукв3="К") Тогда
СС = Лев(СС,ДлСС-2) + ?(Падеж="Р", ?(ВерхРег=1,"ОГО","ого"), ?(Падеж="Д", ?(ВерхРег=1,"ОМУ","ому"), ?(Падеж="В", ?(ВерхРег=1,"ОГО","ого"), ?(Падеж="Т", ?(ВерхРег=1,"ИМ","им"), ?(Падеж="П", ?(ВерхРег=1,"ОМ","ом"), "")))));
ИначеЕсли (ПБукв2="И") И ((ПБукв3="Ш") ИЛИ (ПБукв3="Щ")) Тогда
СС = Лев(СС,ДлСС-2) + ?(Падеж="Р", ?(ВерхРег=1,"ЕГО","его"), ?(Падеж="Д", ?(ВерхРег=1,"ЕМУ","ему"), ?(Падеж="В", ?(ВерхРег=1,"ЕГО","его"), ?(Падеж="Т", ?(ВерхРег=1,"ИМ","им"), ?(Падеж="П", ?(ВерхРег=1,"ЕМ","ем"), "")))));
ИначеЕсли (ПБукв2="О") ИЛИ (ПБукв2="Ы") Тогда
СС = Лев(СС,ДлСС-2) + ?(Падеж="Р", ?(ВерхРег=1,"ОГО","ого"), ?(Падеж="Д", ?(ВерхРег=1,"ОМУ","ому"), ?(Падеж="В", ?(ВерхРег=1,"ОГО","ого"), ?(Падеж="Т", ?(ВерхРег=1,"ЫМ","ым"), ?(Падеж="П", ?(ВерхРег=1,"ОМ","ом"), "")))));
ИначеЕсли (ПБукв2="А") ИЛИ (ПБукв2="Е") ИЛИ (ПБукв2="И") ИЛИ (ПБукв2="У") ИЛИ (ПБукв2="Э") ИЛИ (ПБукв2="Ю") ИЛИ (ПБукв2="Я") И (ПБукв3<>"К") Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"Я","я"), ?(Падеж="Д", ?(ВерхРег=1,"Ю","ю"), ?(Падеж="В", ?(ВерхРег=1,"Я","я"), ?(Падеж="Т", ?(ВерхРег=1,"ЕМ","ем"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли
ИначеЕсли (ПБукв1 = "Н") И ((ПБукв2 = "И") ИЛИ (ПБукв2 = "Ы")) Тогда
Если п_ПризнакФамилии Тогда
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ЫМ","ым"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
Иначе
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ОМ","ом"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
ИначеЕсли (ПБукв1 = "Х") И ((ПБукв2 = "И") ИЛИ (ПБукв2 = "Ы")) Тогда
// НЕ СКЛОНЯЮТСЯ
ИначеЕсли (ПБукв1 = "Ц") ИЛИ (ПБукв1 = "Ч") ИЛИ (ПБукв1 = "Ш") Тогда
Если (п_ПризнакФамилии) и (Не п_Пол = Неопределено и п_Пол = Перечисления.Пол.Ж) Тогда
Возврат СС;
Иначе
СС = СС + ?(Падеж="Р", ?(ВерхРег=1,"А","а"), ?(Падеж="Д", ?(ВерхРег=1,"У","у"), ?(Падеж="В", ?(ВерхРег=1,"А","а"), ?(Падеж="Т", ?(ВерхРег=1,"ЕМ","ем"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
ИначеЕсли ПБукв1 = "Ь" Тогда
Если (Не п_Пол = Неопределено и п_Пол = Перечисления.Пол.М) Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"Я","я"), ?(Падеж="Д", ?(ВерхРег=1,"Ю","ю"), ?(Падеж="В", ?(ВерхРег=1,"Я","я"), ?(Падеж="Т", ?(ВерхРег=1,"ЕМ","ем"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
Иначе
Если п_ПризнакФамилии Тогда
СС = СС;
Иначе
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"И","и"), ?(Падеж="Д", ?(ВерхРег=1,"И","и"), ?(Падеж="В", ?(ВерхРег=1,"Ь","ь"), ?(Падеж="Т", ?(ВерхРег=1,"ЬЮ","ью"), ?(Падеж="П", ?(ВерхРег=1,"И","и"), "")))));
КонецЕсли;
КонецЕсли;
ИначеЕсли ПБукв1 = "Я" Тогда
Если ПБукв2 = "М" Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"ЕНИ","ени"), ?(Падеж="Д", ?(ВерхРег=1,"ЕНИ","ени"), ?(Падеж="В", ?(ВерхРег=1,"Я","я"), ?(Падеж="Т", ?(ВерхРег=1,"ЕНЕМ","енем"), ?(Падеж="П", ?(ВерхРег=1,"ЕНИ","ени"), "")))));
ИначеЕсли ПБукв2 = "И" Тогда
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"И","и"), ?(Падеж="Д", ?(ВерхРег=1,"И","и"), ?(Падеж="В", ?(ВерхРег=1,"Ю","ю"), ?(Падеж="Т", ?(ВерхРег=1,"ЕЙ","ей"), ?(Падеж="П", ?(ВерхРег=1,"И","и"), "")))));
ИначеЕсли ПБукв2 = "А" Тогда
СС = Лев(СС,ДлСС-2) + ?(Падеж="Р", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="Д", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="В", ?(ВерхРег=1,"УЮ","ую"), ?(Падеж="Т", ?(ВерхРег=1,"ОЙ","ой"), ?(Падеж="П", ?(ВерхРег=1,"ОЙ","ой"), "")))));
Иначе
СС = Лев(СС,ДлСС-1) + ?(Падеж="Р", ?(ВерхРег=1,"И","и"), ?(Падеж="Д", ?(ВерхРег=1,"Е","е"), ?(Падеж="В", ?(ВерхРег=1,"Ю","ю"), ?(Падеж="Т", ?(ВерхРег=1,"ЕЙ","ей"), ?(Падеж="П", ?(ВерхРег=1,"Е","е"), "")))));
КонецЕсли;
КонецЕсли;
Возврат СС;
КонецФункции

Функция работы с ФИО сотрудника.

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

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

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

Если ИОвНачале = 1 Тогда
Возврат(Имя+Отчество+" "+Фамилия);
ИначеЕсли ИОвНачале = 2 Тогда
Возврат(СокрЛП(Фамилия) + "," + СокрЛП(Имя) + "," + СокрЛП(Отчество));
Иначе
Возврат(Фамилия+Имя+Отчество);
Конецесли;
КонецФункции

Функции кидаем в глобальный модуль.
Далее добавляем в печатные формы документов.

аватар: Денис Уваров
Денис Уваров
Дата: СР, 08/02/2012 - 05:33
Звание: Наблюдатель
Сообщений: 3

Цитировать

юзеры работают через web
так почему бы не использовать веб-сервисы склонения? код умещается в 20 строк, интернет под рукой всегда Smile

аватар: Spider_NET
Spider_NET
Дата: СР, 08/02/2012 - 07:18
Звание: Мастер
Сообщений: 2455

Можно использовать, но интернет не всегда под рукой (((( Иногда юзерам приходится полностью перекрывать доступ в сеть.

аватар: angryvitum
angryvitum
Дата: ЧТ, 09/02/2012 - 12:20
Звание: Посвященный
Сообщений: 551

А чем плоха Padeg.dll?

аватар: DrBlack
DrBlack
Дата: ЧТ, 09/02/2012 - 18:11
Звание: Мастер
Сообщений: 1786

Цитировать
Пожалуй, главный минус библиотеки - ее нужно поставлять пользователям.

аватар: KOT-Pskov
KOT-Pskov
Дата: ПТ, 25/01/2013 - 17:28
Звание: Наблюдатель
Сообщений: 1

Спасибо за код! Оказался очень полезным.

Правда пришлось малость подправить, поскольку при попытке преобразовать несколько ФИО одного за другим, выдавало ошибку записи:

{ОбщийМодуль.СклонениеПадежейФИО.Модуль(17)}: Поле объекта недоступно для записи (Клиент)
ФИО=СокрЛП(СтрЗаменить(ФИО," "," "));

Получилось исправить довольно таки легко, заменив в начале функции название переменной и немного изменив порядок строк (честно говоря, 1С занимаюсь не так уж давно, потому не судите строго за моё трорение Smile ):

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

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

.........

КонецФункции