6. Лекция: СУБД Microsoft Visual FoxPro. Отчеты, запросы, проекты и приложения

Рассмотрены назначение и виды отчетов, запросов и проекта при работе с базами данных. Разобрана последовательность разработки отчета с помощью Мастера, виды и свойства объектов отчетов, модификация его в Конструкторе. Изложены основы разработки запросов с помощью Мастера, Конструктора и SQL-программы. Дается 2 способа создания проекта: простейшего на основе одной экранной формы и созданного с помощью Мастера приложений. Приведен синтаксис основных команд и функций алгоритмического языка системы. Цель: освоение методов создания и использования отчетов, запросов и проектов в Visual FoxPro.

Разработка отчетов

Для разработки отчетов - печатных документов, отражающих информацию базы данных, в системе VFP существует Конструктор отчетов (Report Designer) и Мастер отчетов (Report Wizard). Важным свойством отчетов является возможность группировки данных и получения итоговых данных для групп и всего отчета. При формировании отчетов можно задавать фильтр отбора необходимых данных либо формировать отчет на основе данных SQL-запроса или представления данных (View).

Наиболее просто для разработки основы отчета воспользоваться Мастером отчетов с последующей модификацией и дополнением отчета в Конструкторе.

Существует 2 типа Мастера отчетов:

One-to-Many Report Wizard - Мастер отчета, в котором для одной записи главной таблицы существует множество записей связанной с ней дочерней таблицы.

Report Wizard - Мастер простого отчета, но с возможностью задания группировки данных.

Поставим задачу разработать отчет, в котором показаны экзаменационные оценки всех студентов за зимнюю сессию 2005-2006 учебного года (с 10.01.2006 по 06.02.2006) с группировкой данных по факультетам, курсам, группам и в группе - по фамилиям студентов.

Как обычно, создание нового объекта начинаем, нажав кнопку New на стандартной панели инструментов, затем выбираем Report - Wizard - One-to-Many Report Wizard.

Далее на первом шаге Мастера (рис. 6.1) выбираем базу Students и поля главной таблицы базы (Spisok), которые мы хотим показать в отчете.

Шаг 1 Мастера разработки отчета
Рис. 6.1.  Шаг 1 Мастера разработки отчета

На втором шаге (рис. 6.2) выбираем поля дочерней таблицы - Ocenki.

Шаг 2 Мастера разработки отчета
Рис. 6.2.  Шаг 2 Мастера разработки отчета

Третий шаг - подтверждаем, что эти таблицы связаны по значению поля NZ.

На четвертом шаге необходимо задать порядок сортировки данных в отчете. Мастер позволяет задать не более трех значений полей для сложной сортировки (с созданием соответствующего сложного индекса). Выберем поля N_fclt, Kurs, N_grup с сортировкой в порядке возрастания (Ascending).

Пятый шаг (рис. 6.3) - задаем стиль отчета, расположение его на листе (вертикальный лист - Portrait или горизонтальный - Landscape) и суммарные параметры - расчет среднего значения (Avg) для поля Ball.

Шаг 5 Мастера разработки отчета
Рис. 6.3.  Шаг 5 Мастера разработки отчета

На последнем, 6-м шаге задаем заголовок отчета, выбираем команду Сохранить отчет и модифицировать его в Конструкторе отчетов - Save report and modify it in Report Designer и после нажатия на кнопку Finish задаем имя (Spisok) и место сохранения файлов отчета (будут созданы два файла с одинаковым именем и расширениями *.frt и *.frx).

В окне Report Designer мы увидим отчет, показанный на рис. 6.4.


увеличить изображение
Рис. 6.4.  Окно Конструктора отчетов

В Конструкторе отчет разбит на отдельные зоны, информация которых может присутствовать в отчете один раз (Title и Summary), в начале каждой страницы (Page Header) или в конце каждой страницы (Page Footer), в начале каждой группы (Group Header, групп может быть много) и в конце каждой группы (Group Footer), а также зона показа информации каждой записи таблицы (Detail).

Особенность отчета, созданного Мастером, - в нем присутствуют зоны итогов для группы NZ и всего отчета, но поля для расчета средней оценки в них нет, хотя мы просили Мастера это сделать (см. рис. 6.3.). Заданное условие не было выполнено, т.к. поле ball имеет текстовый тип, а мы задали функцию для работы с числами. Для вычисления средней оценки придется самим добавить новое поле в отчет с расчетом средней оценки после преобразования в этом поле текстового значения в числовое с использованием функции Val(ball).

Контекстное меню для Конструктора отчетов (щелчок правой кнопкой мыши на пустом месте окна Report Designer ) содержит следующие пункты (рис. 6.5.):

Контекстное меню
Рис. 6.5.  Контекстное меню

  • Paste - вставить;
  • Run Report: - напечатать отчет на принтере;
  • Print Preview - предварительный просмотр отчета на экране и печать на принтере;
  • Data Environment: - окно данных, связанных с отчетом;
  • Optional Bands: - страница свойств зон Title, Summary и Detail в окне свойств отчета;
  • Data Grouping: - страница группировки данных в окне свойств отчета;
  • Variables: - страница переменных в окне свойств отчета;
  • Properties: - окно свойств отчета.

Для использования в отчете названий факультетов, специальностей и предметов необходимо открыть окно Data Environment, добавить в него справочные таблицы базы и правильно установить связи между ними, как показано на рис. 6.6. (для постоянных связей базы иногда возникает неправильное направление, связь должна идти от поля главной таблицы к индексу дочерней).

Окно данных отчета
Рис. 6.6.  Окно данных отчета

Для связи между таблицами Spisok и Ocenki должно быть установлено свойство OneToMany = .T.

Для таблицы Spisok в окне Properties для Data Environment зададим фильтр VAL(Ocenki.ball)>1 AND VAL(Ocenki.ball)<6 AND Ocenki.data_b=>{^2006/01/10} AND Ocenki.data_b<={^2006/02/06} - условие отбора студентов, у которых есть оценки (от 2 до 5, среди баллов могут быть отметки о неявке (Н), незачете (1), зачете (6) и пр.) в заданном периоде (в фильтре используется формат даты в виде {^ГГГГ/ММ/ДД}). Установленный фильтр имеет особенность: фильтр задан для таблицы Spisok, а его логическое выражение построено из значений полей таблицы Ocenki, что не совсем обычно, но допустимо при наличии связи между этими таблицами. Если данное выражение написать как фильтр для таблицы Ocenki, в отчет могут попасть студенты, у которых нет оценок за заданный период, и средняя оценка будет рассчитана неправильно.

Для дальнейшего оформления отчета необходимо присутствие на экране двух панелей инструментов - Report Controls и Layout.

Первая панель содержит те объекты, которые можно располагать на отчетах (рис. 6.7.).

Панель объектов отчета
Рис. 6.7.  Панель объектов отчета

Так как наша задача - представить отчет с группировкой и расчетом средних оценок по факультетам, курсам, группам, необходимо добавить новые группы в отчет и модифицировать, соответственно, индексный файл главной таблицы. Выбрав пункт Data Grouping в контекстном или главном меню (раздел Report), добавим необходимые группы (рис. 6.8.).

Страница группировки данных в окне свойств отчета
Рис. 6.8.  Страница группировки данных в окне свойств отчета

Далее перенесем номера факультетов, курсов и групп в зоны заголовков соответствующих групп, добавим поля с названиями из справочников факультетов, специальностей и предметов, добавим итоговые поля для расчета средних оценок (val(ocenki.ball)). Новые поля можно создать с использованием соответствующей кнопки на панели Report Controls (рис. 6.7.) или копированием имеющихся в отчете полей (для сохранения заданного шрифта) с изменением данных, которые показывает поле (свойство Expression поля).

В свойствах итоговых полей (окно свойств выбранного поля открывается двойным кликом на нем, или выбором пункта Properties в его контекстном меню, или на клавиатуре Alt+Enter) в разделе Calculate следует правильно указать в пункте Calculation Type - Average (среднее) и в пункте Reset based on - соответствующую группу или End of Report для зоны Summary (см. рис. 6.9.).


Окно свойств поля отчета. Страницы General и Calculate
Рис. 6.9.  Окно свойств поля отчета. Страницы General и Calculate

Для таблицы Spisok следует модифицировать созданный Мастером сложный индекс с именем WIZARD_1 - добавить в него поле FIO: STR(n_fclt,2,0) + STR(kurs,1,0) + n_grup + fio.

Отчет в Конструкторе будет иметь вид, показанный на см. рис. 6.10..


увеличить изображение
Рис. 6.10.  Окончательный вид отчета в Конструкторе

При предварительном просмотре (Preview) или после печати на принтере мы получим отчет, показанный на рис. 6.1. (примечание: перед формированием отчета откройте таблицу Ocenki, иначе заданный фильтр для таблицы Spisok вызовет сообщение об отсутствии алиаса Ocenki).


увеличить изображение
Рис. 6.11.  Фрагмент отчета, напечатанного на принтере

Отбор данных из базы с использованием SQL-запросов

Ранее отмечалось, что для работы с данными, отобранными в соответствии с каким-либо условием, может быть использована команда SET FILTER TO <условие> - установить фильтр для открытой таблицы базы данных.

Однако большими возможностями обладает так называемый SQL-запрос - команда SELECT :, сформированная в соответствии с правилами языка запросов SQL (Structured Query Language).

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

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

В VFP и других системах фирмы Microsoft (Word, Excel) можно использовать Конструктор запросов, что упрощает и ускоряет написание запросов. Кроме того, в VFP есть Мастер для разработки запросов разного вида. Однако использование этих средств не позволяет реализовать все возможности языка запросов. Максимальные возможности - при написании запроса в текстовом виде в любом программном модуле в соответствии с синтаксисом команды SELECT (полный синтаксис будет описан далее).

Принцип формирования запросов наиболее легко освоить при использовании Мастера запросов.

Поставим задачу отобрать информацию по экзаменационным оценкам студентов по факультету № 1 за 1-й семестр 2005/2006 учебного года по предмету № 1 ("Математика" в справочной таблице) с сортировкой данных по группам, в группах - в порядке уменьшения оценки.

Для этого выбираем на стандартной панели или в меню команду New, далее выбираем Query и нажимаем кнопку Query Wizard. В появившемся списке из трех пунктов: Cross-Tab Wizard, Graph Wizard и Query Wizard выбираем последний вариант - стандартный запрос.

На первом шаге Мастера необходимо выбрать таблицы и поля, которые следует включить в запрос. Если предварительно база данных не была открыта, следует ее выбрать с помощью кнопки рядом с полем списка Databases and tables. Выбор полей может быть выполнен из нескольких таблиц базы (рис. 6.12.).

Мастер запросов - шаг 1
Рис. 6.12.  Мастер запросов - шаг 1

На шаге 2 следует добавить в список связей выражение SPISOK.NZ = OCENKI.NZ, что Мастер сам предложит вам сделать.

На шаге 2а вам нужно ответить на вопрос, какие записи при объединении таблиц следует включать в результаты (join conditions - условия объединения):

only matching rows - отбираются только записи при их одновременном присутствии в обеих связанных таблицах для заданных условий отбора и связей (условие объединения Inner Join);

all rows from table SPISOK - отбираются все записи таблицы SPISOK, соответствующие условиям отбора, и связанные записи другой таблицы при их наличии (Left Outer Join);

all rows from table OCENKI- отбираются все записи таблицы OCENKI, соответствующие условиям отбора, и связанные записи другой таблицы при их наличии (Right Outer Join);

all rows from both tables - отбираются все записи таблиц SPISOK и OCENKI, соответствующие условиям отбора, независимо от наличия связанных записей другой таблицы (Full Join).

Выбираем первый вариант для нашего запроса.

На шаге 3 могут быть заданы условия отбора данных (количество условий - не более двух, в Конструкторе запросов или в тексте запроса можно увеличить их количество). Зададим условия - SPISOK.N_FCLT=1 and OCENKI.SEMESTR=1 (рис. 6.13.). В Мастере нельзя задать больше двух условий, в Конструкторе или тексте SQL-программы количество условий не ограничено.

Мастер запросов - шаг 3
Рис. 6.13.  Мастер запросов - шаг 3

Шаг 4 - задание условий сортировки данных. Здесь можно выбрать последовательно 3 поля таблиц, по которым следует сортировать данные, например, n_grup, ball - упорядочить по группам, внутри групп - по баллу в порядке уменьшения (Descending).

На шаге 4а можно задать процент или количество рассматриваемых записей, здесь мы оставим без изменений условие all records - все записи.

На последнем шаге 5 выберем вариант Save query and modify it in Query Designer - Сохранить запрос и модифицировать его в Конструкторе запросов, зададим путь и имя для сохранения файла запроса.

В результате на диске будет создан текстовый файл запроса с расширением *.qpr (например, query_s1.qpr), который может быть открыт как текстовый файл или в Конструкторе запросов с отображением всех условий запроса.

Как видим на рис. 6.14., в верхней половине Конструктора запросов показаны таблицы, используемые для отбора данных и связи между ними, в нижней части - присутствуют страницы для выбора полей таблиц (Fields), условий объединения (Join), отбора данных (Filter), упорядочения (Order By), группировки (Group By) и разное (Miscellaneous). Щелчок правой кнопкой мыши в окне вызовет контекстное меню, в котором можно выбрать позицию Output settings и задать тип сохранения результата отбора данных - Browse, Cursor, Table, Screen. По умолчанию используется режим Screen - данные сохраняются в курсоре (временной таблице, доступной только для чтения, автоматически уничтожающейся при завершении работы системы) и показываются на экране как Browse.


увеличить изображение
Рис. 6.14.  Конструктор запросов

Модифицируем запрос для отбора данных только по экзаменационным оценкам за 1 семестр 2005/2006 учебного года. Для этого на странице Filter добавим новые условия: semestr = 1, val(Ocenki.ball)>1, val(Ocenki.ball)<6 и YEAR(Ocenki.data_b) = 2006 (см. рис. 6.15.).


увеличить изображение
Рис. 6.15.  Страница задания условий отбора данных в Конструкторе запросов

Текст запроса на языке SQL будет выглядеть следующим образом (в контекстном меню можно воспользоваться командой View SQL):

SELECT Spisok.n_fclt, Spisok.n_grup, Spisok.fio, Ocenki.semestr,;
  Ocenki.n_predm, Ocenki.ball;
 FROM ;
     STUDENTS!SPISOK ;
    INNER JOIN STUDENTS!OCENKI ;
   ON  Spisok.nz = Ocenki.nz;
 WHERE  Spisok.n_fclt = 1;		{для всех условий задан одинаковый }
   AND  Ocenki.semestr = 1;		{приоритет (Pri.) равный 0}
   AND  Ocenki.n_predm = 1;
   AND  val(Ocenki.ball) > 1;
   AND  val(Ocenki.ball) < 6;   AND  YEAR(Ocenki.data_b) = 2006; 
 ORDER BY Spisok.n_grup, Ocenki.ball DESC

Выполнив запрос (кнопка Run на стандартной панели), мы получим результат отбора данных (рис. 6.16.).

Результаты отбора данных по запросу
Рис. 6.16.  Результаты отбора данных по запросу

Более сложный вариант - запрос с группировкой данных и расчетом групповых итогов. Поставим задачу показать средний балл для студенческих групп по экзаменационным оценкам для факультета № 1 за 1-й семестр 2005/2006 учебного года по предмету № 1. Сделать это можно путем модификации в Конструкторе предыдущего запроса.

Далее уберем лишние поля на странице Fields. При группировке данных допускается отображение только сгруппированных или итоговых данных, таких как следующие:

  • значения столбцов группировки (входящих в предложение GROUP BY);
  • расчетные значения для групп, такие, как SUM(°), AVG(°) и пр.

Не допускается отображение значений отдельных строк таблицы.

Оставим в списке полей только поле группировки - n_grup, и добавим новое поле - выражение для расчета средней оценки - AVG(VAL(ball). На странице Order By запишем одно условие - упорядочить по новому расчетному полю в порядке убывания. На странице Filter оставим все прежние условия отбора. Введем вывод результатов запроса в таблицу query_s2.dbf 1)

Текст запроса будет выглядеть следующим образом:

SELECT Spisok.n_grup, AVG(VAL(Ocenki.ball));
 FROM ;
     STUDENTS!SPISOK ;
    INNER JOIN STUDENTS!OCENKI ;
   ON  Spisok.nz = Ocenki.nz;
 WHERE  Spisok.n_fclt = 1;
   AND  Ocenki.semestr = 1;
   AND  Ocenki.n_predm = 1;
   AND  VAL(Ocenki.ball) > 1;
   AND  VAL(Ocenki.ball) < 6;
   AND  YEAR(Ocenki.data_b) = 2006;
 GROUP BY Spisok.n_grup;
 ORDER BY 2 DESC;
 INTO TABLE query_s2.dbf  

Результаты отбора данных по запросу показаны на рис. 6.17.

Отбор данных по запросу с группировкой
Рис. 6.17.  Отбор данных по запросу с группировкой

Результаты отбора данных могут быть показаны в виде диаграммы (объект Microsoft Graph). Для этого можно воспользоваться мастером построения диаграмм в VFP - в меню системы Tools - Wizards - All Wizards:, далее в окне полного списка Мастеров выбрать GraphWizard (см. табл. "Полный список Wizard-ов в VFP 9.0"). Результат построения столбчатой диаграммы показан на рис. 6.18. (после дополнительного редактирования объекта в системе VFP).

"Полный список Wizard-ов в VFP 9.0"
Application Builder
Application Wizard
Cross-Tab Wizard
Database Wizard
Documenting Wizard
Form Wizard
Graph Wizard
Import Wizard
Label Wizard
Local View Wizard
Mail Merge Wizard
Microsoft SQL Server Upsizing Wizard
One-to-Many Form Wizard
One-to-Many Report Wizard
One-to-Many Report Wizard
Query Wizard
Remote View Wizard
Report Wizard
Table Wizard
Web Publishing Wizard
Web Services Publisher

Диаграмма, построенная по результатам запроса
Рис. 6.18.  Диаграмма, построенная по результатам запроса

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

SELECT Fclt.name_f, Spisok.n_grup, Predmets.name_p,;
  AVG(VAL(Ocenki.ball));
 FROM ;
     STUDENTS!SPISOK ;
    INNER JOIN STUDENTS!OCENKI ;
   ON  Spisok.nz = Ocenki.nz ;
    INNER JOIN students!fclt ;
   ON  Fclt.n_fclt = Spisok.n_fclt ;
    INNER JOIN students!predmets ;
   ON  Predmets.n_predm = Ocenki.n_predm;
 WHERE  Ocenki.semestr = ( 1 );
   AND  VAL(Ocenki.ball) > ( 1 );
   AND  VAL(Ocenki.ball) < ( 6 );
   AND  YEAR(Ocenki.data_b) = ( 2006 );
 GROUP BY Fclt.name_f, Spisok.n_grup, Predmets.name_p;
 ORDER BY Fclt.name_f, Spisok.n_grup, Predmets.name_p, 4 DESC;
 INTO TABLE query_s3.dbf

Результаты отбора данных по запросу показаны на рис. 6.19.

Отбор данных по запросу с группировкой
Рис. 6.19.  Отбор данных по запросу с группировкой

На основе таблицы query_s3.dbf можно построить перекрестный запрос(Cross-Tab Wizard) для отображения в последующем данных на одной трехмерной диаграмме с осями X (Row) - группа, Y (Column) - предмет, Z (Data) - средний балл. Страница 3 мастера с заданием этих параметров показана на рис. 6.20.

Страница 3 мастера Cross-Tab Wizard
Рис. 6.20.  Страница 3 мастера Cross-Tab Wizard

Текст запросав системе VFP будет выглядеть следующим образом:

SELECT Query_s3.n_grup, Query_s3.name_p, AVG(Query_s3.avg_exp_4);
 FROM ;
     QUERY_S3.DBF;
 GROUP BY Query_s3.n_grup, Query_s3.name_p;
 ORDER BY Query_s3.n_grup, Query_s3.name_p;
 INTO TABLE q_cross.dbf  
DO (_GENXTAB) WITH 'Query'
BROWSE NOMODIFY

Результат выполнения перекрестного запроса показан на рис. 6.21.

Данные перекрестного запроса
Рис. 6.21.  Данные перекрестного запроса

Для полученной таблицы можно построить трехмерную диаграмму с помощью Мастера GraphWizard, показанную на рис. 6.22. (после дополнительного редактирования ее в системе VFP).

Диаграмма, построенная по данным перекрестного запроса
Рис. 6.22.  Диаграмма, построенная по данным перекрестного запроса

Разработка проекта и исполняемой программы

Основой разработки программ для операционной системы Microsoft Windows в большинстве современных систем (VFP, Delphi, Visual C++, Visual Basic и пр.) является проект (Project).

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

Создать новый проект можно с помощью Мастера разработки проекта или самостоятельно. Более целесообразно использовать Мастер, зачастую с этого и следует начинать при разработке сложной системы (после разработки базы данных - сразу создать проект с помощью Мастера системы VFP 6.0 -7.0 - этот Мастер при генерации стандартного проект предложит создать также необходимые вам экранные формы, панели инструментов, отчеты, меню и пр.).

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

Создаем новый файл проекта (New - Project - New file), выбираем для нее папку и даем имя Students.pjx. В соответствующие группы пустого окна проекта добавляем созданные нами ранее экранную форму и отчет. Если вы хотите добавить в проект базу данных, она должна быть помечена как внешняя ( Exclude). После этого окно проекта будет иметь вид, приведенный на рис. 6.23. (форма Spisok.scx выделена в нем жирно как головная программа).

Диаграмма, построенная по данным перекрестного запроса
Рис. 6.23.  Диаграмма, построенная по данным перекрестного запроса

На странице All представлены все виды компонентов, которые могут входить в состав проекта. При работе с большими проектами удобнее пользоваться отдельными страницами проект (Data, Documents, Classes, Code, Other).

Справа в окне проект расположена группа кнопок, нижняя из которых - Build: - компиляция проекта. Если мы нажмем на нее, появится список для выбора типа компиляции проекта (для тех, кто забыл: компиляция - перевод исходного текста программы на машинный язык, исполняемый в данной операционной системе).

Если скомпилировать такой проект в exe-файл (рис. 6.24.), на диске появится файл students.exe, но для данного состава проекта запускаться и нормально работать он будет только из системы VFP (из Windows он запустится и тут же завершит свою работу), т.к. в нем нет головной программы с командой запуска процесса обработки событий read events.

Компиляция проекта
Рис. 6.24.  Компиляция проекта

Для получения программы, работающей в операционной системе Windows, нужно сделать следующее:

  1. в окне проекта выбираем раздел Code - Programs (программные файлы), нажимаем New:, в чистом окне программы пишем 2 строки: do form spisok; read events сохраняем файл в своей папке с названием program1 или с другим названием и указываем в проекте, что это головная программа (правый клик на файле и выбрать команду Set Main);
  2. открываем форму Spisok и окно свойств, в окно события формы Destroy Event вписываем фразу: clear events (чтобы после закрытия формы завершался процесс обработки событий и завершалась работа программы) - рис. 6.25.

Процедура Destroy Event для формы Spisok
Рис. 6.25.  Процедура Destroy Event для формы Spisok

Далее снова компилируем программу и проверяем ее работу, запуская ее из папки Windows. Мы увидим, что окно экранной формы при запуске программы появляется внутри другого окна, имеющего некоторое стандартное меню. Если вы хотите, чтобы на экране было только окно вашей формы Spisok, можно изменить свойство формы ShowWindow на 2-As Top-Level Form и добавить первой строкой в головной файл проекта команду: _SCREEN.Visible=.F. (Вместо 2-го пункта можно создать в папке программы файл config.fpw и в нем написать строку SCREEN = OFF). В результате мы получим небольшую по размеру (около 250 Кб) программу, имеющую все основные возможности для работы с базой данных. Для запуска такой программы на другом компьютере потребуется сама база данных, файл этой программы (с расширением *.exe) и в доступном каталоге (например, Windows - System32) библиотечные файлы VFPVersionNumberR.dll and VFPVersionNumberRRUS.dll (для 9-й версии Vfp9r.dll - размер 4,49 Мб и Vfp9rrus.dll - 1,18 Мб). Может потребоваться также файл Msvcr70.dll.

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

Другой путь разработки проекта - использовать Мастер разработки приложения (Application Wizard). После выбора New - Project - Wizard появляется окно, в котором нужно задать название проекта (student) и путь его сохранения (оставим галочку у фразы "Создать структуру каталогов"). После генерации основы проекта и появления окна проекта">проекта на экране, появляется также многостраничная форма построителя проекта (Application Builder), в которой на первой странице (рис. 6.26.) следует указать, будут ли использоваться окна информации о программе и авторе (Splash и About), окно Start для выбора формы или отчета в начале работы с программой и окно User login для задания имени пользователя и его пароля.

Первая страница Построителя приложений
Рис. 6.26.  Первая страница Построителя приложений

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

Третья страница Построителя
Рис. 6.27.  Третья страница Построителя

Далее нажимаем кнопку Generate, и для всех отмеченных таблиц базы создаются стандартные формы и отчеты.

На странице 4 Forms следует указать некоторые особенности использования каждой из форм в программе:

Name - название, которое будет показано для формы в окне Start;

Single instance - открытие единственного экземпляра этого окна;

Use navigation toolbar - показывать навигационную панель (перемещения по таблице);

Use navigation menu - показывать навигационное меню;

Appear in File New dialog - форма появляется в пункте New меню и панели инструментов;

Appear in File Open dialog - форма появляется в пункте Open

На странице 5 Reports следует указать Name - название, которое будет показано для отчета в окне Start, и Appears in Print Report dialog - показывать или нет отчет в диалоге печати отчетов.

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

Как правило, экранные формы и отчеты в дальнейшем подвергаются автором значительной модификации.

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

Некоторые команды и функции для работы с базой данных

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

Полный список команд и функций с разъяснением их параметров и примерами использования можно найти в справочной системе VFP в разделе Language Reference.

Команды для работы с базами данных, таблицами, индексами, связями

  • Создать базу
    CREATE DATABASE [DatabaseName | ?]
  • Создать таблицу базы данных (SQL-команда)
    CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE] 
        [CODEPAGE = nCodePage]
        ( FieldName1 FieldType [( nFieldWidth [, nPrecision] )] [NULL | NOT NULL] 
        [CHECK lExpression1 [ERROR cMessageText1]] 
        [AUTOINC [NEXTVALUE NextValue [STEP StepValue]]] [DEFAULT eExpression1] 
        [PRIMARY KEY | UNIQUE [COLLATE cCollateSequence]] 
        [REFERENCES TableName2 [TAG TagName1]] [NOCPTRANS]
        [, FieldName2... ] 
        [, PRIMARY KEY eExpression2 TAG TagName2 |, UNIQUE eExpression3 TAG TagName3 
        [COLLATE cCollateSequence]]
        [, FOREIGN KEY eExpression4 TAG TagName4 [NODUP] 
        [COLLATE cCollateSequence] 
        REFERENCES TableName3 [TAG TagName5]] [, CHECK lExpression2 [ERROR cMessageText2]] ) 
        | FROM ARRAY ArrayName
    
  • Открыть базу данных, представление (View) или таблицу базы
    USE [[DatabaseName!]Table | SQLViewName | ?]
       [IN nWorkArea | cTableAlias] [ONLINE] [ADMIN] [AGAIN]
       [NOREQUERY [nDataSessionNumber]] [NODATA] [INDEX IndexFileList | ?
       [ORDER [nIndexNumber | IDXFileName   | [TAG] TagName [OF CDXFileName]
          [ASCENDING | DESCENDING]]]]   [ALIAS cTableAlias]   [EXCLUSIVE]
       [SHARED]   [NOUPDATE]   [CONNSTRING cConnectionString | (m.nStatementHandle) ]
    Функция ALIAS([nWorkArea]) возвращает алиас для текущей или заданной рабочей зоны.
    
  • Выбрать свободную рабочую зону (0), заданную рабочую зону или выбрать таблицу
    SELECT([ 0 | 1 | cTableAlias ])
       SELECT(0) - возвращает номер выбранной рабочей зоны
       SELECT(1) - возвращает наибольший номер свободной зоны
       SELECT 0 - выбор свободной зоны с наименьшим номером
    
  • Создать индексный файл
    INDEX ON eExpression TO IDXFileName | TAG TagName 
       [COLLATE cCollateSequence] [OF CDXFileName] [FOR lExpression]
       [COMPACT] [ASCENDING | DESCENDING] [UNIQUE | CANDIDATE] [ADDITIVE]
       [BINARY]
    
  • Открыть индекс
    SET INDEX TO [IndexFileList | ? ] 
     ORDER nIndexNumber | IDXIndexFileName |
     [TAG] TagName [OF CDXFileName] [ASCENDING |
     DESCENDING]] [ADDITIVE]
    
  • Установить порядок по индексу
    SET ORDER TO [nIndexNumber | IDXIndexFileName | 
     [TAG] TagName [OF CDXFileName] [IN nWorkArea |
     cTableAlias][ASCENDING |  DESCENDING]]
    
  • Установить связь между таблицами
    SET RELATION TO [eExpression1 INTO nWorkArea1 |
     cTableAlias1 [, eExpression2 INTO nWorkArea2 |
     cTableAlias2 ] [IN nWorkArea | cTableAlias]
     [ADDITIVE]]
    
  • Установить множественную связь между таблицами (используется при формировании отчетов)
    SET SKIP TO [TableAlias1 [, TableAlias2] ...]

Команды перемещения по таблице, поиска и отбора данных

  • Перейти к записи...
    GO [RECORD] nRecordNumber [IN nWorkArea | 
        IN cTableAlias]
    GO TOP | BOTTOM [IN nWorkArea | IN cTableAlias]
       (вместо GO можно использовать GOTO)
    
  • Переместиться по таблице (вперед или назад)
    SKIP [nRecords] [IN nWorkArea | cTableAlias]

    Для nRecords>0 - перемещение далее по таблице, для nRecords<0 - назад к предыдущим записям.

    Функция BOF() возвращает .T., если текущая запись - первая и Вы пытаетесь выполнить команду SKIP -1, аналогично для последней записи - EOF()=.T.

  • Поиск для заданного логического условия
    LOCATE [FOR lExpression1] [Scope] [WHILE]
     [NOOPTIMIZE]

    (Найти следующую запись, соответствующую условию - команда CONTINUE)

  • Поиск по значению индекса
    SEEK eExpression ORDER nIndexNumber | 
        IDXIndexFileName | [TAG] TagName 
        [OF CDXFileName] [ASCENDING | DESCENDING]] 
        [IN nWorkArea | cTableAlias]
  • Установить фильтр
    SET FILTER TO [lExpression] 
         [IN nWorkArea | cTableAlias]
  • Выполнить запрос (SQL-команда)
    SELECT [ALL | DISTINCT] [TOP nExpr [PERCENT]] Select_List_Item [, ...]
       FROM [FORCE] Table_List_Item [, ...]
          [[JoinType] JOIN DatabaseName!]Table[[AS] Local_Alias]
          [ON JoinCondition [AND | OR [JoinCondition | FilterCondition] ...] 
       [WITH (BUFFERING = lExpr)]
       [WHERE JoinCondition | FilterCondition [AND | OR JoinCondition | FilterCondition] ...]
       [GROUP BY Column_List_Item [, ...]] [HAVING FilterCondition [AND | OR ...]]
       [UNION [ALL] SELECTCommand]
       [ORDER BY Order_Item [ASC | DESC] [, ...]]
       [INTO StorageDestination | TO DisplayDestination]
       [PREFERENCE PreferenceName] [NOCONSOLE] [PLAIN] [NOWAIT]

    В качестве StorageDestination можно использовать одно из следующих предложений:

    • ARRAY ArrayName - в массив переменных памяти;
    • CURSOR CursorName - в курсор;
    • DBF TableName | TABLE TableName - в таблицу.

    В качестве DisplayDestination можно использовать одно из следующих предложений:

    • FILE FileName [ADDITIVE] - ASCII текстовый файл;
    • PRINTER [PROMPT] - вывод на принтер;
    • SCREEN - в главное окно системы VFP.

Команды для добавления, модификации и удаления данных

  • Открыть окно для работы в табличном формате с таблицей базы данных:
    BROWSE [FIELDS FieldList] [FONT cFontName [, nFontSize]] 
       [STYLE cFontStyle] [FOR lExpression1 [REST]] [FORMAT] 
       [FREEZE FieldName] [KEY eExpression1 [, eExpression2]] [LAST | NOINIT]
       [LOCK nNumberOfFields] [LPARTITION] [NAME ObjectName] [NOAPPEND]
       [NOCAPTIONS] [NODELETE] [NOEDIT | NOMODIFY] [NOLGRID] [NORGRID] 
       [NOLINK] [NOMENU] [NOOPTIMIZE] [NOREFRESH] [NORMAL] [NOWAIT] 
       [PARTITION nColumnNumber [LEDIT] [REDIT]]
       [PREFERENCE PreferenceName] [SAVE] [TIMEOUT nSeconds] 
       [TITLE cTitleText] [VALID [:F] lExpression2 [ERROR cMessageText]]
       [WHEN lExpression3] [WIDTH nFieldWidth] [WINDOW WindowName1]
       [IN [WINDOW] WindowName2 | IN SCREEN] [COLOR SCHEME nSchemeNumber]

    При описании полей (в параметре FIELDS) список может содержать следующие параметры:

    FieldName 				(имя поля)
       [:R] 				                           (только чтение)
       [:nColWidth]			                   (ширина поля)
    [:V = lExpr1 [:F] [:E = cTxt]]	       (функция, выполняемая при выходе из поля)
       [:P = cFormatCodes] 		       (формат)
       [:B = eMin, eMax [:F]]	           (диапазон данных)
       [:H = cHeadingText]		           (заголовок)
       [:W = lExpr2]				           (функция,выполняемая
                                                перед входом в поле)

    Близкий синтаксис имеют команды EDIT и CHANGE для работы с таблицей при построчном расположении полей.

  • Добавление записей
    APPEND [BLANK] [IN nWorkArea | cTableAlias] [NOMENU]
    APPEND FROM FileName | ? [FIELDS FieldList] 
       [FOR lExpression][[TYPE] [DELIMITED 
     [WITH Delimiter | WITH BLANK | WITH TAB | 
     WITH CHARACTER Delimiter] | DIF | FW2 | MOD | 
     PDOX | RPD | SDF | SYLK | WK1 |WK3 | WKS | WR1 |
     WRK | CSV | XLS | XL5 [SHEET cSheetName]| XL8 
     [SHEET cSheetName]]] [AS nCodePage]
    
    APPEND FROM ARRAY ArrayName [FOR lExpression] [
       FIELDS FieldList | FIELDS LIKE Skeleton | 
       FIELDS EXCEPT Skeleton]

    SQL-команда INSERT INTO - добавить запись с заданными значениями полей:

    INSERT INTO dbf_name [(FieldName1 [, FieldName2, ...])]
       VALUES (eExpression1 [, eExpression2, ...])
       INSERT INTO dbf_name FROM ARRAY ArrayName | FROM MEMVAR | FROM NAME ObjectName
    INSERT INTO dbf_name [(FieldName1 [, FieldName2, ...])]
       SELECT SELECTClauses [UNION UnionClause SELECT SELECTClauses ...]
  • Занести данные в поля таблицы
    REPLACE FieldName1 WITH eExpression1 [ADDITIVE]
       [, FieldName2 WITH eExpression2 [ADDITIVE]]
       ...[Scope][FOR lExpression1][WHILE lExpression2] 
      [IN nWorkArea | cTableAlias][NOOPTIMIZE]
  • Копировать данные текущей записи в массив переменных
    SCATTER [FIELDS FieldNameList | FIELDS LIKE 
     Skeleton | FIELDS EXCEPT Skeleton] [MEMO] 
     TO ArrayName | TO ArrayName BLANK | MEMVAR 
     | MEMVAR BLANK | NAME ObjectName [BLANK]

    параметр MEMVAR означает - используются переменные с теми же именами, что и имена полей записи; имя переменной в программе следует писать как m.<имя поля>).

  • Копировать данные из массива переменных в текущую запись
    GATHER FROM ArrayName | MEMVAR | NAME ObjectName
     	[FIELDS FieldList | FIELDS LIKE Skeleton | 
       FIELDS EXCEPT Skeleton] [MEMO]
  • Копирование данных таблицы в массив
    COPY TO ARRAY ArrayName [FIELDS FieldList | 
       FIELDS LIKE Skeleton | FIELDS EXCEPT Skeleton]
     [Scope] [FOR lExpr1a] [WHILE lExpression2]
     [NOOPTIMIZE]
  • Выполнить обновление данных (SQL-команда)
    UPDATE Target
       SET Column_Name1 = eExpression1 [, Column_Name2 = eExpression2 ...]
       [FROM [FORCE] Table_List_Item [[, ...] | [JOIN [ Table_List_Item]]]
       WHERE FilterCondition1 [AND | OR FilterCondition2 ...]

    Здесь Target - таблица (table), курсор (cursor) или их алиас или файл для обновления.

  • Пометить записи таблицы для удаления записи
    DELETE [Scope] [FOR lExpression1] [WHILE lExpression2]
       [IN nWorkArea | cTableAlias] [NOOPTIMIZE]
  • Удалить помеченные для удаления записи из файла
    PACK [MEMO | DBF] [Tablename ] [IN nWorkarea | cTableAlias]
  • Выполнить удаление записей (SQL-команда)
    DELETE [Target] FROM [FORCE] Table_List [[, Table_List ...] | [JOIN [ Table_List]]]
       [WHERE FilterCondition1 [AND | OR FilterCondition2 ...]]

Команды вычислений по данным таблиц

  • CALCULATE eExpressionList [Scope] [FOR lExpression1] [WHILE lExpression2][TO VarList | TO ARRAY ArrayName] [NOOPTIMIZE] [IN nWorkArea | cTableAlias]

    где для eExpressionList - можно использовать следующие функции:

    AVG(nExpression) - среднее значение
    CNT( ) 		  - количество
    MAX(eExpression) - максимальное значение
    MIN(eExpression) - минимальное значение
    NPV(nExpression1, nExpression2 [, nExpression3])   
      - банковская функция
    STD(nExpression) - стандартное отклонение
    SUM(nExpression) - сумма
    VAR(nExpression) - статистическая функция
    
    SUM [eExpressionList]   [Scope] [FOR lExpression1] 
       [WHILE lExpression2][TO MemVarNameList | 
       TO ARRAY ArrayName]   [NOOPTIMIZE]
    
    AVERAGE [ExpressionList]   [Scope] [FOR lExpression1] 
       [WHILElExpression2][TO VarList | 
       TO ARRAY ArrayName]   [NOOPTIMIZE] 
    
    COUNT [Scope] [FOR lExpression1] [WHILE lExpression2]
       [TO VarName][NOOPTIMIZE]

Математические функции

^  *  /  +  -  ABS() ACOS() ASIN() ATAN() ATN2() AVG()
BINTOC() BITAND() BITCLEAR() BITLSHIFT() BITRSHIFT() BITSET() BITTEST() BITXOR() 
CEILING() COS() COUNT() DTOR() EXP() FLOOR() FV() INT() LOG() LOG10() MAX() MIN() 
MOD() MTON() NTOM() PAYMENT() PI() PV() RAND() ROUND(,) RECCOUNT() RECNO() RTOD() 
SIGN() SIN() SQRT() SUM() TAN() VAL()

Функции для операций с текстовыми данными

+  -  ASC()  ALLTRIM()  AT(,,)  ATC(,,)  CHR()  CHRTRAN(,,)  CTOBIN()  
CURSORTOXML(,,,,)  CURVAL(,)  FILETOSTR()  GETPEM(,)  GETWORDCOUNT(,)  GETWORDNUM(,)  
LEFT(,)  LEN()  LOWER()  LTRIM()  MAX(,)  MIN(,)  OCCURS(,)  OEMTOANSI()  OLDVAL(,)  PADC(,) 
PADL(,)  PADR(,) PEMSTATUS(,,)  PROPER()  RAT(,,)  REPLICATE(,)  RIGHT(,) RTRIM()  SOUNDEX() 
SPACE()  STR(,,)  STREXTRACT(,,,,)  STRTRAN(,,)  STUFF(,,,)  SUBSTR(,,) TRANSFORM(,)  TRIM()  
TYPE()  UPPER()  $  AT_C(,,)  ATCC(,,)  CHRTRANC(,,)  LEFTC(,)  LENC( )  RATC(,,) RIGHTC(expC,) 
TEXTMERGE(,,,)  STRCONV(,)  STUFFC(,,,)  SUBSTRC(,,)

Функции для операций с данными типа "дата" и "время"

{date} CDOW() CMONTH() CTOD() CTOT() DATE() DATETIME() DAY() DMY() DOW() 
DTOC() DTOS() DTOT() GOMONTH(,) HOUR() MAX(,) MDY() MIN(,) MINUTE() MONTH() QUARTER() 
SEC() SECONDS() TIME() TTOC() TTOD() WEEK() YEAR()

Логические функции

<  >  =  <  >  <=  >=  ==  .T.  .F.  .NULL.  NOT  AND  OR  BETWEEN(,,) 
DELETED()  EMPTY()  IIF(,,) INLIST(,,)  NVL(,)  SEEK(,,) 
  1)   Параметры вывода итогов запроса могут быть следующие:INTO Destination В качестве Destination можно использовать одно из следующих предложений: ARRAY ArrayName - в массиве переменных памяти; CURSOR CursorName - в курсор; DBF TableName | TABLE TableName - в таблицу. Вместо INTO можно использовать. TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN