Как-то на одном из проектов столкнулся с такой ситуацией, когда заказчику потребовалось в отчетах, формируемых системой DIRECTUM, склонять ФИО и должности работников организации по падежам. Данную проблему, на мой взгляд, можно было решить несколькими путями:
- Добавить на карточку справочника Работники закладку с дополнительными реквизитами, куда в ручную будут вбиваться ФИО работника в различных падежах. Затем в отчетах выводить информацию из этих реквизитов в зависимости от нужного падежа.
- Разработать свою функцию, которая бы умела склонять ФИО работников и их должности по падежам.
- Использовать какое-нибудь готовое решение.
Первый вариант отпал сразу, так как потребует значительной нагрузки на ответственных, следящих за актуальностью оргструктуры предприятия. Второй вариант тоже отпал, так как потребует значительных трудозатрат. Следовательно, остается только третий вариант.
Порыскав по просторам интернета, была найдена библиотека функций Padeg.dll.
Данная библиотека предназначена для преобразования фамилии, имени и отчества, наименования должности или подразделения, заданных в именительном падеже в форму любого другого падежа, а также для восстановления именительного падежа для ФИО, записанного в произвольном
падеже. Склонение ФИО выполняется по правилам склонения имен собственных, принятых в русском языке. ФИО для склонения может быть задано одной или тремя строками при склонении и одной строкой – при восстановлении именительного падежа. Наименование должности
или подразделения задаются одной строкой.
Список функций библиотеки Padeg.dll:
1. функции склонения ФИО, заданного в формате "фамилия имя отчество"
- function GetFIOPadeg(pLastName, pFirstName, pMiddleName: PChar; bSex: Boolean; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения фамилии (pLastName), имени (pFirstName) и отчества (pMiddleName) рода (bSex) в заданный падеж (nPadeg). Значение функции – результат
выполнения операции преобразования.
- function GetFIOPadegAS(pLastName, pFirstName, pMiddleName: PChar; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения фамилии (pLastName), имени (pFirstName) и отчества (pMiddleName) в заданный падеж (nPadeg) с автоматическим определением рода. Значение функции – результат выполнения операции преобразования.
- function GetFIOPadegFS(pFIO: PChar; bSex: Boolean; nPadeg: LongInt; pResult: PChar; var nLen: LongInt):Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения фамилии имени и отчества, записанных одной строкой (pFIO), рода (bSex)
в заданный падеж (nPadeg). Значение функции – результат выполнения операции преобразования.
- function GetFIOPadegFSAS(pFIO: PChar; nPadeg: LongInt; pResult: PChar; var nLen: LongInt):Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения фамилии имени и отчества, записанных одной строкой (pFIO), в заданный
падеж (nPadeg) с автоматическим определением рода. Значение функции – результат выполнения операции преобразования.
2. функции склонения ФИО, заданного в формате "имя фамилия"
- function GetIFPadeg(pFirstName, pLastName: PChar; bSex: Boolean; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения имени (pFirstName) и фамилии (pLastName) рода (bSex) в заданный падеж (nPadeg). Значение функции – результат выполнения операции преобразования.
- function GetIFPadegFS(pIF: PChar; bSex: Boolean; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения имени и фамилии (pIF), записанных одной строкой, рода (bSex) в указанный
падеж (nPadeg). Значение функции – результат выполнения операции преобразования.
3. функция восстановления именительного падежа
- function GetNominativePadeg(pFIO, pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) восстановленный именительный падеж для ФИО, записанного одной строкой (pFIO) в произвольном падеже. Значение функции – результат выполнения операции преобразования.
4. функции склонения наименований должностей и подразделений
- function GetAppointmentPadeg(pAppointment: PChar; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения наименования должности (pAppointment) в заданный падеж (nPadeg). Значение функции – результат выполнения операции преобразования.
- function GetFullAppointmentPadeg(pAppointment, pOffice: PChar; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат объдинения наименований должности (Appointment) и подразделения (Office) в падеже (nPadeg). Значение
функции – результат выполнения операции преобразования.
- function GetOfficePadeg(pOffice: PChar; nPadeg: LongInt; pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Помещает в буфер (pResult) размера (nLen) результат склонения наименования подразделения (pSrc) в заданный падеж (nPadeg). Значение функции – результат выполнения
операции преобразования.
5. сервисные функции
- function GetSex(pMiddleName: PChar): Integer; stdcall; export; - Определяет род по отчеству, записанному в произвольном падеже.
- function GetPadegID(pFIO: PChar): Integer; stdcall; export; - Определяет номер падежа в котором записано ФИО(pFIO).
- function GetFIOParts(pFIO: PChar; Parts: PPartsFIO): Integer; stdcall; export; - Выделяет из ФИО (pFIO) его составляющие. Результат помещается в буфер (Parts).
6. функции работы со словарем исключений
- function UpdateExceptions: Boolean; stdcall; export; - Служит для принятия изменений, сделанных в файле словаря исключений во время работы приложения, использующего библиотеку.
- function GetExceptionsFileName(pResult: PChar; var nLen: LongInt): Integer; stdcall; export; -
Возвращает в буфере (pResult) размера (nLen) полное имя словаря исключений.
- function SetDictionary(FileName: PChar): Boolean; stdcall; export; -
Устанавливает в качестве рабочего словарь FileName.
Процесс установки библиотеки сводится к следующему:
- Скопировать файл Padeg.dll в директорию C:\Windows\System32\
- Скопировать файл Except.dic в директорию C:\Program Files\Microsoft Office\Office10\. Если путь к каталогу Office отличается от приведенного или принято решение разместить файл словаря в другом месте, то в этом случае перед установкой программы потребуется
редактирование параметра "ExceptionDicDir" в файле Padeg.reg
- Выполнить файл Padeg.reg для внесения служебной информации в системный реестр Windows
- Для обеспечения работы с сервером автоматизации необходимо зарегистрировать его, выполнив в командной строке: regsvr32.exe padeg.dll
Пример работы с библиотекой по технологии COM:
MsgTemplate = "%2:s%1:s%3:s%1:s%4:s%1:s%5:s%0:s"
LogFileName = GetTempFolder()&"\DIRECTUM_Padeg.log"
FIO = "Иванов Иван Иванович"
// Создадим объект Padeg
FreeException()
ExceptionsOff()
Decl = CreateObject("Padeg.Declension")
ExceptionsOn()
// Проверим результат создания объекта Padeg
if ExceptionExists()
Error = GetLastException()
// Ошибка при создании объекта Padeg. Подробнее:
ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
ArrayOf(CR; TAB; Today(); Time(); 'Padeg';
"Ошибка при создании объекта Padeg. Подробнее: "&Error.Message)))
FreeException()
Прервать()
endif
Somes = Decl.GetFIOPadegFS(FIO; ""; 3)
SomeStr = Decl.GetFIOPadegFS(FIO; ""; 1)
Somest = Decl.GetFIOPadegFS(FIO; ""; 5)
ShowMessage("Справка" & CR & CR & "Дана настоящая " & Somes & " в том, что " &
SomeStr & " является " & Somest & ".")
Decl = nil
Результат работы примера:
Пример работы с библиотекой через функцию CallProcedure:
OStr = "Иванович"
Result = CallProcedure('Padeg.dll'; 'GetSex'; 'ED';
OStr)
if Result = 0
ShowMessage("Женский")
else
if Result = 1
ShowMessage("Мужской")
else
ShowMessage("Невозможно определить")
endif
endif
Результат работы примера:
Результаты тестирования нескольких продуктов с аналогичной заявленной функциональностью:
|
% ошибок
|
Морфер:
|
1,5%
|
Padeg.dll:
|
2,3%
|
Крохотулька:
|
16,3%
|
Яндекс:
|
50,3%
|
Для некоммерческого использования библиотека распространяется бесплатно.
Библиотека:
pd_Library.zip (149,43 Кб)
Документация:
pd_Docs.zip (65,58 Кб)
Файл исключений:
Except.zip (2,34 Кб)
Авторы продукта:
Склонение фамилий, имен и отчеств по падежам Библиотека функций.
***** Обновление от 17.10.2012 *****
Появилось аналогичное по функционалу техническое решение DIRECTUM:
Библиотека функций склонения
Из этого:
следует, что у вас как раз коммерческое использование.
В любом случае, при публикации было бы справедливым указать авторов продукта: Склонение фамилий, имен и отчеств по падежам Библиотека функций.
В приложенном архиве pd_Library.zip в файле License.txt указано:
Настоящие лицензионное соглашение распространяется только на библиотеку версии 3.X и выше.
Лицензия на библиотеку версии ниже 3.0 не изменяется.
Когда я использовал эту библиотеку, она была еще свободно распространяемой. К сожалению сейчас она действительно для коммерческого использования стала платной. Но судя по ценам взятым из прайса:
- Лицнзия для коммерческого использования Программы - 500 руб РФ
- Корпоративная лицензия для коммерческого использования Программы - 1000 руб РФ
- Исходные тексты *) - 1000 руб РФ
я вполне могу позволить купить её себе и использовать в своих разработках. Для сравнения тот же морфер стоит 7500 руб.
Ну а Директумовцы вполне бы могли купить исходники и разработать на их основе ф-ии, которые включили бы в стандартную разработку, чтобы мы не использовали для решения таких задач сторонние продукты. Ну или сами бы чего-нибудь подобное реализовали :)
З.Ы. Ссылку на авторов продукта в материал добавлю
Что-то ссылка не работает :(
Как её в материал добавить правильно?
Ссылка, вроде, правильная. Это Delphi Kingdom отвечать перестал. Починят...
А может есть более простые и бесплатные варианты решения данной задачи? Просто на тот момент мне в голову ничего другого не пришло :(
Кстати у данного решения есть существенный минус, библиотеку придеться регать на всех рабочих местах, где потребуется её использование, правда при наличии АД данная задача решается просто.
В Диасофте (www.diasoft.ru) используется собственная функция для этих целей, вот её написание на diasoftscript (delphi)
function GenitiveCase(aSurname, aName, aPatronymic: string): string;
var
bMaleSex: Boolean;
sSurname, sName, sPatronymic: string;
begin
Result := '';
try
sSurname := AnsiUpperCase(Trim(aSurname));
sName := AnsiUpperCase(Trim(aName));
sPatronymic := AnsiUpperCase(Trim(aPatronymic));
if sPatronymic <> '' then
bMaleSex := sPatronymic[Length(sPatronymic)] = 'Ч'
else
bMaleSex := true;
// Фамилия
if Length(sSurname) > 0 then
begin
if bMaleSex then
Case sSurname[Length(sSurname)] of
'О', 'И', 'Я', 'А': Result := sSurname;
'Й': Result := LeftStr(sSurname, Length(sSurname) - 2) + 'ОГО';
else Result := sSurname + 'А';
end
else
case sSurname[Length(sSurname)] of
'О', 'И', 'Б', 'В', 'Г', 'Д', 'Ж', 'З',
'К', 'Л', 'М', 'Н', 'П', 'Р', 'С', 'Т',
'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь': Result := sSurname;
'Я': Result := LeftStr(sSurname, Length(sSurname) - 2) + 'ОЙ';
else Result := LeftStr(sSurname, Length(sSurname) - 1) + 'ОЙ';
end;
Result := Result + ' ';
end;
// Имя
if Length(sName) > 0 then
begin
if bMaleSex then
case sName[Length(sName)] of
'Й', 'Ь': Result := Result + LeftStr(sName, Length(sName) - 1) + 'Я';
else Result := Result + sName + 'А';
end
else
case sName[Length(sName)] of
'А': case sName[Length(sName) - 1] of
'И', 'Г': Result := Result + LeftStr(sName, Length(sName) - 1) + 'И';
else Result := Result + LeftStr(sName, Length(sName) - 1) + 'Ы';
end;
'Я': if sName[Length(sName) - 1] = 'И' then
Result := Result + LeftStr(sName, Length(sName) - 1) + 'И'
else
Result := Result + LeftStr(sName, Length(sName) - 1) + 'И';
'Ь': Result := Result + LeftStr(sName, Length(sName) - 1) + 'И';
else Result := Result + sName;
end; //of case
Result := Result + ' ';
end;
// Отчество
if Length(sPatronymic) > 0 then
if bMaleSex then Result := Result + sPatronymic + 'А'
else Result := Result + LeftStr(sPatronymic, Length(sPatronymic) - 1) + 'Ы';
except
end;
Result := NameCase(Result);
end;
function NameCase(aString: string): string;
var
iPos: integer;
s, sTemp: string;
begin
Result := '';
sTemp := AnsiLowerCase(Trim(aString));
while Length(sTemp) > 0 do
begin
s := ChooseWord(sTemp,1);
Result := Result + ' ' + AnsiUpperCase(LeftStr(s,1)) + RightStr(s, Length(s)-1);
sTemp := Trim(RightStr(sTemp, Length(sTemp) - Length(s)));
end;
Result := Result;
end;
Склонение ФИО - как раз не проблема! И решается функцией DIRECTUM без дополнительных средств.
Уважаемый автор, как будет корректное склонение наименований должностей и подразделений, в которых может быть более 10 слов?
Например, прослконяется ли с помощью Вашего решения следущее наименование:
заведующий сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение".
Заранее благодарю за ответ.
Уважаемый Дмитрий! Название подразделений - не ошибка. Как правило на данном предприятии используются сокращенные названия подразделений. Например, "Сектор разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение".
Но в официальных документах наименование пишется полностью. И вот здесь правила склонения применить без человеческого участия практически невозможно. Что скажете?
Если вы сходите по ссылке, ведущей к авторам продукта, то в пункте 10: "Правила склонения ФИО, реализованные в библиотеке" вы увидите правила, по которым данная библиотека склоняет ФИО. Написание данного функционала с нуля, с учетом всех этих нюансов и правил склонения, в директум своими силами потребует значительных трудозатрат. Я всего лишь предложил уже готовое решение. Впрочем, если вы все тоже самое реализуете средствами директум, то это будет отличное техническое решение :)
Не совсем понял что имелось ввиду.
Я специально привел в конце материала табличку с процентом ошибок склонения при применении различных аналогичных продуктов. В данном случае проблему ошибочного склонения можно решить добавлением исключений в файл исключений.
Вот код, которым я тестировал склонение вышеприведенных должности и наименования подразделения:
MsgTemplate = "%2:s%1:s%3:s%1:s%4:s%1:s%5:s%0:s"
LogFileName = GetTempFolder()&"\DIRECTUM_Padeg.log"
FIO = "Иванов Иван Иванович"
// Создадим объект Padeg
FreeException()
ExceptionsOff()
Decl = CreateObject("Padeg.Declension")
ExceptionsOn()
// Проверим результат создания объекта Padeg
if ExceptionExists()
Error = GetLastException()
// Ошибка при создании объекта Padeg. Подробнее:
ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
ArrayOf(CR; TAB; Today(); Time(); 'Padeg';
"Ошибка при создании объекта Padeg. Подробнее: "&Error.Message)))
FreeException()
Прервать()
endif
Dolg = 'заведующий сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"'
Rez1 = Decl.GetAppointmentPadeg(Dolg; 1)
Rez2 = Decl.GetAppointmentPadeg(Dolg; 2)
Rez3 = Decl.GetAppointmentPadeg(Dolg; 3)
Rez4 = Decl.GetAppointmentPadeg(Dolg; 4)
Rez5 = Decl.GetAppointmentPadeg(Dolg; 5)
Rez6 = Decl.GetAppointmentPadeg(Dolg; 6)
Podr = 'Сектор разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"'
Rez11 = Decl.GetOfficePadeg(Podr; 1)
Rez12 = Decl.GetOfficePadeg(Podr; 2)
Rez13 = Decl.GetOfficePadeg(Podr; 3)
Rez14 = Decl.GetOfficePadeg(Podr; 4)
Rez15 = Decl.GetOfficePadeg(Podr; 5)
Rez16 = Decl.GetOfficePadeg(Podr; 6)
EditText("Именительный: "&Rez1&CR&
"Родительный: "&Rez2&CR&
"Дательный: "&Rez3&CR&
"Винительный: "&Rez4&CR&
"Творительный: "&Rez5&CR&
"Предложный: "&Rez6&CR&CR&
"Именительный: "&Rez11&CR&
"Родительный: "&Rez12&CR&
"Дательный: "&Rez13&CR&
"Винительный: "&Rez14&CR&
"Творительный: "&Rez15&CR&
"Предложный: "&Rez16)
Decl = nil
Результат работы тестового примера:
Именительный: заведующий сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Родительный: заведующего сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Дательный: заведующему сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Винительный: заведующего сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Творительный: заведующим сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Предложный: заведующем сектором разработки и внедрения корпоративных проектов Отдела корпоративных информационных систем управления управления автоматизированных систем управления департамента информационных технологий ЗАО "Газпромнефтьбурение"
Именительный: Сектор разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Родительный: Сектора разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Дательный: Сектору разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Винительный: Сектор разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Творительный: Сектором разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Предложный: Секторе разработки и внедрения корпоративных проектов ОКИСУ управления АСУ департамента ИТ ЗАО "Газпромнефтьбурение"
Как видно из тестового примера, количество слов в наименовании должности и подразделения на результат склонения не влияет.
Дополнительная информация по функциям склонения с сайта авторов продукта:
GetAppointmentPadeg
Функция предназначена для склонения наименования должностей, записанных одной строкой. Начиная с версии библиотеки 3.3.0.21 стала возможной обработка составных должностей. Разделителем в этом случае должна быть цепочка символов: пробел, дефис, пробел (' - '). При этом, каждая из должностей в в своем составе может содержать дефис (инженер-конструктор).
GetFullAppointmentPadeg
Функция позволяет получить полное наименование должности и выполнить его преобразование в заданный падеж. При объединении удаляются повторяющиеся слова при их наличии. Например: должность — Начальник цеха; подразделение — Цех нестандартного оборудования; результат — Начальник цеха нестандартного оборудования. Все, сказанное выше в отношении составных должностей, справедливо и для данной функции.
GetOfficePadeg
Функция предназначена для склонения наименования подразделений, записанных одной строкой. Кроме подразделений функция также может выполнять склонение и наименований предприятий.
коммерческая реализация библиотеки функций склонения:
http://club.directum.ru/post/Biblioteka-funkcijj-sklonenija.aspx
новость на directum.ru:
http://www.directum.ru/4142646.aspx
Алексей, спасибо! Добавил ссылку в материал.
Дмитрий, спасибо! Отличное решение.
Дмитрий, Вы не в курсе, можно ли прикрутить данную библиотеку для работы на x64?
Имеется server 2008 r2, x64. При попытке зарегистрировать библиотеку выходит ошибка: "Возможно, модуль "Padeg.dll" не совместим с версией Windows...". Может есть какие то варианты?
Я не проверял данную библиотеку на 64-разрядных ОС. Судя по всему, данный продукт прекратил свое развитие еще в 2007 году и я не уверен, что найдется готовое решение под x64, разве что создание дополнительной "обвертки" для функций этой dll, чтобы они запускалась в 64-разрядных системах. Возможно google подскажет еще какие-нибудь способы.
В качестве альтернативы, я уже указал в материале ссылку на техрешение Библиотека функций склонения от Систем-Консалт.
Если кто-то знает, как использовать Java-файлы из DIRECTUM, то на хабре выкладывали jar файл этой библиотеки - http://habrahabr.ru/post/161335/ - мне кажется он должен работать на x64
К сожалению, не использовал Java-файлы, и данный функционал не настолько критичен чтобы покупать ТР за те деньги (да и вообще покупать), которые продает вышеуказанная компания
Добрый день!
Инна Циликина писала "Склонение ФИО - как раз не проблема! И решается функцией DIRECTUM без дополнительных средств." - не смог найти функцию в Directum, которая это выполняет. Может кто знает, что именно имелось в виду?
Дмитрий, это решение устанавливается на клиентскую машину или на сервер?
Скорее всего она имела в виду функцию ММФиоСклПадеж. Функция находится в группе устаревших функций и ожидать от нее высокой точности склонения не стоит. Решение, которое описано тут, устанавливается и используется на клиентской машине. Серверный вариант есть тут: Библиотека функций склонения.
Авторизуйтесь, чтобы написать комментарий