Распечатать страницу

Форма "Содержание книг" в Visual FoxPro

« Назад

Форма использует все таблицы базы данных HomeLibrary (рис. 2.25).

18.1.-Окружение-данных-формы-Содержание-книг

Рис. 2.25. Окружение данных формы "Содержание книг"

В сетке формы отображаются данные таблиц BooksContent и WorkType (рис. 2.26).

18.2.-Форма-Содержание-книг

Рис. 2.26. Форма "Содержание книг"

Источником данных сетки является таблица BooksContent, источником столбца "Произведение" сетки – поле BooksContent.Name, а столбца "Вид" – поле WorkType.WorkType. Между таблицами BooksContent и WorkType в окружении данных формы установлена связь по индексу TypeId (см. рис. 2.25). Тип связи "один к одному" (рис. 2.27).

18.3.-Связь-между-таблицами-BooksContent-и-WorkType

Рис. 2.27. Связь между таблицами BooksContent и WorkType

Такая связь позволяет в столбце "Вид" отображать соответствующее название вида произведения, находя его в таблице WorkType по значению BooksContent.TypeId.

Заголовок надписи Label2, расположенной над сеткой формы, отображает название книги и фамилии (с инициалами) ее авторов. Изменяет заголовок обработчик события AfterRowColChange сетки формы:

&& Обработчик события AfterRowColChange сетки Grid1 формы "Содержание книг"

&&

lparameters nColIndex

with ThisForm

if Deleted( ) then

.Command2.Enabled = .F.

.Command3.Caption = "Возвратить"

else

Command2.Enabled = .T.

Command3.Caption = "Удалить"

endif

endwith

&&

&& Формируем значение переменной auList – строку со списком авторов книги

&& Выбираем все записи без пометки удаления

set deleted on

dimension aAuthors(20)

aAuthors = ''                       && Инициализация массива

&&

&& Заносим в массив данные об авторах книги с кодом Books.BookId

select Author from Authors, BooksAuthors ;

where Authors.AuthorId = BooksAuthors.AuthorId ;

and BooksAuthors.BookId = BooksContent.BookId ;

order by Author ;

into array aAuthors

&&

auList = ''

if not Empty(aAuthors(1)) then

&& В массиве имеется по крайней мере один не пустой элемент

список авторов

auList = auList + ThisForm.ShortAuthor(au) + ', '

next

&& Удаляем последние запятую и пробел

auList = Substr(auList, 1, Len(auList) – 2)

endif

&&

&& Находим название книги

bookName = Trim(Lookup(Books.Book, BooksContent.BookId, Books.BookId, 'BookId'))

&&

&& Заголовок надписи Label2

ThisForm.Label2.Caption = bookName + Iif(Empty(auList), '', '; ' + auList)

set deleted off

Обработчик обращается к добавленному в форму методу ShortAuthor, принимающему фамилию, имя и отчество автора и возвращающему фамилию автора и его инициалы:

&& Метод ShortAuthor формы "Содержание книг"

&&

parameters auFull

nWords = GetWordCount(auFull)   && Число слов в строке auFull

sAu = GetWordNum(auFull, 1)       && Фамилию берем полностью

for k = 2 to nWords            && Добавляем инициалы

sAu = sAu + " " + Left(GetWordNum(auFull, k), 1) + "."

next

return sAu                           && Возвращаем фамилию с инициалами

Записи в сетке формы упорядочены по индексу BookIdName с индексным выражением TRANSFORM(BookId) + Name. Индекса с выражением Name таблица не имеет, поэтому обработчик события Click кнопки "Найти" использует последовательный поиск в таблице BooksContent – команду LOCATE:

&& Обработчик события Click кнопки "Найти"

&&

with ThisForm

.Wk = InputBox("Введите название произведения или часть названия", ;

"Поиск произведения", .Wk)

if not Empty(.Wk)

set exact off

recOld = Recno( )

locate for BooksContent.Name =.Wk

if not Found( ) then

MessageBox('Произведение по строке ' +.Wk + ' не найдено', 48)

&& Возврат к записи, с которой был начат поиск

go recOld

&& Делаем кнопку "Далее" недоступной

Command5.Enabled = .F.

else

&& Делаем доступной кнопку "Далее"

Command5.Enabled = .T.

endif

endif

.Grid1.SetFocus

endWith

Свойство Wk, добавленное в форму, хранит подстроку поиска, которая после первого удачного поиска используется обработчиком события Click кнопки "Далее", обеспечивающим поиск по значению свойства Wk следующей записи таблицы BooksContent:

&& Обработчик события Click кнопки "Далее"

&&

set exact off

recOld = Recno( )

&& Поиск следующей, отвечающей строке поиска записи

continue

if not Found( )

&& Возврат к записи, с которой был начат поиск

go recOld

&& Делаем кнопку "Далее" недоступной

This.Enabled = .F.

endif

ThisForm.Grid1.SetFocus

Кнопка "Далее", имеющая имя Command5, при открытии формы недоступна: ее свойство Enabled установлено в .F. В случае удачного поиска по кнопке "Найти" кнопка становится доступной и остается в таком состоянии, пока повторный поиск по строке, хранимой свойством Wk, дает положительные результаты. Также кнопка окажется недоступной, если новый поиск, инициированный кнопкой "Найти", не даст результатов.

Оба обработчика в случае неудачного поиска не меняют позиции таблицы BooksContent, выполняя команду GO recOld.

Ввод новой или редактирование существующей записи таблицы BooksContent выполняется в форме WorkEdit. Чтобы ввести значение вида произведения, необходимо разорвать связь между таблицами BooksContent (родительской) и WorkType (дочерней). Если этого не сделать, то позиция таблицы WorkType будет определяться значение TypeId родительской таблицы. После закрытия формы WorkType связь между таблицами должна быть восстановлена. Все эти операции выполняются обработчиками события Click кнопок "Добавить" и "Изменить" формы "Содержание книг".

&& Обработчик события Click кнопки "Добавить"

&&

formName = appPath + 'Forms\WorkEdit'

&&

&& Разрываем связь между BooksContent и WorkType

select BooksContent

set relation off into WorkType

do form (formName) with 'new'

&&

&& Устанавливаем связь между BooksContent и WorkType

set order to tag TypeId in WorkType

set relation to TypeId into WorkType in BooksContent

ThisForm.Grid1.SetFocus

Заметим, что связь разрывается на все время работы с формой WorkEdit, поскольку она открывается модально. После закрытия модальной формы выполнение программы будет продолжено с оператора, расположенного вслед за командой DO FORM.