Subject: Создание резервных копий
From: <Сохранено Microsoft Internet Explorer 5>
Date: Wed, 17 Feb 2010 00:17:23 +0900

Работа с Фамилиями, Именами,
Отчествами

Очень актуальный вопрос при
ведении учета людей, печатания различных справок, постановлений и .т.п.... Хочу
поделиться своим опытом работы с "человеческими" атрибутами ;)

Вопрос первый. Как хранить
Фамилию Имя Отчество в базе ? Некоторые хранят каждый атрибут в отдельном поле -
Фамилию в одном поле таблицы, Имя в другом, Отчество, соответственно, в третьем
поле. На первый взгляд, довольно логично... Можно работать отдельно с именем,
отдельно с фамилией - видимо так думают те, кто проектирует таблицу. Однако, на
практике выяснилось, что, как бы изначально логично задуманная работа с
отдельными атрибутами полного имени человека в отдельных полях не имеет
смысла.

Маленькое отступление от
темы:

всегда тщательнейшим образом
проектируйте таблицы базы данных и связи между таблицами. Если Вы не можете
перечислить и объяснить (хотя бы самому себе) формы нормализации таблиц, ни в
коем случае не начинайте проектировать схему базы данных - сначала почитайте
литературу по теме нормализации таблиц. Если Вы не поняли, о чем это я тут пишу,
тем более почитайте. Ошибки на стадии проектирования таблиц потом оборачиваются
невозможностью продолжать проект из-за изначально заложенной "кривизны"
разложения модели. Ваш выпестованный проект с большой вероятностью прекратит
существование или будет дико тормозить уже на ранних стадиях накопления данных.
Поверьте, спешка на этом этапе погубила многие дельные начинания программистов
(и не надо тут на Access валить), которые садились писать код, вместо того,
чтобы садиться подумать.

Хватит нотаций, продолжим
выдавать на гора мысли по теме ;). Пробуя на практике разные варианты, (даже не
хочу их публиковать здесь, но приятно было встретить свой код склонения ФИО в
чужой базе) я все равно пришел к мысли, что лучше хранить атрибуты в одном
текстовом поле таблицы и только это лучшее и проверенное на практике решение
опубликую для Вас..

Есть текстовое поле, в которое
оператор "забивает" атрибуты человека, например:

салихов  РАФаиль     ИльдусовиЧ

хм... будете требовать в
категоричной форме от оператора правильности указания прописных букв и
соблюдения количества пробелов между словами ? Могу примерно сказать, что Вам
придется услышать в ответ ;) Что ж....будем учить машину молча исправлять
(приводить к правильному виду) любые ошибки человека. И не надо винить
операторов, сами бы попробовали набивать в день несколько сотен квитанций и
постановлений....

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

' Функция удаляет повторяющиеся пробелы (любое количество) из
строки

' - приводит
их к одному пробелу.
' автор Силантьев Сергей (AKA Силыч) прим. взято с
форума сайта sql.ru
Public Function StrReplaceMoreSpaceToOne(str As String)
Dim strSTR As String
Dim strNew As String
Dim pos As Long
Dim pos1 As Long
Dim str1 As String
Dim str3 As String

On Error GoTo
StrReplaceMoreSpaceToOne_ERR
If Len(str) = 0 Then
StrReplaceMoreSpaceToOne =
str
End If
strSTR =
str
pos = 1
pos1 = 1
strNew = ""
Do
pos1 = InStr(pos, strSTR, Chr(32))
'-- ищем первое вхождение
пробела
If pos1 = 0 Or
IsNull(pos1) Then '-- если не
нашли - значит их здесь вообще
нет

StrReplaceMoreSpaceToOne = IIf(Len(strNew) = 0, strSTR, strNew +
strSTR)
Exit Function
Else
str1 =
Mid$(strSTR, 1, pos1)
If str1 = Chr(32) Then

'-- пропускаем лишние
пробелы

str3 = Mid$(strSTR, pos1 + 1, Len(strSTR) - (pos1 + 1) +
1)
Else

'-- формируем новую
строку

strNew = strNew +
str1
str3
= Mid$(strSTR, pos1 + 1, Len(strSTR) - (pos1 + 1) +
1)
End
If

strSTR = str3 '-- продолжаем с тем, что ещё не
обработали
End If
Loop
Exit Function
StrReplaceMoreSpaceToOne_ERR:
StrReplaceMoreSpaceToOne
= str
Beep
End Function

получили такую строку:

салихов
РАФаиль ИльдусовиЧ

уже неплохо - теперь все слова с
заглавных букв:

Public Function
StrUpFirstLetter(str As String)
On Error GoTo ErrorHandler
'created 26.11.2004 - 00:39 by Rafa
' функция делает все слова
с Заглавной Буквы
If Len(str) = 0 Then
StrUpFirstLetter = str
Else
StrUpFirstLetter = StrConv(str,
vbProperCase)
End If

Exit Function
'----------------------ErrorHandler-------------------------
ErrorHandler:
MsgBox
"Ошибка - " & Err.Number & vbCrLf & vbCrLf & Err.Description,
vbExclamation, _
"Module: mdlФИО_Обработка Function:
StrUpFirstLetter"
End Function

Возвращенный результат: Салихов РаФаиль
Ильдусович

Функция StrUpFirstLetter - это практически один рабочий
оператор StrConv(str, vbProperCase) поэтому
можно просто обработать возвращаемое значение функции StrReplaceMoreSpaceToOne.

StrReplaceMoreSpaceToOne = StrConv(IIf(Len(strNew) = 0, strSTR, strNew + strSTR),
vbProperCase)

я все-таки решил более подробно
расписать для удобства усвоения, потом сами оптимизируете ;)

Как видно из кода - лучше всего
завести отдельный модуль mdlФИО_Обработка,
например, и в него вставить эти две функции. Вызов также осуществляется из
программного кода последовательно - сначала удаление пробелов, потом заглавные
буквы:

Dim strФИОПослеОбработки As
String
strФИОПослеОбработки =
StrReplaceMoreSpaceToOne(Me.txtФИО.Value)
strФИОПослеОбработки =
StrUpFirstLetter(strФИОПослеОбработки)
Me.txtФИО.Value = strФИОПослеОбработки

подготовительный этап мы
рассмотрели, возникает вопрос - как же склонять ? Погодим склонять, сначала
подумаем как нам получать из полных атрибутов строку такого вида (ведь будет
нужна, точно знаю ;):  Салихов
Р. И.

Dim strФИО As String ' для получения полных
атрибутов

Dim strФамилия As String ' для
выделения только фамилии
Dim strИ As String * 1 ' для первой буквы имени
Dim
strО As String * 1 ' для первой буквы отчества

strФИО = Me.txtФИО.Value

strФамилия = Left(strФИО, InStr(1, strФИО, " ") - 1) ' выделяем фамилию
strИ = Mid(strФИО, Len(strФамилия) +
2, 1) ' выделяем первую букву имени
strО =
Mid(strФИО, InStr(Len(strФамилия) + 2, strФИО, " ") + 1, 1) ' выделяем первую букву отчества
Me.txtФамилияИО.Value =
strФамилия & " " & strИ & ". " & strО & "."

ну вот, теперь можно рассмотреть код склонения.
Долго мучившись и писая ;) самопальные процедуры обработки склонения, я всегда
искал идеальный способ решения этой непростой задачи и кажется нашел ;).
Особенно хорошо было от мысли, что для склонения процедура требует именно
полного значения атрибута, которое изначально хранилось у меня в одном поле:
Фамилия Имя Отчество. (правда, ничто не мешает написать процедуру объединения
значений трех отдельных полей)

Этим способом является
изумительная библиотечка,
написанная Плаховым С.В. [email-masked] и
Покаташкиным Г.Л. [email-masked] и
выложенная для общего пользования в свободный доступ (правда, про коммерческое
использование библиотеки ничего не говорится). Скажу сразу - авторами проведена
титаническая работа по созданию программы и мне ни разу не пришлось краснеть за
выдаваемый ею результат (а уж какие только фамилии, имена и отчества не
встречаются среди населения ;)

Хоть звучит страшно -
динамическая библиотека!, работать с нею очень легко. Просто скопируйте файл
библиотеки Padeg.dll в папку "C:\Program Files\Microsoft Office\Office" и
запустите прилагаемый файлик реестра PADEG.REG. Вы можете скопировать файл в
любое место - просто измените путь в прилагаемом файле реестра (или в самом
реестре). Например, если у Вас установлен Офис ХР, то Вы, скорее всего,
скопируете файл библиотеки в папку  "C:\Program Files\Microsoft
Office\Office10" - не забудьте поправить путь в файле PADEG.REG (ну и конечно,
запустить этот файл). Таким простым образом Вы произвели регистрацию библиотеки
и теперь Ваша программа может сразу использовать ее.

Если Вы читаете статью с начала
то помните, что я упоминал об отдельном модуле mdlФИО_Обработка. Вот в него то мы и вставим небольшой
код для работы с библиотекой:

Option Compare Database
Option Explicit

' Функция склонения ФИО с автоматическим определением пола по
отчеству
' Параметры: pFIO - фамилия, имя, отчество
' nPadeg - падеж
(допустимые значения: 1..6)
' pResult - буфер результата
' nLen - размер
буфера (после преобразования - длина результата)
' Значение: 0 - успешное
завершение
' -1 - недопустимое значение падежа
' -3 - результат не
поместился в буфере

Private Declare Function GetPadeg Lib "Padeg.dll" Alias
"GetFIOPadegFSAS" _
(ByVal pFIO As String, ByVal nPadeg As Long, ByVal pResult As String, ByRef nLen As Long) As Integer

' Функция преобразования
cFIO в падеж nPadeg
Public Function MakePadeg(ByVal cFIO
As String, ByVal nPadeg As Long) As String
On Error GoTo
ErrorHandler

Dim tmpS As String
Dim nLen As Long
Dim RetVal As Integer
If Len(cFIO) = 1 Then Exit Function
nLen =
255
tmpS = String(nLen, 0)
RetVal = GetPadeg(cFIO, nPadeg, tmpS,
nLen)
If RetVal = -1 Then MsgBox "Недопустимое значение падежа - " & "("
& nPadeg & ")", , "Склонение ФИО"
MakePadeg = Mid(tmpS, 1,
nLen)

Exit Function
'----------------------ErrorHandler-------------------------
ErrorHandler:
MsgBox
"Ошибка - " & Err.Number & vbCrLf & vbCrLf & Err.Description,
vbExclamation, _
"Module: mdlФИО_Обработка Function: MakePadeg"
End Function

вот этот маленький код решает все
большие проблемы со склонением! Работать с ним фантастически легко! Сколько
использую, все не могу удержаться от восторженных восклицаний ;)

strФИО =
MakePadeg(Me.txtФИО.Value, 4)

если в поле txtФИО было значение: Салихов
Рафаиль Ильдусович, то вызываемая функция
присвоит строковой переменной значение: Салихова
Рафаиля Ильдусовича

Как видите, получить требуемое
склонение просто - достаточно вызвать функцию, передать ей значение и указать
порядковый номер падежа и все! функция возвращает просклоненную строку ;)

выше я публиковал код получения
такого результата:  Салихов Р. И.

если заменить строку

strФИО = Me.txtФИО.Value

на

strФИО =
MakePadeg(Me.txtФИО.Value, 4) ' на КОГО ? запрос на
изменение падежа dll-кой

то мы получим результат: Салихова Р. И.

Возможности библиотеки просто
огромны! Восстановление именительного падежа как Вам нравится ? Ведение
собственного словаря исключений позволяет тонко настроить склонение самых
каверзных имен. Все это описано в прилагаемой справке, я лишь показал самую
необходимую возможность использования....Авторы очень серьезно подошли к решению
проблемы, за что им огромнейшая благодарность и признание их бескорыстного
труда.

Я надеюсь, после прочтения этой
статьи для Вам не останется трудностей в управлении атрибутами людей.

назад