Сервисные функции программы рпт 76 2 Руководство пользователя 79 1Запуск программы 79

Вид материалаРуководство пользователя

Содержание


2.3 Создание приложения BDE
Подобный материал:
1   2   3   4   5   6   7   8

2.3 Создание приложения BDE



Запустите C++ Builder. Далее перейдите на закладку Standard на панели в верхней части программы и вынесите на форму приложения компонент MainMenu — главное меню для будущего приложения. Затем щелкнула по добавленному на форму элементу (MainMenu) дважды левой кнопкой мышки. В открывшемся окне с заголовком Form1->MainMenu1 сформировала основные каскадные меню:

1. Студенты

1.1. Список

-полный

-по группам

1.2 Личная карточка

1.3 Успеваемость

1.4 Оценки по ведомости

2. Ведомости

2.1 Экзаменационная

2.2 Зачетная

2.3 Сводная

3. Преподаватели

3.1 Ввод часов преподавателей

3.2 Ведомость учета часов

3.3 Отчет по часам

4. Справочники

5. Год

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

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

Для работы с компонентами меню во время разработки используется специализированный Редактор меню представленный на рисунке ____. Он открывается при щелчке на кнопке свойства items компонента меню в Инспекторе объектов или при двойном щелчке на компоненте. Он обеспечивает отображение всех элементов меню, представленных в свойстве items.

Редактор меню активно взаимодействует с Инспектором объектов. Для каждого выбранного в Редакторе элемента в Инспекторе объектов появляются значения его свойств.

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




Рисунок 2.7 - Формируем элементы главного меню в окне Form1.

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

Вид формы приложения на этапе проектирования показан на рисунке ___, где в форме размещены компоненты Table1, DataSource1, DBGrid1 и DBNavigator1.

Компонент Table1 обеспечивает взаимодействие с таблицей БД. Для связи с требуемой таблицей нужно установить соответствующие значения свойству DataBaseName, указывающему путь к БД или алиас, и свойству TableName, указывающему имя таблицы. После задания таблицы для открытия набора данных свойству Active должно быть установлено значение true.

В рассматриваемом приложении использована таблица студентов. Файлы этой и других таблиц находятся в каталоге, путь к которому указывает псевдоним UCH1. Настройка псевдонима может быть выполнена с помощью программы BDE Administrator.

Компонент DataSource1 является промежуточным звеном между компонентом Table1, соединенным с реальной таблицей БД, и визуальными компонентами DBGrid1 и DBNavigator1, с помощью которых пользователь взаимодействует с этой таблицей. На компонент Table1 с которым связан компонент DataSource1, указывает свойство DataSet последнего.



Рисунок 2.8 - Форма приложения для работы с БД

Компонент DBGrid1 отображает содержимое таблицы БД в виде сетки, в которой столбцы соответствуют полям, а строки — записям таблицы. По умолчанию пользователь может просматривать и редактировать данные. Компонент DBNavigator позволяет пользователю перемещаться по таблице, редактировать, вставлять и удалять записи. Компоненты DBGrid1 и DBNavigator1 связываются со своим источником данных — компонентом DataSource1 — через свойства DataSource.

Схема взаимосвязи компонентов приложения и таблицы БД и используемые при этом свойства компонентов показаны на рисунке 2.9.

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





Рисунок 2.9 - Схема взаимосвязи компонентов приложения и таблицы БД

Доступ к остальным таблицам организуется аналогичным образом. В основном окне программы (Список студентов) находятся:

- Успеваемость студента;

- Успеваемость за семестр;

- Распечатать личную карточку.

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

if(Form3->ShowModal()!=mrOk) return;

Variant A_,B_,T_,D_,V_;

char gg[6],sp[3];

int kurs, sem, i,oc5,oc4,oc3,oc2,kol[6],t=0;

String oo,pre2;

try{

A_ = CreateOleObject("Word.Application");

B_=A_.OlePropertyGet("WordBasic");

B_.OleProcedure("FileNew", (ExtractFilePath(ParamStr(0))+"usp.dot").c_str());

D_=A_.OlePropertyGet("ActiveDocument");

V_=D_.OlePropertyGet("Variables");

strcpy(gg,Form3->DBLookupComboBox1->Text.c_str());

if (gg[1]=='-') {sp[0]=gg[0];sp[1]=0; kurs=gg[2]-48;}

else {sp[0]=gg[0];sp[1]=gg[1];sp[2]=0; kurs=gg[3]-48;}

sem=(kurs-1)*2+(Form3->RadioButton1->Checked?1:2);

V_.OleProcedure("Add", "Nom_kurs", kurs);

V_.OleProcedure("Add", "Nom_gr", (Form3->DBLookupComboBox1->Text) .c_str());

V_.OleProcedure("Add", "Sem", Form3->RadioButton1->Checked?1:2);

V_.OleProcedure("Add", "Uch_god", ((String)uch_god+"-"+(String)(uch_god+1)).c_str());

D_.OlePropertyGet("Fields").OleProcedure("Update");

B_.OleProcedure("AppShow");

//student->Filter="Spec='"+(String)sp+"' AND Nom_kurs="+(String)kurs+" AND Nom_gr="+(String)gr;

student->Filter="Gruppa='"+Form3->DBLookupComboBox1->Text+"'";

student->Filtered=true;

Label23->Caption=Form3->DBLookupComboBox1->Text;

ocenka->Active=false;

ocenkafio_stud->Visible=false;

ocenkafio_stud->FieldKind=fkCalculated;

ocenkan_predmet->FieldKind=fkLookup;

ocenkan_predmet->Visible=true;

ocenka->IndexName="Nom_zach";

ocenka->MasterFields="";

ocenka->MasterSource=dstudent;

ocenka->MasterFields="nom_zach";

ocenka->Active=true;

student->First();

char sss[20];

kol[2]=0;

kol[3]=0;

kol[4]=0;

kol[5]=0;

while(!student->Eof)

{ocenka->First();

char oc[]="Oc0";

oc[2]=sem+48;

oc5=0;oc4=0;oc3=0;oc2=0;t=0;

pre2="";

while(!ocenka->Eof)

{if (ocenka->FieldByName(oc)->IsNull) {ocenka->Next();continue;}

oo=ocenka->FieldByName(oc)->AsString;

if (oo[1]=='2'||oo[1]=='н') {oc2++;pre2=pre2+ocenka->FieldByName("n_predmet")->AsString+" ,";}

if (oo[1]=='3') oc3++;

if (oo[1]=='4') oc4++;

if (oo[1]=='5') oc5++;

ocenka->Next();}

if (oc2>0) {t=2;T_=D_.OlePropertyGet("Tables").OleFunction("Item",5);}

else if (oc3>0) {t=3;T_=D_.OlePropertyGet("Tables").OleFunction("Item",4);}

else if (oc4>0) {t=4;T_=D_.OlePropertyGet("Tables").OleFunction("Item",3);}

else if (oc5>0) {t=5;T_=D_.OlePropertyGet("Tables").OleFunction("Item",2);}

if (t!=0) {

T_.OleFunction("Cell",kol[t]+1,2).OleProcedure("Select");

kol[t]++;

_.OlePropertyGet("Selection").OleProcedure("InsertRowsBelow",(int)kol[t]);

T_.OleFunction("Cell",kol[t]+1,2).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",student->FieldByName("Fio")->AsString.c_str());

T_.OleFunction("Cell",kol[t]+1,1).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",kol[t]);

if (t==2)

{ T_.OleFunction("Cell",kol[t]+1,3).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",pre2.c_str()); } }

student->Next();}

B_.OleProcedure("AppShow");}

catch(EOleException& e){ShowMessage("OleException "+e.Message);}

catch(EOleSysError& e){ShowMessage("OleSyserror "+e.Message);}

catch(Exception& e){ShowMessage("Exception "+e.Message);}

student->Filtered=false;

Label23->Caption=" ";

TabSheet1->Show(); }

На главной форме разместила PageControl, состоящий из вкладок:

студенты - просмотр, добавление, поиск, изменение и удаление студентов, также с этой вкладки можно распечатать успеваемость студента, группы и личную карточку;

личная карточка - сдержит основные сведения о студенте (номер зачетки, ФИО, группу, приказы о зачислении и переводе с курса на курс) и учебно-производственные практики;

оценки по студенту - при помощи компонента DBGrid выставляются оценки по всем предметам для конкретного студента;

оценки по предмету - выставление оценок по конкретному предмету студентам одной группы;

справочники - просмотр, добавление, поиск, изменение и удаление предметов, преподавателей, групп и специальностей соответственно;

часы - позволяет вводить данные об отработанных часах преподавателя.

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

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

{String aaa=((TMenuItem *)Sender)->Caption;

int aa=aaa.Pos("&");

if (aa) aaa.Delete(aa,1);

student->Filter="Gruppa='"+aaa+"'";

student->Filtered=true;

Label23->Caption=aaa;

TabSheet1->Show();}

При выборе в меню подпункта Личная карточка пользователь имеет возможность просмотреть либо добавить данные по студенту.

Для создания надписей (№ зачетки, ФИО, группа, курс, специальность и т.д) выбрала компонент label (надпись) расположенный на вкладке Standard.

Для группы и специальности поместила DBLookupComboBox, компонент представляющий собой комбинированный список значений поля синхронного просмотра для поля, заданного свойством DataFieid, из набора данных DataSource. Его основное назначение — автоматически устанавливать соответствие между полями двух наборов данных по одинаковому значению заданного поля исходной таблицы и ключевого поля таблицы синхронного просмотра. В списке синхронного просмотра отображаются возможные значения для редактирования поля основной таблицы. По своим функциональным возможностям компонент совпадает с компонентом TDBComboBox.

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

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

В поле можно передавать фиксированные значения, связанные с отдельными переключателями в группе.

Если текущее значение связанного поля соответствует значению какого либо переключателя, то он включается. Если пользователь включает другой переключатель, то связанное с переключателем значение заносится в поле. Возможные значения, на которые должны реагировать переключатели в группе, заносятся в свойство Values при помощи специального редактора в Инспекторе объектов или программно посредством методов класса TStrings. Каждому элементу свойства values соответствует один переключатель представленный на рисунке ___ (М, Ж).

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

Текущее значение связанного поля содержится в поле value.

Использование переключателя DBRadioGroup исключает возможность появления ошибок.



Рисунок 2.10 - Задание параметра Values компонента DBRadioGroup


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

Компонент может осуществлять проверку редактируемых данных по заданной для поля маске.

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

В компоненте DBGrid можно отображать произвольное подмножество полей используемого набора данных, но число записей ограничить нельзя — в компоненте всегда присутствуют все записи связанного набора данных. Требуемый набор полей можно составить при помощи специального Редактора столбцов, который открывается при двойном щелчке на компоненте, перенесенном на форму, или кнопкой свойства Columns в Инспекторе объектов.

Новая колонка добавляется при помощи кнопки Add New, после этого ее название появляется в списке колонок представленном на рисунке ___. Для выбранной в списке колонки доступные для редактирования свойства появляются в Инспекторе объектов. Колонки в списке можно редактировать, удалять, менять местами. При помощи кнопки Add All Fields в сетку можно добавить все поля набора данных.

Каждая колонка компонента TDBGrid описывается специальным классом Column, а совокупность колонок доступна через свойство columns компонента, оно имеет тип DBGridColumns и представляет собой индексированный список объектов колонок. Поле набора данных связывается с конкретной колонкой при помощи свойства FieidName класса Column. При этом в колонку автоматически переносятся все необходимые параметры поля, в частности заголовок поля, настройки шрифтов, ширина поля. После ручного изменения параметров первоначальные значения восстанавливаются методами соответствующих объектов Column.



Рисунок 2.11 - Редактор колонок компонента DBGrid

Для управления записями таблицы установлен навигатор – DBNavigator связанный с таблицей практика (praktika) через DataSource (dpraktika).

Для настройки свойств компонента DataSource необходимо выполнить следующие действия.

1. Связать набор данных и компонент DataSource. Для этого используется свойство DataSet компонента DataSource, доступное через Инспектор объектов. Это указатель на экземпляр компонента доступа к данным. В списке этого свойства в Инспекторе объектов перечислены все доступные компоненты наборов данных.

2. Переименовать компонент. Это не обязательное действие. Тем не менее желательно присваивать компонентам осмысленные имена, соответствующие названиям связанных наборов данных. Обычно название компонента комбинирует имя набора данных например dstudent, dspecial.



Рисунок 2.12 - Таблица ввода учебной и производственной практики студента.

Для перехода на личную карточку делаем активной вкладку 2:

{ TabSheet2->Show();}

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

Ниже расположена таблица DBGrid состоящая из столбцов Наименование предмета и 8 столбцов с оценками за 8 семестров. Установлена связь с таблицей оценка.

Для удобства работы пользователей добавление предмета производится из раскрывающегося списка представленного на рисунке ______.

Перед переходом на вкладку Оценки по студенту для таблицы Ocenka задала связь с таблицей Студенты используя свойства MasterSource (главная таблица) через поле Номер зачетки. Название предмета отображается через Lookup поле n_predmet:

ocenka->Active=false;

ocenkafio_stud->Visible=false;

ocenkafio_stud->FieldKind=fkCalculated;

ocenkan_predmet->FieldKind=fkLookup;

ocenkan_predmet->Visible=true;

ocenka->IndexName="Nom_zach";

ocenka->MasterFields="";

ocenka->MasterSource=dstudent;

ocenka->MasterFields="nom_zach";

ocenka->Active=true;

TabSheet3->Show();}


Для управления данными в таблице установила навигатор, прописав в событиях (Events) команду для OnClick:

{ if (Button==nbInsert)

ocenka->FieldValues["Nom_zach"]=student->FieldValues["Nom_zach"];}




Рисунок 2.13 - Ввод оценок по студенту

При вводе оценок по ведомости (по предмету) необходимо выбрать предмет и группу (поле преподаватель не отображается). Для этого была создана форма (Form2). В свойствах (Properties) установила:

BorderStyle = bsDialog;

Position = poScreenCenter.

На форме разместила кнопки ОК и Отмену используя компонент BitBtn. Для выбора группы и предмета размещен компонент DBLookupComboBox. Форма представлена рисунке 2.14.



Рисунок 2.14 - Форма выбора параметров.

При нажатии в меню на Справочники страница становится активной

{TabSheet5->Show();}

Содержит четыре таблицы со своими навигаторами для управления:

- предметы

- преподаватели

- группы

- специальности.

Для каждой таблицы установлены соответствующие связи в свойствах (Properties): dpredmet, dprepod, dgruppa, dspecial.



Рисунок 2.15 - Справочники открытые в программе C++ Builder.

Мой проект в C++ Builder состоит из шести форм. Форма — это всего лишь окно приложения на этапе разработки. Каждую форму описывают два файла — файл формы, описывающий свойства формы и размещенных на ней компонентов, и модуль, содержащий описание экземпляра класса формы и исходный код.

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

Для создания новой формы проекта выбрала команду New Form из меню File . Форма, на которой находится компонент, становится его владельцем.

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

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

В зависимости от настроек свойств, формы в проекте могут играть разные роли. Форма может быть главной формой проекта - Form1 (Студенты). Для этого форма в файле проекта создавалась первой. В этом случае она автоматически появляется при запуске приложения, а ее закрытие приводит к завершению работы всей программы.

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

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

Для формирования и распечатывания ведомостей, личной карточки студента, в Microsoft Word было создано 7 шаблонов [Приложение А].

Для каждого документа были введены соответствующие коды полей:

Наименование документа

Название поля

Код поля

Зачетная ведомость и

Экзаменационная ведомость

предмет

{DOCVARIABLE Predmet \* MERGEFORMAT}




курс

{DOCVARIABLE Nom_kurs \* MERGEFORMAT}




группа

{DOCVARIABLE Nom_gr \* MERGEFORMAT}




специальность

{DOCVARIABLE Spec \* MERGEFORMAT}




экзаменатор

{DOCVARIABLE Prepod \* MERGEFORMAT}










Сводная ведомость

курс

{DOCVARIABLE Nom_kurs \* MERGEFORMAT}




группа

{DOCVARIABLE Nom_gr \* MERGEFORMAT}




семестр

{DOCVARIABLE Sem \* MERGEFORMAT}




Учебный год

{DOCVARIABLE Uch_god \* MERGEFORMAT}










Ведомость учета часов учебной работы преподавателя

группа

{DOCVARIABLE Nom_gr \* MERGEFORMAT}




Месяц

{DOCVARIABLE Mes \* MERGEFORMAT}




Учебный год

{DOCVARIABLE Uch_god \* MERGEFORMAT}










Сводная ведомость учета часов учебной работы преподавателя

Фамилия преподавателя

{DOCVARIABLE Fio \* MERGEFORMAT}




наименование предмета

{DOCVARIABLE Predmet \* MERGEFORMAT}










Отчет по успеваемости группы

курс

{DOCVARIABLE Nom_kurs \* MERGEFORMAT}




группа

{DOCVARIABLE Nom_gr \* MERGEFORMAT}




семестр

{DOCVARIABLE Sem \* MERGEFORMAT}




Учебный год

{DOCVARIABLE Uch_god \* MERGEFORMAT}










Личная карточка


ФИО студента

{DOCVARIABLE Fio \* MERGEFORMAT}




Курс зачисления

{DOCVARIABLE Kurs_post \* MERGEFORMAT}




группа

{DOCVARIABLE Nom_gr \* MERGEFORMAT}




специальность

{DOCVARIABLE Spec \* MERGEFORMAT}




Дата поступления

{DOCVARIABLE Data_post \* MERGEFORMAT}




Пол

{DOCVARIABLE Pol \* MERGEFORMAT}




Число, месяц и год рождения

{DOCVARIABLE Data_rozd \* MERGEFORMAT}




Место рождения

{DOCVARIABLE Mest_rozd \* MERGEFORMAT}




Адрес родителей

{DOCVARIABLE Adr_pod \* MERGEFORMAT}




Национальность

{DOCVARIABLE nacional \* MERGEFORMAT}




Приказ о зачислении

{DOCVARIABLE Prik_zach \* MERGEFORMAT}




Приказ о переводе на 2 курс

{DOCVARIABLE Prik2 \* MERGEFORMAT}




Приказ о переводе на 3 курс

{DOCVARIABLE Prik3 \* MERGEFORMAT}




Приказ о переводе на 4 курс

{DOCVARIABLE Prik4 \* MERGEFORMAT}

Таблица 2.1 - Переменные шаблона Microsoft Word.

При нажатии на сводную ведомость появляется окно (Form3) представленная на рисунке 2.16.



Рисунок 2.16 - Форма для заполнения сводной ведомости.

Пользователю необходимо выбрать группу и семестр, программа формирует сводную ведомость, которая передается в Word:

if(Form3->ShowModal()!=mrOk) return;

Результат помещаю в переменную типа Variant, чтобы можно было впоследствии управлять этим документом.

Variant A_,B_,T_,D_,V_;

char gg[6],sp[3];

int kurs, sem, i,pre[20],kach[20],kol[20],kols=0;

for (i=0;i<20;i++) {pre[i]=0; kach[i]=0; kol[i]=0;}

String oo;

try{

A_ = CreateOleObject("Word.Application");

B_=A_.OlePropertyGet("WordBasic");

B_.OleProcedure("FileNew", (ExtractFilePath(ParamStr(0))+"Svod.dot").c_str());

D_=A_.OlePropertyGet("ActiveDocument");

V_=D_.OlePropertyGet("Variables");

strcpy(gg,Form3->DBLookupComboBox1->Text.c_str());

if (gg[1]=='-') {sp[0]=gg[0];sp[1]=0; kurs=gg[2]-48;}

else {sp[0]=gg[0];sp[1]=gg[1];sp[2]=0; kurs=gg[3]-48;}

sem=(kurs-1)*2+(Form3->RadioButton1->Checked?1:2);

V_.OleProcedure("Add", "Nom_kurs", kurs);

V_.OleProcedure("Add", "Nom_gr", (Form3->DBLookupComboBox1->Text) .c_str());

V_.OleProcedure("Add", "Sem", Form3->RadioButton1->Checked?1:2);

V_.OleProcedure("Add", "Uch_god", ((String)uch_god+"-"+(String)(uch_god+1)).c_str());

D_.OlePropertyGet("Fields").OleProcedure("Update");

B_.OleProcedure("AppShow");

//student->Filter="Spec='"+(String)sp+"' AND Nom_kurs="+(String)kurs+" AND Nom_gr="+(String)gr;

student->Filter="Gruppa='"+Form3->DBLookupComboBox1->Text+"'";

student->Filtered=true;

Label23->Caption=Form3->DBLookupComboBox1->Text;

ocenka->Active=false;

ocenkafio_stud->Visible=false;

ocenkafio_stud->FieldKind=fkCalculated;

ocenkan_predmet->FieldKind=fkLookup;

ocenkan_predmet->Visible=true;

ocenka->IndexName="Nom_zach";

ocenka->MasterFields="";

ocenka->MasterSource=dstudent;

ocenka->MasterFields="nom_zach";

ocenka->Active=true;

T_=D_.OlePropertyGet("Tables").OleFunction("Item",2);

student->First();

char sss[20];

int l=3;

while(!student->Eof)

Прописала команду для заполнения столбца ФИО из базы данных таблицы Student (Студенты).

{ T_.OleFunction("Cell",l,2).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",student->FieldByName("Fio")->AsString.c_str());

ocenka->First();

char oc[]="Oc0";

oc[2]=sem+48;

while(!ocenka->Eof)

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

{if (ocenka->FieldByName(oc)->IsNull) {ocenka->Next();continue;}

for (i=0;i<19;i++) if (pre[i]==0 || pre[i]==ocenka->FieldByName("predmet")->AsInteger) break;

if (i>=19) {ocenka->Next();continue;}

if (pre[i]==0)

{pre[i]=ocenka->FieldByName("predmet")->AsInteger;

T_.OleFunction("Cell",2,3+i).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",ocenka->FieldByName("n_predmet")->AsString.c_str()); }

oo=ocenka->FieldByName(oc)->AsString;

if (oo[1]=='5' || oo[1]=='4' || oo[1]=='з') kach[i]++;

if (oo[1]=='5' || oo[1]=='4' || oo[1]=='3' || oo[1]=='з') kol[i]++;

T_.OleFunction("Cell",l,3+i).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",oo.c_str());

ocenka->Next();}

l++;

kols++;

В одной группе не может быть больше 38 предметов, иначе программа не введет их в сводную таблицу.

if(l>38) break;

student->Next();}

for (i=0;i<19;i++)

{ if (pre[i]==0) break;

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

T_.OleFunction("Cell",38,3+i).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",kach[i]*100/kols);

T_.OleFunction("Cell",39,3+i).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",kol[i]*100/kols);}

B_.OleProcedure("AppShow");}

catch(EOleException& e){ShowMessage("OleException "+e.Message);}

catch(EOleSysError& e){ShowMessage("OleSyserror "+e.Message);}

catch(Exception& e){ShowMessage("Exception "+e.Message);}

student->Filtered=false;

Label23->Caption=" ";

TabSheet1->Show();}

Для зачетной ведомости аналогичным образом происходит передача данных из базы в документ Microsoft Word. При выборе в меню Зачетной ведомости открывается форма представленная на рисунке___, при выборе полей из раскрывающихся списков группа, предмет и преподаватель автоматически создается документ на основе шаблона zach. Происходит заполнение прописанных кодов-полей отписанных в таблице 2.1.



Рисунок 2.17 - Форма выбора данных для заполнения зачетной и экзаменационной ведомостей.

Задаем условие, если пользователь нажимает кнопку ОК, выполняется алгоритм:

{Form2->Label2->Visible=true;

Form2->DBLookupComboBox3->Visible=true;

if(Form2->ShowModal()!=mrOk) return;

Variant A_,B_,T_,D_,V_;

char gg[6],sp[3];

int kurs;

wchar_t www[100];

try{

A_ = CreateOleObject("Word.Application");

B_=A_.OlePropertyGet("WordBasic");

B_.OleProcedure("FileNew", (ExtractFilePath(ParamStr(0))+(Sender==N3?"Ekzam_ved.dot":"Zach.dot")).c_str());

D_=A_.OlePropertyGet("ActiveDocument");

V_=D_.OlePropertyGet("Variables");

V_.OleProcedure("Add", "Predmet", Form2->DBLookupComboBox2->Text.c_str());

strcpy(gg,Form2->DBLookupComboBox1->Text.c_str());

if (gg[1]=='-') {sp[0]=gg[0];sp[1]=0; kurs=gg[2]-48;}

else {sp[0]=gg[0];sp[1]=gg[1];sp[2]=0; kurs=gg[3]-48;}

V_.OleProcedure("Add", "Nom_kurs", kurs);

V_.OleProcedure("Add", "Nom_gr", (Form2->DBLookupComboBox1->Text) .c_str());

V_.OleProcedure("Add", "Spec", ((String)special->Lookup("Buk_spec",sp,"Naz_spec") +" ").c_str());

V_.OleProcedure("Add", "Prepod", (Form2->DBLookupComboBox3->Text +" ").c_str());

D_.OlePropertyGet("Fields").OleProcedure("Update");

B_.OleProcedure("AppShow");

Прописала фильтр по группе, которая была выбрана на форме (Form2)

student->Filter="Gruppa='"+Form2->DBLookupComboBox1->Text+"'";

Label23->Caption=Form2->DBLookupComboBox1->Text;

student->Filtered=true;

T_=D_.OlePropertyGet("Tables").OleFunction("Item",2);

student->First();

char sss[20];

int l=2,i;

while(!student->Eof)

Заполнение в таблице столбцов номер по порядку и фамилия, имя, отчество учащегося.

{ T_.OleFunction("Cell",l,1).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",itoa(l-1,sss,10));

T_.OleFunction("Cell",l,3).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",student->FieldByName("Fio")->AsString.c_str());

l++;

if(l>50) break;

student->Next();}

B_.OleProcedure("AppShow");}

Обработка возможной ошибки, которая может возникнуть при взаимодействии с MsWord.

catch(EOleException& e){ShowMessage("OleException "+e.Message);}

catch(EOleSysError& e){ShowMessage("OleSyserror "+e.Message);}

catch(Exception& e){ShowMessage("Exception "+e.Message);}

student->Filtered=false;

Label23->Caption=" ";

TabSheet1->Show();}

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

Набор данных Query связывается с компонентом UpdateSQL через свое свойство UpdateObject типа TDataSetUpdateObject, В качестве значения которого выбирается имя компонента UpdateSQL. Кроме того, для набора данных Query нужно установить значение true свойствам CachedUpdates и RequestLive.

Роль компонента UpdateSQL заключается в выполнении SQL-запросов, обновляющих необходимые записи связанного с ним набора данных Query

Этот компонент позволяет хранить и выполнять три разных запроса:

- update (редактирование записей);

- insert (вставка записей);

- delete (удаление записей).

Указанные запросы содержатся в свойствах ModifySQL, insertsql и DeleteSQL типа Tstrings соответственно. Таким образом, компонент UpdateSQL частично совмещает функциональность сразу трех компонентов Query.

Ввести тексты соответствующих запросов компонента UpdateSQL можно вручную аналогично тому, как это выполняется для свойства sql компонента Query. На этапе разработки приложения удобно использовать для этих целей Редактор свойств компонента UpdateSQL, окно которого показано на рисунке ____. Редактор свойств вызывается командой UpdateSQL Editor контекстного меню компонента или двойным щелчком на компоненте UpdateSQL.

В названии окна выводятся имена компонента UpdateSQL и соответствующего набора данных Query.

Редактор содержит две вкладки, первоначально выбрана вкладка параметров Options. В списке Table Name выбирается таблица, для записей которой включен механизм кэшированных изменений. Список содержит имена таблиц, указанных в запросе набора данных Query.

После выбора таблицы в списках ключевых (Key Fields) и обновляемых полей (Update Fields) отображается перечень ее столбцов. В первом списке нужно выделить столбцы, входящие в состав индекса и используемые при доступе к данным, а во втором — столбцы, значения которых будут обновляться.



Рисунок 2.18 - Редактирование свойств компонента UpdateSQL.

Запросы компонента UpdateSQL можно выполнить либо через вызов методов Компонента Database, либо через метод самого компонента UpdateSQL.

При подтверждении кэшированных изменений методом ApplyUpdates компонента Database для указанных наборов данных Query автоматически отрабатываются запросы соответствующего компонента updateSQL. Эти запросы и выполняют сохранение кэшированных изменений "своего" набора.

Набор данных Query связан с компонентами Database и UpdateSQL через свои свойства DatabaseName и UpdateObject соответственно.



Рисунок 2.19 - SQL-запросы компонента updateSQL.

Система C++ Builder автоматически учитывает все указанные в SQL- запросе параметры в специальном списке параметров, являющемся для набора данных Query значением свойства Params типа TParams, представляющим собой массив. Это свойство позволяет получить доступ к каждому параметру, как при разработке, так и при выполнении приложения. Чтобы обратиться к параметру во время выполнения приложения, следует указать его номер (индекс) в списке параметров или обратиться по имени параметра. На этапе разработки приложения можно вызвать Редактор параметров представленный на рисунке 2.20 в Инспекторе объектов. Тип каждого параметра целесообразно указать а свойстве DataType типа TFieldType.



Рисунок 2.20 - Окно Редактора параметров.

Компонент Query представляет собой набор данных, записи которого формируются в результате выполнения SQL-запроса и основаны на реляционном способе доступа к данным.

Набор данных Query, в отличие от компонента Table, может включать в себя записи более чем одной таблицы БД.

Текст запроса, на основании которого в набор данных отбираются записи, содержится в свойстве sql типа Tstrings. Запрос включает в себя команды на языке SQL и выполняется при открытии набора данных с помощью вызова его методов ExecSQL или Open. Запрос SQL иногда называют SQL- программой.

При формировании запроса на этапе разработки приложения я использовала текстовый редактор представленный на рисунке 2.21, вызываемый через Инспектор объектов двойным щелчком в области значения свойства sql.



Рисунок 2.21 - Редактирование запроса SQL

При выборе в пункте меню ввод часов преподавателей, открывается форма (Form4) представленная на рисунке 2.22.



Рисунок 2.22 - Выбор параметров для ввода часов преподавателей.

Из раскрывающихся списков (LookupComboBox) можно выбрать предмет, преподавателя и группу.

Год и месяц установлены компонентом CSpinEdit из вкладки Samples на панели инструментов C++ Builder - контейнеров для ввода значений атрибутов, а также поставьте каждому из них в соответствие объект Label (метка или комментарий, компонент проживает во вкладке Standard).

Далее измените название формы с Form4 (поле Caption окна инспектора свойств) на заголовок вида: «Учет часов». Наконец, поместите на рабочую область программы кнопка типа BitBtn из группы Additional и задайте в свойствах:

- для кнопки ОК Kind->bkOk;

- для отмены: Kind->bkCancel;

Перейдите в окно редактирования исходного кода и встройте после директивы:
#include "uchebka.h"следующую команду:
#include "Unit4.h"
Этим действием мы подключим четвертую форму к нашей основной программе или, проще говоря, активируем рабочую область четвертой формы. Теперь назначим действие ведущее к открытию вкладки часы для редактирования (изменение, удаление, добавление часов). Поместите следующий код:

{Form4->CSpinEdit1->Value=year(Date());

Form4->CSpinEdit2->Value=month(Date());

Form4->Label26->Visible=true;

Form4->Label1->Visible=true;

Form4->DBLookupComboBox3->Visible=true;

Form4->CSpinEdit2->Visible=true;

if(Form4->ShowModal()!=mrOk) return;

TLocateOptions Opts;

Opts.Clear();

Variant locvalues[5];

locvalues[0] = Variant(gruppa->FieldValues["gruppa"]);

locvalues[1] = Variant(predmet->FieldValues["Kod_pred"]);

locvalues[2] = Variant(prepod->FieldValues["Kod"]);

locvalues[3] = Variant(Form4->CSpinEdit1->Value);

locvalues[4] = Variant(Form4->CSpinEdit2->Value);

if (!chasi-Locate("Nom_gr;Predmet;Prepod;God;Mes",VarArrayOf(locvalues, 4), Opts))

{chasi->Append();

chasi->FieldValues["Nom_gr"] = gruppa->FieldValues["gruppa"];

chasi->FieldValues["Predmet"] = predmet->FieldValues["Kod_pred"];

chasi->FieldValues["Prepod"] = prepod->FieldValues["Kod"];

chasi->FieldValues["God"] = Form4->CSpinEdit1->Value;

chasi->FieldValues["Mes"] = Form4->CSpinEdit2->Value;

chasi->Post();}

TabSheet6->Show();}
В верхней части открывшейся вкладки отображаются: предмет, преподаватель, группа, год, месяц, которые можно просмотреть но не изменить.

Поля DBEdit от 1 до 31 предназначенные для ввода часов по числам месяца. На кнопку ОК происходит сохранение введенных данных.



Рисунок 2.23 - Вкладка ввода часов учебной работы преподавателя.

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

Загружается Microsoft Word и соответствующие данные заполняют шаблон таблицы:

if(Form5->ShowModal()!=mrOk) return;

Variant A_,B_,T_,D_,V_;

int i,c0,cs;

try{ A_ = CreateOleObject("Word.Application");

B_=A_.OlePropertyGet("WordBasic");

B_.OleProcedure("FileNew", (ExtractFilePath(ParamStr(0))+"prep_chac.dot").c_str());

D_=A_.OlePropertyGet("ActiveDocument");

V_=D_.OlePropertyGet("Variables");

V_.OleProcedure("Add", "Nom_gr", (Form5->DBLookupComboBox3->Text) .c_str());

V_.OleProcedure("Add", "Mes", Form5->CSpinEdit2->Value);

V_.OleProcedure("Add", "God", Form5->CSpinEdit1->Value);

D_.OlePropertyGet("Fields").OleProcedure("Update");

B_.OleProcedure("AppShow");

chasi->Filter="Nom_gr='"+Form5->DBLookupComboBox3->Text+"' AND Mes="+(String)Form5->CSpinEdit2->Value+" AND God="+(String)Form5->CSpinEdit1->Value;

chasi->Filtered=true;

T_=D_.OlePropertyGet("Tables").OleFunction("Item",1);

chasi->First();

char sss[20];

int l=4;

while(!chasi->Eof)

{ T_.OleFunction("Cell",l,1).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",((String)predmet->Lookup("Kod_pred", chasi->FieldByName("predmet")->AsInteger, "Naim_pred")).c_str());

T_.OleFunction("Cell",l,2).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",((String)prepod->Lookup("Kod", chasi->FieldByName("prepod")->AsInteger, "Fio")).c_str());

char cc[]="c00";

cs=0;

for (i=1;i<=31;i++)

{ itoa(i,cc+1,10);

c0=chasi->FieldByName(cc)->AsInteger;

T_.OleFunction("Cell",l,2+i).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",c0);

cs+=c0;}

T_.OleFunction("Cell",l,34).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",cs);

l++;

if(l>30) break;

chasi->Next();}

chasi->Filtered=false;

B_.OleProcedure("AppShow");}

catch(EOleException& e){ShowMessage("OleException "+e.Message);}

catch(EOleSysError& e){ShowMessage("OleSyserror "+e.Message);}

catch(Exception& e){ShowMessage("Exception "+e.Message);}

chasi->Filtered=false;}

За год формируется отчет по часам, который передается в Microsoft Word.

{ Form4->Label26->Visible=false;

Form4->Label1->Visible=false;

Form4->DBLookupComboBox3->Visible=false;

Form4->CSpinEdit2->Visible=false;

if(Form4->ShowModal()!=mrOk) return;

Variant A_,B_,T_,D_,V_;

int cs;

char sss[20];

int l=1,i,mes;

int cha[13]; //сумма по строкам

int chag=0; // по столбам

try{

A_ = CreateOleObject("Word.Application");

B_=A_.OlePropertyGet("WordBasic");

B_.OleProcedure("FileNew", (ExtractFilePath(ParamStr(0))+"prep-sv.dot").c_str());

D_=A_.OlePropertyGet("ActiveDocument");

V_=D_.OlePropertyGet("Variables");

V_.OleProcedure("Add", "Fio", (prepod->FieldByName("Fio")->AsString).c_str());

V_.OleProcedure("Add", "Predmet", predmet->FieldByName("Naim_pred")->AsString.c_str());

V_.OleProcedure("Add", "Uch_god", ((String)Form4->CSpinEdit1->Value+"-"+(String)(Form4->CSpinEdit1->Value+1)).c_str()); D_.OlePropertyGet("Fields").OleProcedure("Update");

B_.OleProcedure("AppShow");

chasi->Filter="Prepod='"+prepod->FieldByName("Kod")->AsString+"' AND Predmet="+predmet->FieldByName("Kod_pred")->AsString+" AND (God="+(String)Form4->CSpinEdit1->Value+" AND Mes>8 OR God="+(String)(Form4->CSpinEdit1->Value+1)+" AND Mes<8 )";

chasi->Filtered=true;

T_=D_.OlePropertyGet("Tables").OleFunction("Item",1);

chasi->First();

for (i=1;i<13;i++) cha[i]=0;

grupf="";

while(!chasi->Eof)

{ if (grupf!=chasi->FieldByName("Nom_gr")->AsString)

{ if (chag){

T_.OleFunction("Cell",17,l).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",chag);

chag=0; }

l++;

if(l>13) break;

grupf=chasi->FieldByName("Nom_gr")->AsString;

T_.OleFunction("Cell",2,l).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",grupf.c_str()); }

mes=chasi->FieldByName("Mes")->AsInteger;

char cc[]="c00";

cs=0;

for (i=1;i<=31;i++)

{ itoa(i,cc+1,10);

cs+=chasi->FieldByName(cc)->AsInteger;}

cha[mes]+=cs;

chag+=cs;

T_.OleFunction("Cell",(mes>8? (mes-9):(mes+3))+4,l).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",cs);

chasi->Next();}

chasi->Filtered=false;

if (chag){

T_.OleFunction("Cell",17,l).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",chag); }

for (mes=1;mes<13;mes++)

{ T_.OleFunction("Cell",(mes>8? (mes-9):(mes+3))+4,14).OleProcedure("Select");

A_.OlePropertyGet("Selection").OlePropertySet("Text",cha[mes]);}

B_.OleProcedure("AppShow");}

catch(EOleException& e){ShowMessage("OleException "+e.Message);}

catch(EOleSysError& e){ShowMessage("OleSyserror "+e.Message);}

catch(Exception& e){ShowMessage("Exception "+e.Message);}

chasi->Filtered=false;}

Последним пунктом меню является переход на следующий учебный год, при нажатии на него открывается форма предупреждающая об удалении выпускных групп и переводе остальных студентов на следующий курс, поле № и дата приказа (Edit) необходимо заполнить, затем нажать ОК. Перед переводом создастся архив базы данных, содержащий последние данные до перевода на следующий учебный год.



Рисунок 2.24 - Форма перехода студентов на следующий учебный год.

char gg[6],sp[3];

hDBIDb hDb;

String kurator;

char dir[DBIMAXPATHLEN + 1];

if(Form7->ShowModal()!=mrOk) return;

hDb=nastr->DBHandle;

DbiGetDirectory(hDb,0,dir);

nastr->Active=false;

special->Active=false;

student->Active=false;

praktika->Active=false;

ocenka->Active=false;

predmet->Active=false;

gruppa->Active=false;

prepod->Active=false;

chasi->Active=false;

String ss=(String)dir+"arh.exe a -x*.rar -x*.exe A"+(String)uch_god+" *.*";

PROCESS_INFORMATION pin;

STARTUPINFO si;

memset(&si, 0, sizeof(STARTUPINFO));

si.cb = sizeof(STARTUPINFO);

si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;

si.wShowWindow = SW_HIDE;

si.hStdOutput = 0;

si.hStdError = 0;

if (!CreateProcess(0,ss.c_str(),0,0,1,0,0,dir,&si,&pin)){MessageBox(Form1->Handle,"Ошибка архивирования продолжение невозможно","Ошибка",MB_OK|MB_ICONERROR);return;}else{

CloseHandle(pin.hThread);

WaitForSingleObject(pin.hProcess, 200000); }

nastr->Active=true;

special->Active=true;

student->Active=true;

praktika->Active=true;

ocenka->Active=true;

predmet->Active=true;

gruppa->Active=true;

prepod->Active=true;

chasi->Active=true;

ocenka->IndexName="Nom_zach";

ocenka->MasterFields="";

ocenka->MasterSource=dstudent;

ocenka->MasterFields="nom_zach";

Label23->Caption="";

student->Filtered=false;

student->First();

while(!student->Eof){

if(special->Lookup("Buk_spec",student->FieldByName("Spec")->AsString,"Let")==student->FieldByName("Nom_kurs")->AsInteger)

{ if (student->RecNo==student->RecordCount) {student->Delete();break;}

student->Delete();

} else {

strcpy(gg,student->FieldByName("Gruppa")->AsString.c_str());

if (gg[1]=='-') {gg[2]++;}

else if (gg[2]=='-') {gg[3]++;}

student->Edit();

switch(student->FieldByName("Nom_kurs")->AsInteger){

case 1: student->FieldByName("Prik2")->AsString=Form7->Edit1->Text; break;

case 2: student->FieldByName("Prik3")->AsString=Form7->Edit1->Text; break;

case 3: student->FieldByName("Prik4")->AsString=Form7->Edit1->Text; break; }

student->FieldByName("Gruppa")->AsString=gg;

student->Post();

student->Next(); }}

int kk;

gruppa->Last();

while(!gruppa->Bof){

strcpy(gg,gruppa->FieldByName("Gruppa")->AsString.c_str());

if (gg[1]=='-') {sp[0]=gg[0];sp[1]=0;gg[2]++;kk=gg[2]-48;}

else if (gg[2]=='-') {sp[0]=gg[0];sp[1]=gg[1];sp[2]=0;gg[3]++;kk=gg[3]-48;}

if(special->Lookup("Buk_spec",sp,"Let")
gruppa->Delete();

gruppa->Prior();

}else {

gruppa->Edit();

gruppa->FieldByName("Gruppa")->AsString=gg;

gruppa->Post();

gruppa->Prior(); }}

nastr->Edit();

nastr->FieldByName("Uch_god")->AsInteger=++uch_god;

nastr->Post();

Form1->Caption="Учебная часть РПТ "+(String)uch_god+"-"+(String)(uch_god+1)+" учебный год"; }

Ежедневно выполняется проверка и переиндексация баз, по средам архивация. Для архивации вызывается внешний архиватор с параметрами для архивации всех файлов кроме exe и .rar в папке, имя файла соответствует дате архивации:

{char *bas[]={"chasi.db","gruppa.db","ocenka.db","praktika.db","predmet.db","prepod.db","special.db","student.db","propusk.db"};

WORD err;

char bbb[100];

hDBIDb hDb;

hDb=nastr->DBHandle;

char dir[DBIMAXPATHLEN + 1];

DbiGetDirectory(hDb,0,dir);

if (nastr->FieldByName("Datar")->AsDateTime!=Date()) {

if (Date().DayOfWeek()==4){

nastr->Close();

String ss=(String)dir+"arh.exe a -x*.rar -x*.exe "+Date().FormatString("yyyymmdd")+" *.*";

PROCESS_INFORMATION pin;

STARTUPINFO si;

memset(&si, 0, sizeof(STARTUPINFO));

si.cb = sizeof(STARTUPINFO);

si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;

si.wShowWindow = SW_HIDE;

si.hStdOutput = 0;

si.hStdError = 0;

if (!CreateProcess(0,ss.c_str(),0,0,1,0,0,dir,&si,&pin)){MessageBox(Form1->Handle,"Ошибка архивирования","Ошибка",MB_OK|MB_ICONERROR);}else{

CloseHandle(pin.hThread);

WaitForSingleObject(pin.hProcess, 200000); } }

nastr->Close();

nastr->Exclusive=true;

try{

nastr->Open();

}catch(EDatabaseError &E)

{ nastr->Exclusive=false;

nastr->Open();

return; }

for (int i=0;i<9;i++)

{ //err=DbiRegenIndexes(Table1->Handle);

CRTblDesc TblDesc;

memset((void *) &TblDesc, 0, sizeof(CRTblDesc));

lstrcpy(TblDesc.szTblName, bas[i]);

lstrcpy(TblDesc.szTblType, szPARADOX);

TblDesc.bPack = TRUE;

err=DbiDoRestructure(hDb,1,&TblDesc,0,0,0,0);

if (err!=DBIERR_NONE)

{ sprintf(bbb,"Ошибка переиндексации %x",err);

MessageBox(0,bbb,bas[i],MB_OK); } }

nastr->Close();

nastr->Exclusive=false;

nastr->Open();

nastr->Edit();

nastr->FieldValues["Datar"]=Date();

nastr->Post(); }}