Склонение в 1С
Источник: https://1c-programmer-blog.ru/programmirovanie/sklonenie-v-1s.html
Потребность в склонении фамилий, имен, отчеств, улиц, городов, должностей, званий и всего прочего возникает регулярно. И для решения этой задачи существуют проверенные и зарекомендовавшие себя способы. С выходом платформы 8.3.13 к этим способам добавился еще один — склонение средствами платформы, и именно этот способ видится наиболее правильным и удобным. Этот и прочие, достойные упоминания (по моему субъективному мнению), способы будут рассмотрены ниже.
Внешняя компонента
Начнем с самого, вероятно, популярно на сегодняшний день способа — внешняя компонента «Склонение ФИО». Эта компонента существует в двух вариантах: по технологии COM и по технологии Native API. Вариант выполненный по технологии Native API современнее и предпочтительнее.
При скачивании с сайта ИТС мы получаем архив который содержит файл «NAMEDECL.DLL» и файл «NameDecl.zip». Первый файл — это компонента по технологии COM, а второй файл — это архив содержащий компоненту по технологии Native API (он так и используется в архиве).
Компоненту выполненную по технологии COM сначала нужно зарегистрировать, командой «regsvr32» от имени администратора:
Регистрация внешней компоненты
Пример использования:
&НаКлиенте
Процедура КомпонентаCOM(Команда)
Компонента = "C:\NameDecl.dll";
Попытка
ЗагрузитьВнешнююКомпоненту(Компонента);
Объект = Новый("AddIn.NameDeclension");
Исключение
Сообщить("Не удалось загрузить внешнюю компоненту по причине: " + ОписаниеОшибки());
КонецПопытки;
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 2, 1)); //родительный, пол мужской
Сообщить(Объект.Просклонять("Иванова Анна Ивановна", 3, 2)); //дательный, пол женский
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 4)); //винительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 5)); //творительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 6)); //предложный, пол авто
КонецПроцедуры
&НаКлиенте
Процедура КомпонентаCOM(Команда)
Компонента = "C:\NameDecl.dll";
Попытка
ЗагрузитьВнешнююКомпоненту(Компонента);
Объект = Новый("AddIn.NameDeclension");
Исключение
Сообщить("Не удалось загрузить внешнюю компоненту по причине: " + ОписаниеОшибки());
КонецПопытки;
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 2, 1)); //родительный, пол мужской
Сообщить(Объект.Просклонять("Иванова Анна Ивановна", 3, 2)); //дательный, пол женский
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 4)); //винительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 5)); //творительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 6)); //предложный, пол авто
КонецПроцедуры
Компоненту выполненную по технологии Native API регистрировать не нужно, ее необходимо поместить в общий макет (тип макета — «Внешняя компонента») и использовать примерно таким кодом:
&НаКлиенте
Процедура КомпонентаNative(Команда)
УстановитьВнешнююКомпоненту("ОбщийМакет.КомпонентаСклонений");
Попытка
ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаСклонений", "NameDecl" , ТипВнешнейКомпоненты.Native);
Объект = Новый("AddIn.NameDecl.CNameDecl");
Исключение
Сообщить("Не удалось подключить внешнюю компоненту по причине: " + ОписаниеОшибки());
КонецПопытки;
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 2, 1)); //родительный, пол мужской
Сообщить(Объект.Просклонять("Иванова Анна Ивановна", 3, 2)); //дательный, пол женский
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 4)); //винительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 5)); //творительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 6)); //предложный, пол авто
КонецПроцедуры
&НаКлиенте
Процедура КомпонентаNative(Команда)
УстановитьВнешнююКомпоненту("ОбщийМакет.КомпонентаСклонений");
Попытка
ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаСклонений", "NameDecl" , ТипВнешнейКомпоненты.Native);
Объект = Новый("AddIn.NameDecl.CNameDecl");
Исключение
Сообщить("Не удалось подключить внешнюю компоненту по причине: " + ОписаниеОшибки());
КонецПопытки;
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 2, 1)); //родительный, пол мужской
Сообщить(Объект.Просклонять("Иванова Анна Ивановна", 3, 2)); //дательный, пол женский
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 4)); //винительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 5)); //творительный, пол авто
Сообщить(Объект.Просклонять("Иванов Иван Иванович", 6)); //предложный, пол авто
КонецПроцедуры
Как уже говорилось выше, компонента выполненная по технологии Native API предпочтительнее, так как работает и в ОС Linux, в тоже время ее можно использовать и на клиенте и на сервере.
Вариант применения
// Функция склоняет переданую фразу
// Параметры:
// Фраза (обязательный), тип строка
// Параметр должен содержать фразу. Каждое слово фразы будет просклонено отдельно
//
// Падеж (обязательный), тип число
// Падеж, в который необходимо поставить ФИО.
// 1 - Именительный
// 2 - Родительный
// 3 - Дательный
// 4 - Винительный
// 5 - Творительный
// 6 - Предложный
//
//Функция Просклонять(Компонента, Знач Фраза = "", Падеж = 1, Пол = Неопределено, Результат) Экспорт
УниверсальныеМеханизмы.Просклонять(глЗначениеПеременной("глКомпонентаСклоненияФИО"), Слово, Падеж, Пол , СловоВПадеже);
Веб-сервис
Еще одним способом просклонять что-либо является использование веб-сервиса «Морфер». Сервис бесплатный, хотя имеет и платный вариант, кроме этого функционал «Морфера» доступен в виде платной внешней компоненты.
Основным недостатком данного метода является его негарантированная работоспособность — нет интернета или сервис не доступен.
Использование веб-сервиса выглядит так:
&НаКлиенте
Процедура СервисСклонения(Команда)
СклоняемыйТекст = "Пушкин Александр Сергеевич";
АдресСервера = "ws3.morpher.ru";
Соединение = Новый HTTPСоединение(АдресСервера,,,,,, Новый ЗащищенноеСоединениеOpenSSL());
ТекстЗапроса = "/russian/declension?s=" + СклоняемыйТекст;
Заголовки = Новый Соответствие;
Заголовки.Вставить("User-Agent", "1C Enterprise 8.3");
Заголовки.Вставить("Accept", "application/json");
Заголовки.Вставить("charset", "UTF-8");
Запрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки);
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
СтруктураОтвета = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Сообщить(СтруктураОтвета.Р);
Сообщить(СтруктураОтвета.Д);
Сообщить(СтруктураОтвета.В);
Сообщить(СтруктураОтвета.Т);
Сообщить(СтруктураОтвета.П);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СервисСклонения(Команда)
СклоняемыйТекст = "Пушкин Александр Сергеевич";
АдресСервера = "ws3.morpher.ru";
Соединение = Новый HTTPСоединение(АдресСервера,,,,,, Новый ЗащищенноеСоединениеOpenSSL());
ТекстЗапроса = "/russian/declension?s=" + СклоняемыйТекст;
Заголовки = Новый Соответствие;
Заголовки.Вставить("User-Agent", "1C Enterprise 8.3");
Заголовки.Вставить("Accept", "application/json");
Заголовки.Вставить("charset", "UTF-8");
Запрос = Новый HTTPЗапрос(ТекстЗапроса, Заголовки);
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
СтруктураОтвета = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Сообщить(СтруктураОтвета.Р);
Сообщить(СтруктураОтвета.Д);
Сообщить(СтруктураОтвета.В);
Сообщить(СтруктураОтвета.Т);
Сообщить(СтруктураОтвета.П);
КонецЕсли;
КонецПроцедуры
Отмечу, что приведен минимально необходимый код, для реального применения будет разумно добавить какие-то проверки и обработки возможных ошибок.
Средства платформы
И, наконец, рассмотрим недавно добавленную функцию «ПолучитьСклоненияСтроки». Данная функция не блещет функциональностью (вероятно, со временем это изменится), но свою основную задачу выполняет исправно и очень проста в использовании. Третий параметр функции указан как необязательный, но если его не указать, то склонение не будет выполнено. В следующей версии платформы — 8.3.14, была добавлена еще одна функция: ПолучитьСклоненияСтрокиПоЧислу()» . Она позволяет формировать фразы которые содержать какое-либо значение. Пример использования обеих функций:
&НаСервере
Функция СклонениеПлатформаНаСервере()
Результат = ПолучитьСклоненияСтроки("Пушкин Александр Сергеевич", "Л=ru_RU;ПЛ=Мужской", "ПД=Родительный");
//Результат[0] //Пушкина Александра Сергеевича
//эта функция доступна в версии платформы 8.3.14 и выше
Результат = ПолучитьСклоненияСтрокиПоЧислу("стул", 12, "", "ЧС=Порядковое", "ПД=Родительный; ПЧ=ЧислоСОкончанием");
//Результат[0] //12-го стула
Результат = ПолучитьСклоненияСтрокиПоЧислу("автомобиль", 5, "", "ЧС=Количественное", "ПД=Дательный; ПЧ=ЧислоПрописью");
//Результат[0] //пяти автомобилям
Результат = ПолучитьСклоненияСтрокиПоЧислу("медный купорос", 3.5, "килограмм, грамм, 2", "ЧС=Количественное", "ПД=Винительный; ПЧ=ЧислоПрописью");
//Результат[0] //три килограмма пятьдесят граммов медного купороса
КонецФункции
&НаСервере
Функция СклонениеПлатформаНаСервере()
Результат = ПолучитьСклоненияСтроки("Пушкин Александр Сергеевич", "Л=ru_RU;ПЛ=Мужской", "ПД=Родительный");
//Результат[0] //Пушкина Александра Сергеевича
//эта функция доступна в версии платформы 8.3.14 и выше
Результат = ПолучитьСклоненияСтрокиПоЧислу("стул", 12, "", "ЧС=Порядковое", "ПД=Родительный; ПЧ=ЧислоСОкончанием");
//Результат[0] //12-го стула
Результат = ПолучитьСклоненияСтрокиПоЧислу("автомобиль", 5, "", "ЧС=Количественное", "ПД=Дательный; ПЧ=ЧислоПрописью");
//Результат[0] //пяти автомобилям
Результат = ПолучитьСклоненияСтрокиПоЧислу("медный купорос", 3.5, "килограмм, грамм, 2", "ЧС=Количественное", "ПД=Винительный; ПЧ=ЧислоПрописью");
//Результат[0] //три килограмма пятьдесят граммов медного купороса
КонецФункции