Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VisualFoxPro.doc
Скачиваний:
15
Добавлен:
01.07.2025
Размер:
11 Мб
Скачать
☆

2.5.6. Форма BookEdit

Ввод и редактирование книги – записи таблицы Books выполняется в форме BookEdit (рис. 2.24).

Рис. 2.24. Ввод новой книги

Форма имеет 3 поля ввода – Book, Pdate и Price и 5 надписей. Все поля формы обязательны для заполнения, что контролируется добавленным в форму методом CheckFields.

Надпись с именем LabelBookId предназначена для отображения кода книги. При вводе новой книги заголовок надписи содержит текст "Определяется автоматически", а при редактировании записи – строку с номером кода книги:

This.LabelBookId.Caption = Transform(Books.BookId)

Значение свойства Caption надписи определяется в обработчике события Init формы.

Поле Price формы является числовым. Чтобы добиться при вводе новой записи отображения необходимого числа десятичных знаков, можно в обработчике события Init формы выполнить следующую инициализацию:

This.Price.Value = 0.00

В остальном обработчик этого события напоминает одноименный обработчик рассмотренной выше формы AuhtorEdit.

Некоторые особенности имеет обработчик события Error кнопки "Сохранить". Это связано с тем, что поле BookId таблицы Books имеет тип Integer (AutoInc) и поэтому формируется автоматически с гарантированной уникальностью. Поле не редактируется; шаг, с которым наращивается BookId, равен 1. Однако есть вероятность, что программно или интерактивно для таблицы Books будет установлено значение опции NEXTVALUE меньшее, чем максимальное значение BookId. Тогда при добавлении новой записи возникнет ошибка с номером 1884, означающая неуникальность индекса BookId. Ее истоки – неверное значение NEXTVALUE, что и отображается в выводимом в Error-обработчике сообщении.

&& Обработчик события Error кнопки "Сохранить"

&&

lparameters nError, cMethod, nLine

if nError = 1884 then

MessageBox("Неверное значение Next Value поля BookId." ;

+ Chr(13) + "Нарушается уникальность индекса BookId!", 48)

else

MessageBox("Ошибка № " + Transform(nError) + " в строке " ;

+ Transform(nLine) + " метода " + cMethod, 48)

endif

ThisForm.NoError = .F.

Предполагается, что книги разных авторов могут иметь одинаковое название; контроль достоверности введенных названий полностью возлагается на пользователя. Хотя, в принципе, можно встроить в форму поиск повторяющихся названий и предупреждать об этом при вводе и редактировании данных.

Кнопка имеет то же действие, что и такая же кнопка формы AuthorEdit.

2.5.7. Форма "Содержание книг"

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

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

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

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

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

Рис. 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

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

for each au in aAuthors && Формируем список авторов

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.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]