Форма "Содержание книг" в Visual FoxPro
« Назад Форма использует все таблицы базы данных 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 && В массиве имеется по крайней мере один не пустой элемент список авторов 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. |