Главная » C++, C++ Builder » Пример программы просмотра полей базы данных в CBuilder

0

 

Для того чтобы создать программу просмотра полей базы данных, вы должны кое-что узнать о внутреннем устройстве баз данных. Для этого вам понадобится база данных, с которой вы могли бы работать. В нашем примере мы предоставим пользователю возможность выбрать базу данных с диска. В данном случае мы наложим ограничение на тип базы данных — это будет dBase, так что вам не придется волноваться по поводу установленных драйверов ODBC, но все будет работать точно так же и для любого другого типа баз данных из числа поддерживаемых CBuilder.

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

Внутри объекта TTable содержится указатель на объект TFieldDefs. В этом объекте содержится массив объектов описания полей типа TFieldDef (один объект TFieldDefs содержит множество объектов TFieldDef). Этот объект содержит свойства, которые представляют информацию о каждом поле. Среди прочего, внутри этого объекта вы найдете имя, тип и размер поля. Имея всю эту информацию, мы можем приступить к созданию программы просмотра, используя форму, показанную на рис. 7.1.

Создаем пример программы просмотра полей

Создайте форму, показанную на рис. 7.1, добавив в пустую форму объекты TStringGrid, TMainMenu, TOpenDialog и TTable. В этом примере мы не будем напрямую устанавливать свойства объектов grid, dialog или table. Объект main menu должен содержать пункт Файл с подпунктами Открыть и Выход. Пункт меню Открыть будет использоваться для выбора таблицы базы данных для просмотра, а пункт Выход — для того, чтобы закрыть приложение.

Рис. 7.1. Форма программы просмотра полей базы данных

Первым шагом для отображения информации будет создание таблицы типов полей. Типы полей хранятся в базе данных как числовые значения типа TFldType. Нам бы хотелось иметь возможность отображать эти данные в более информатив ном виде, чтобы пользователь мог в них разобраться. Для осуществления подобного преобразования добавьте следующий код в начало исходного файла Unit1.h:

typedef struct

{

int nCode; char *strDesc;

} DbFieldType;

DbFieldType sFieldTypes[] =

{

{ftUnknown, "Неизвестно или не определено"},

{ftString, "Символьное или строковое поле"},

{ftSmallint, "16-битное целое поле"},

{ftInteger, "32-битное целое поле"},

{ftWord, "16-битное беззнаковое целое поле"},

{ftBoolean, "Логическое поле"},

{ftFloat, "Поле чисел с плавающей точкой"},

{ftCurrency, "Денежное поле"},

{ftBCD, "Двоично-кодированное десятичное поле"},

{ftDate, "Поле даты"},

продолжение И

Глава 7•Работа с базами данных

{ftTime, "Поле времени"},

{ftDateTime, "Поле даты и времени"},

{ftBytes, "Фиксированное количество байт (двоичное представление)"},

{ftVarBytes, "Переменное количество байт (двоичное представление"},

{ftAutoInc, "Автоматически увеличивающееся 32-битное целое поле счетчика"},

{ftBlob, "Поле Binary Large Object (большой двоичный объект)"},

{ftMemo, "Поле memo (строка неограниченной длины)"},

{ftGraphic, "Поле растрового рисунка"},

{ftFmtMemo, "Поле форматированного memo"},

{ftParadoxOle, "Поле Paradox OLE"},

{ftDBaseOle, "Поле dBase OLE"},

{ftTypedBinary, "Типизированное двоичное поле"},

{-1,""}

};

Эта таблица будет просто ставить в соответствие типы данных (символы ftxxx) и строки, которые характеризуют тип поля. Строки будут отображаться в сетке напротив каждого поля как тип этого поля.

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

char *TForm1::GetFieldTypeDescription(int nInd)

{

for (int i=0; sFieldTypes[i].nCode != -1; ++i) if (sFieldTypes[i].nCode == nInd)

return sFieldTypes[i].strDesc;

return "";

}

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

void __fastcall TForm1::Open1Click(TObject *Sender)

{

OpenDialog1->Filter = "Файлы баз данных dBase|*.dbf"; if (OpenDialog1->Execute())

{

// Пытаемся открыть выбранную базу данных Разбираемся во внутреннем устройстве базданных Table1->DatabaseName = ExtractFilePath(OpenDialog1->FileName);

// Определяем имя таблицы

Table1->TableName = ExtractFileName(OpenDialog1->FileName);

// Делаем таблицу активной

Table1->Active = true;

// Загружаем сетку с частями таблицы StringGrid1->RowCount = Table1->FieldCount; StringGrid1->ColCount = 4;

// Устанавливаем ширину столбцов StringGrid1->ColWidth[0] = 30; StringGrid1->ColWidth[1] = StringGrid1->ClientWidth/3 – 10; StringGrid1->ColWidth[2] = StringGrid1->ClientWidth/3 – 10; StringGrid1->ColWidth[3] = StringGrid1->ClientWidth/3 – 10;

// Устанавливаем заголовки StringGrid1->Cells[0][0] = "№ поля"; StringGrid1->Cells[0][0] = "Имя поля"; StringGrid1->Cells[0][0] = "Тип поля"; StringGrid1->Cells[0][0] = "Размер"; for (int i=1; i<Table1->FieldCount; ++i)

{

StringGrid1->Cells[0][i] = AnsiString(i); StringGrid1->Cells[1][i] =

Table1->FieldDefs->Items[i]->Name; StringGrid1->Cells[2][i] = GetFieldTypeDescription(Table1-> FieldDefs->Items[i]->DataType); StringGrid1->Cells[3][i] = AnsiString(Table1->FieldDefs->

Items[i]->Size);

}

}

}

Что же здесь происходит?

Некоторые строки приведенного выше кода — как, например, касающиеся инициализации сетки или задания ширины колонок — не представляют собой ничего слож

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

Две вспомогательные функции, определенные в заголовочном файле sysutils.hpp  каталога include\vcl, используются для присвоения имени базы данных и имени таблицы. Имя базы данных для файла dBase — это просто каталог, в котором этот файл находится. Аналогично, имя таблицы

— всего лишь имя файла, который вы собираетесь открыть.

Объект TOpenDialog возвращает полный путь к выбранному пользователем файлу в свойстве FileName. Мы знаем, что выбран файл корректного типа, ведь мы установили свойство Filter так, чтобы допустить только файлы dBase (DBF). Поэтому мы можем использовать вспомогательную функцию ExtractFilePath для того, чтобы получить только имя каталога, и вспомогательную функцию ExtractFileName для получения имени файла с выбранной таблицей. После того как обе

функции были использованы, мы «открываем» базу данных, устанавливая свойство Active1  в true.

Замечание

Хотя это и не показано в примере, вышеприведенный код мог привести к возникновению исключительной ситуации. Если вы хотите сами обработать эту исключительную ситуацию, переустанавливайте свойство Active внутри блока try … catch. Можете делать что хотите внутри блока catch, чтобы дать понять пользователю, что возникла ошибка, и прервать  исполнение метода. Если же вы ничего не сделаете, CBuilder автоматически обработает исключительную ситуацию и остановит работу программы.

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

В  случае  файла  dBase  это  то  же  самое,  что   и   общее   количество   полей   в   таблице. После того как сетка инициирована, ширина и заголовки установлены, одно за другим опрашиваются поля и данные по каждому загружаются в ячейки клетки. Если вам не доводилось использовать класс TStringGrid ранее, не утруждайте себя обращением к справочной системе. На Web-сайте фирмы Borland находится обновленный файл помощи, который содержит информацию о сетке и нескольких других классах, случайно обойденных вниманием как в справочной системе, так и в бумажной документации. В данном примере мы используем свойство TStringGrid, называемое Cells (ячейки) для установки индивидуальных атрибутов строк и столбцов сетки. Если последнее утверждение показалось вам забавным, не волнуйтесь — не вам одному; свойство Cells работает в формате столбец, строка.

Так же как это реализовано во многих других элементах системы, в объекте FieldDefs отдельные поля хранятся в свойстве Items (части, пункты). В свойстве Items вы найдете информацию об имени поля (свойство Name), типе поля (свойство DataField, которое мы преобразуем в строку при помощи метода utility) и размере поля (свойство Size).

1 Если вам на глаза попадется английский оригинал этой книги, будьте осторожны — в ней почему-то вместо свойства Active упоминается несуществующее у TTable свойство Enable. — Примеч. перев.

Замечание

Для всех полей, кроме строковых (или массивов символов), свойство Size будет равно 0. Все остальные поля имеют неявный размер, основывающийся на их реальном воплощении. Например, 16-битное числовое поле будет представлено 2-байтным целым, а 32-битное числовое поле будет представлено 4-байтным целым (или long). dBase уже знает обо всех этих полях, так что только символьные строковые поля должны быть определены при помощи свойства Size.

Последняя вещь в нашем коде, на которую стоит обратить внимание, —  это  преобразование номера поля в строку при помощи класса AnsiString. Хотя мы и рассмотрели класс string в STL, мы так толком и не поговорили об AnsiString. Этот класс поддерживает большинство методов класса string и используется в ситуации, когда требуется строка типа принятой в языке Pascal. Все методы VCL, работающие со строками, допускают AnsiString в качестве типа аргумента.

Последним шагом для завершения нашей программы будет осуществление ее закрытия при выборе команды меню Файл|Закрыть . Добавьте новый обработчик для команды меню Выход, в соответствующий метод Exit1Click добавьте следующие строки:

void __fastcall TForm1::Exit1Click(TObject *Sender)

{

Application->Terminate();

}

На этом программа просмотра баз данных успешно завершена. Скомпилируй те и запустите программу и выберите базу данных для просмотра. Хорошие примеры можно найти в подкаталоге CBuilder\Examples\Data основного каталога CBuilder. На рис. 7.2 показано окно  программы просмотра с отображенным в нем файлом Clients.dbf.

Рис. 7.2. Выбранная пользователем база данных в окне программы просмотра

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

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

TTable.

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

Источник: Теллес М. – Borland C++ Builder. Библиотека программиста – 1998

По теме:

  • Комментарии