Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Laboratornye_po_BD_1-6.doc
Скачиваний:
114
Добавлен:
07.03.2016
Размер:
33.23 Mб
Скачать

Лабораторная работа № 6

Тема: Расширенное использование экранных форм

Цель: Изучить возможности создания многотабличных форм, использование стандартного компонента табличного представления и редактирования данных Grid.

Система VFP предоставляет разработчику два способа создания экранных форм, ориентированных на одновременный просмотр и редактирование данных из нескольких таблиц. Зачастую это единственный подход, позволяющий наглядно представить логически связанные данные, хранимые в разных таблицах, конечному пользователю. Наиболее простым способом является использование мастера построения многотабличных форм.

Для запуска мастера достаточно в менеджере проекта во вкладке Documents выбрать элемент Forms и нажать кнопку New. Система выведет запрос о необходимости использования конструктора или мастера построения форм (рис. 1).

Рис. 1 Окно запроса способа создания экранной формы

Для запуска мастера достаточно нажать кнопку Form Wizard, после чего появится запрос типа создаваемой формы (рис. 2).

Рис.2 Окно выбора типа мастера создания экранных форм

В появившемся окне необходимо выбрать строку One-to-Many Form Wizard, и нажать кнопку OK, после чего и будет запущен мастер создания многотабличных форм.

Работа мастера состоит из шести последовательных этапов. На первом этапе необходимо указать родительскую таблицу, используемую на создаваемой форме, а также поля из этой таблицы, которые будут присутствовать на экране (рис. 3). Допускается выбирать не все поля таблицы, но поля, входящие в первичный ключ должны присутствовать обязательно. Следует также помнить о том, что не выбранные поля в дальнейшем для редактирования на самой форме будут недоступны. После выбора необходимых полей станут активными кнопки Back, Next и Finish, которые позволяют перейти к предыдущему, следующему шагу и закончить работу мастера соответственно.

Рис. 3 Окно выбора родительской таблицы

Для перехода ко второму этапу следует нажать кнопку Next, в результате чего появится окно запроса дочерней таблицы (рис. 4). Во избежание ошибок из списка доступных таблиц базы данных исключается таблица, уже выбранная в качестве родительской. Как и на предыдущем шаге, система предлагает выбрать также необходимые поля, но следует помнить, что поля, входящие в состав внешнего ключа должны присутствовать обязательно.

Рис. 4 Окно выбора дочерней таблицы

Переход к третьему этапу осуществляется нажатием кнопки Next. На этом этапе разработчику предоставляется возможность определения связи данных (рис. 5). Тип связи по определению устанавливается Один-ко-Многим и изменить его нельзя. Однако допускается установка связей, не прописанных в конструкторе базы данных. Выбор полей для связи осуществляется при помощи ниспадающих списков, в левом отображаются поля родительской таблицы, а в правом – индексные выражения и поля дочерней. Следует внимательно следить за совпадением типов полей в связи, в случае несовпадения которых система даст заведомо неправильный результат.

Рис. 5 Окно определения связи между таблицами

Примечание: Не забывайте, что связь устанавливается не по названиям полей, а по фактически хранимым данным. Т.е. система вполне допускает установку логически неправильных связей, например, между кодом заказа и кодом товара.

На четвертом шаге разработчик имеет возможность выбора стиля создаваемой формы (рис. 6). Образец экранного исполнения можно увидеть тут же, в левой верхней части окна. Так же можно выбрать набор кнопок навигации и управления, к которому автоматически привязывается программный код. Набор кнопок создается на основе класса, определенного в библиотеке классов. По умолчанию, при создании проекта, система автоматически генерирует два класса, основанных на текстовых и графических кнопках.

Рис.6 Окно выбора стиля создаваемой формы

В случае выбора опции No buttons, будет создана форма, вообще не содержащая элементов управления. Соответственно, в этом случае, их создание возлагается целиком на разработчика.

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

Рис. 7 Окно определения сортировки данных

Добавление/удаление выбранных полей осуществляется кнопками Add/Remove соответственно. Кроме этого, при помощи переключателей Ascending/Descending, можно указывать направление сортировки, по возрастанию или по убыванию. Однако для всех выбранных полей направление сортировки может быть только одним, т.е. нельзя указать для первого поля сортировку по возрастанию, а для второго – по убыванию.

После указания условий сортировки данных можно перейти к последнему, шестому шагу создания многотабличной формы (рис. 8). В появившемся окне разработчик может указать заголовок формы. Под заголовком в данном случае понимается простая текстовая надпись, расположенная в верхней части создаваемой формы. При помощи набора переключателей разработчик может выбрать тип действий после завершения работы мастера: сохранить форму для дальнейшего использования; сохранить и немедленно запустить; сохранить и открыть в конструкторе для редактирования. Перед сохранением возможно просмотреть внешний вид полученной формы при помощи кнопки Preview.

Расположенные тут же два опциональных компонента Use field mappings и Override with DBC field display classes рекомендуется использовать с великой осторожностью, т.к. они отвечают за использование карт полей и применение к экранным элементам ввода классов, определенных в контейнере базы данных, и описанных в библиотеке классов проекта.

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

Рис. 8 Окно завершающего шага мастера построения многотабличных форм

Создание многотабличных форм при помощи конструктора

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

Гораздо более эффективным представляется создание многотабличных форм при помощи конструктора. В этом случае разработчик не ограничен никакими условиями, кроме требований системы. Для запуска конструктора в окне запроса способа создания экранных форм (см. рис. 1) следует выбрать New Form, после чего, в рабочей области главного окна VFP появится окно конструктора форм и окно свойств. Рекомендуется в окружение данных формы изначально добавить все таблицы, которые будут использоваться в дальнейшем. (Добавление таблиц в окружение данных формы описано в предыдущей работе.) В случае если в самой базе данных определены связи между таблицами, они будет перенесены в окружение данных формы, но с небольшими оговорками, а именно:

  1. Независимо от определения направления связи в базе данных, в окружении данных формы главной будет считаться таблица, добавленная первой. Изменить это в дальнейшем нельзя.

  2. В окружении данных формы не может быть таблицы, являющейся дочерней более чем для одной другой таблицы. Связь будет установлена только для одной родительской таблицы, другая же будет утеряна. Установка связи насильственно проблему не решает, т.к. являющаяся по логике базы данных родительской, таблица будет дочерней, что непосредственно отразится на правильности отображаемых данных.

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

Использование компонента табличного просмотра/редактирования Grid

Т.к. одной строке данных в родительской таблице могут соответствовать произвольное количество строк дочерней таблицы, возникает необходимость отображения множественного массива однотипных записей. Для этого существует стандартный компонент Grid, позволяющий отображать данные на форме в виде таблицы (рис. 9). Для добавления этого компонента на форму достаточно выбрать его на панели Form Controls и щелкнуть левой кнопкой мыши в произвольном месте созданной формы. После этого пустой компонент будет добавлен на форму и станет доступным для редактирования (рис.10). Его свойства и методы можно просмотреть и отредактировать в окне Properties.

Рис. 9 Окно Form Controls с выделенным компонентом Grid

Рис. 10 Форма с добавленным пустым компонентом Grid

Основные свойства компонента Grid Таблица 1.

Свойства

Назначение

ColumnCount

Определяет количество столбцов в Grid’е. По умолчанию установлено –1, что является признаком отсутствия столбцов вообще.

DeleteMark

Определяет наличие столбца в левой части таблицы с признаком пометки на удаление.

GridLines

Определяет начертание сетки таблицы внутри самого компонента.

Name

Задает имя компонента, по которому будет осуществляться дальнейшее обращение к нему.

ReadOnly

Определяет свойство разрешения записи

RecordSource

Определяет имя источника данных.

RecordSourceType

Определяет тип источника данных. Допускаются значения:

0 – Table таблица базы данных

1 – Alias открытая рабочая область

2 – Prompt источник запрашивается у пользователя в процессе работы

3 – Query файл запроса

4 – SQL Statement результат выполнения команды SELECTSQL

RowHeight

Определяет высоту строк. Задается для всех отображаемых строк.

ScrollBars

Задает наличие полос прокрутки.

Visible

Определяет видимость компонента на форме.

Обратите внимание, что при установке значения свойства ColumnCount больше 0, в окне Properties станут доступны свойства подобъектов (рис. 11). Из рисунка видно, что сам компонент Grid состоит из составных объектов Column, которые в свою очередь состоят из подобъектов Header и Text. Для редактирования свойств подобъекта Grid’а необходимо его выбрать в ниспадающем списке окна Properties.

Рис. 11 Иерархия объектов компонента Grid

У объектов типа Column наиболее значимым является свойство ControlSource, которое определяет источник данных для столбца, а точнее, название таблицы и поля, разделенные точкой, из которого будут браться данные для отображения, например Ordsaled.icdOrder. У столбцов так же существует свойство видимости Visible, используя которое можно скрывать от пользователя данные, которые он не должен видеть.

Каждый столбец имеет заголовок Header, который определяет надпись вверху столбца. За текст надписи отвечает свойство объекта Header Caption. Значение надписи заголовка столбца может быть установлено как в режиме разработки путем явного указания текста в свойствах объекта, так и в процессе работы с формой посредством явного присваивания свойства, например:

thisform.Grid1.Column1.Header1.Caption=”Новый текст заголовка

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

Подобъект Text каждого столбца, является объектом ввода Text Box и обладает всеми его свойствами. (Свойства Text Box описаны в предыдущей работе.) Существует возможность расширения набора типов компонентов столбца, т.е. вместо текстового поля отображать в столбце Grid’а другие объекты. Для этого необходимо в режиме конструктора форм выбрать компонент Grid, правой кнопкой мыши вызвать контекстное меню и выбрать пункт Edit (рис 12). При этом система перейдет в режим редактирования составного объекта, о чем будет свидетельствовать визуальное изменение рамки выбранного объекта (вместо точек изменения размера объекта на экране появится цветная полосатая рамочка вокруг объекта). После этого на панели Form Controls нужно выбрать добавляемый компонент и левой кнопкой мыши щелкнуть на столбце Grid, в который будет добавлен выбранный компонент. После этого в свойстве столбца Grid CurrentControl появится возможность выбора текущего типа объекта столбца (рис. 13). Работа с новым типом производится в стандартном режиме.

При запуске формы новый тип объекта по умолчанию будет отображаться только в текущей строке. Для управления отображением служит свойство столбца Sparse, изначальное значение которого True. Установив значение этого свойства False, разработчик может принудительно заставить систему отображать новый тип объекта в каждой строке Grid. В случае, если высоты строки для отображения нового типа объекта недостаточно ее следует увеличить путем изменения значения свойства Grid RowHeight.

Рис. 12 Переход в режим редактирования составного объекта

Рис. 13 Изменение типа объекта столбца

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

Обратите внимание, что при изменении содержимого источника данных (добавление/удаление записей), а так же при изменениях в свойствах Grid, возникает необходимость обновления прорисовки формы командой thisform.Refresh(). Кроме того, следует помнить, что любое закрытие источника данных в процессе работы приведет к его потере для компонента Grid. В этом случае придется предусмотреть программное восстановление связи с источником данных. Лучше всего программный код прописать сразу после нового открытия источника. При этом программа должна содержать команды всех необходимых изменений свойств Grid и его подобъектов, например:

*Использование оператора WITH ... ENDWITH для работы со свойствами некоторого объекта

*в основном используется для уменьшения объема прописываемого кода

*

*строки, начинающиеся с символа * являются необязательными коментариями ;)

*

*Указаный блок WITH ... ENDWITH эквивалентен последовательному использованию команд

* thisform.Grid1.RecordSourceType= 1

* thisform.Grid1.RecordSource = "goods"

* thisform.Grid1.Column1.Header1.Caption="Столбец1"

WITH thisform.Grid1

*Установка связи с источником данных

.RecordSourceType= 1

*в качестве источника указана рабочая область с именем goods

.RecordSource = "goods"

*изменение названия первого столбца

.Column1.Header1.Caption="Столбец1"

*далее могут располагаться другие команды по изменениям свойства Grid

ENDWITH

*Обновление формы

thisform.REFRESH()

Организация работы с несколькими таблицами на одной форме

В принципе работа с несколькими таблицами ничем не отличается от работы с одной таблицей. Только необходимо помнить, что все операции проводятся по умолчанию в текущей рабочей области. Соответственно, при работе с многотабличной формой необходимо перед выполнением некоторых действий следует сделать нужную рабочую область текущей командой SELECT <alias>, например:

*выбрать рабочую область ordsalem

SELECT ordsalem

*добавить пустую запись

APPEND BLANK

*выбрать рабочую область ordsaled

SELECT ordsaled

*перейти к следующей записи

SKIP

данный программный код добавит пустую запись в таблицу ORDSALEM, а в таблице ORDSALED передвинет указатель на следующую запись. При этом все дальнейшие операции будут проводиться с таблицей ORDSALED, пока не будет выбрана другая рабочая область!

Возможен вариант явного указания рабочей области, для которой будет выполнена команда, путем использования служебного слова IN в тексте самой команды: APPEND BLANK IN ORDSALEM. Этот вариант выгоден, когда необходимо выполнить очень небольшой блок команд, при этом текущая рабочая область останется не измененной. Указанная команда не изменяет текущую рабочую область, и дальнейшая работа будет производиться с рабочей областью, которая была текущей до выполнения команды.

В отличии от жестких решений, предлагаемых мастером построения, разработчик имеет гораздо большую свободу при организации интерфейса экранных форм. Одним из вариантов организации работы с несколькими таблицами является создание персонального набора элементов управления для каждой таблицы, т.е. при работе с двумя таблицами, на форме организуются два набора кнопок управления. При этом желательно каждый набор визуально выделять в отдельный функциональный блок и, рекомендуется, использовать разные поясняющие текстовые надписи на самих кнопках, например: «Добавить заказ», «Добавить товар в заказ». Соответственно в программном коде кнопок, следует явно указывать, для какой таблицы производится действие.

Ниже схематично представлен вариант визуальной организации работы с несколькими таблицами на одной форме (рис. 14). Обратите внимание, что навигация по каждой таблице осуществляется пользователем при помощи полос прокрутки, что позволяет избавиться сразу от нескольких кнопочных элементов управления.

Рис. 14 Пример организация работы с несколькими таблицами

Программная организация связи данных

Существует множество способов программной организации связи данных. Один из них базируется на использовании команды SET RELATION TO. При этом в процессе работы система устанавливает временную (будет существовать до закрытия таблиц или насильственного сброса связи) связь двух таблиц, даже при отсутствии таковой в базе данных. Однако, при использовании этой команды необходимо организовать систему индексов в подчиненной таблице, т.к. указать связь по двум полям невозможно. Следующий программный код устанавливает связь между таблицами Customer и Orders, где Orders является подчиненной таблицей:

USE Customer

USE Orders

SELECT Orders

*установка текущего индексного тэга для таблицы Orders

SET ORDER TO TAG Cust_ID

SELECT Customer

*установка связи между таблицами

SET RELATION TO Cust_ID INTO Orders

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

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

Для визуальной эмуляции связи данных удобно использовать команду установки фильтра данных SET FILTER TO <условие>, например:

SET FILTER TO ordsaled.icdorder=ordsalem.icdorder IN ordsaled

thisform.Refresh()

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

Располагать код эмуляции связи можно в произвольном месте, однако наиболее выгодным при использовании Grid’ов является метод AfterRowColChange, который выполняется автоматически после выбора строки в Grid. Программный код следует расположить в методе Grid’а, отвечающего за отображение данных из главной таблицы, (на рис. 14 он располагается в методе AfterRowColChange левого Grid’а).

Недостатком такого метода можно считать то, что данные на экране во втором Grid будут представлены в полном объеме, пока пользователь не произвел выбор строки в первом. Однако это можно обойти, предусмотрев насильственную установку связи в автоматически выполняемом методе (например, метод Load формы, который выполняется при запуске экранной формы). Кроме того, второй Grid и элементы его управления изначально можно сделать невидимыми (установив значение их свойства Visible равным False), а показывать только после выбора строки в первом Grid.

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

При добавлении данных в подчиненную таблицу не следует забывать, что по–умолчанию добавляется пустая строка. Соответственно, она никак не может удовлетворять условиям наложенного фильтра и отображаться на экране не будет. В этом случае необходимо насильственно присвоить значение поля, используемого для эмуляции связи, например:

*выбираем главную таблицу

SELECT ordsalem

*сохраняем значение поля связи во временной переменной temp

temp=ordsalem.icdorder

*возвращаемся к подчиненной таблице

SELECT ordsaled

*добавляем ПУСТУЮ запись

APPEND BLANK

*присваиваем в подчиненной таблице значение поля связи

REPLACE ordsaled.icdorder WITH temp

*обновляем форму

thisform.Refresh()

в данном случае полю icdorder в подчиненной таблице сразу после добавления записи присваивается значение, совпадающее со значением поля связи из главной таблицы. Новая строка удовлетворяет условию фильтрации и будет отображена на форме. Представленный код прописывается в кнопке «Добавить товар в заказ» на рис. 14.

Примечания:

  1. При выборе типа источника данных для элемента Grid RecordSourceType = Alias, источник содержимого рабочей области не важен. Это может быть и таблица базы данных, и представление данных (как локальное, так и удаленное), и результат выполнения команды SELECT – SQL. Это важно в случаях, если в таблицах хранятся данные малопонятные пользователю.

  2. Не стоит увлекаться использованием элементов табличного представления, иногда достаточно простых листовых вкладок (компонент PageFrame).

  3. Следует помнить, что конечный пользователь может не обладать достаточной компетенцией как оператор ЭВМ, и снабжать все функциональные элементы подробными надписями об их действии (надпись на кнопке должна быть не просто «Добавить», а «Добавить товар»).

  4. Не забывайте, что любое изменение данных в таблицах будет отображено на форме только после ее перерисовки. Можно использовать команду thisform.Refresh().

  5. Позиция курсора в Grid и таблице, являющейся источником данных для него, совпадают. Т.е. не стоит слишком стремиться к получению значения из Grid’a, достаточно взять значение поля из таблицы (<переменная> = <таблица>.<поле>).

  6. Не забывайте отслеживать текущую рабочую область. Иногда смена области может происходить совсем не там и не так, как планировал разработчик. От явного указания рабочей области перед выполнением каких–либо действий большой беды не будет.

Задания

  1. Создайте однотабличную форму справочника товаров с использованием компонента Grid. На форме должны быть предусмотрены управляющие элементы в виде набора кнопок, осуществляющие добавление и удаление позиции товара.

  2. Создайте мастером построения многотабличную форму, обеспечивающую работу с заказами. Форма должна обеспечивать обработку как общих данных по заказу, так и списка товаров в заказе.

  3. Создайте форму, реализующую предыдущее задание в конструкторе. Для отображения данных из главной таблицы используйте набор текстовых полей, а для подчиненной – Grid.

  4. Видоизмените форму из предыдущего задания в конструкторе. Используйте для каждой таблицы отдельный компонент Grid.

  5. Проведите сравнительный анализ форм, созданных в заданиях 2–4. Выделите и отразите в отчете достоинства и недостатки каждой формы.

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