Узагальнена програма перегляду баз даних в CBuilder

Однією з найбільш чудових особливостей системи підтримки баз даних в CBuilder є можливість використовувати один і той же код для доступу до різних наборів даних Чутливі до даних компоненти (Data-aware controls), що поставляються з CBuilder, виконують вражаючу роботу з обробки, відображенню й обробці змін великого спектру даних, що зберігаються в будь-яких типах, підтримуваних CBuilder базах даних (а підтримується більшість з існуючих типів)

У цьому прикладі ми створимо універсальну програму перегляду баз даних Ця програма

дозволить вам переглядати будь-яку базу даних, просто відкривши її за допомогою стандартного діалогу відкриття файлів Крім того, ми передбачимо в нашій програмі можливість відфільтровувати дані за критерієм, задаваемому користувачем під час виконання Звичайно, Database Desktop (робочий стіл баз даних), що поставляється з CBuilder, виконує всі перерахований функції Телефон, але іноді вам може знадобитися просто кинути поверхневий погляд на яку-небудь базу даних, не втрачаючи часу на завантаження Database Desktop Крім того, після запуску CBuilder обмеження на розмір використовуваної памяті стають досить жорсткими Наша програма перегляду баз даних є демонстрацією мощі чутливих до даних компонентів

На рис 76 показана форма, використовувана в цьому прикладі З точки зору ставлення кількості використовуваних керуючихкомпонентів до написаного коду, цей приклад не найбільший, але він повною мірою показує міць лежать в його основі керуючих елементів баз даних VCL

У цьому прикладі ми дозволимо користувачеві вибирати для відкриття нову базу даних після натискання кнопки Відкрити Для відкриття бази даних ми скористаємося ся кодом, аналогічним коду попередніх прикладів Ось як виглядає код, який слід додати для події OnClick (При натисканні) для кнопки Відкрити вашої форми:

void __fastcall TForm1::OpenClick(TObject *Sender)

{

if (OpenDialog-&gtExecute())

{

if (Table-&gtActive == true) Table-&gtActive = false Table-&gtDatabaseName =

ExtractFilePath(OpenDialog-&gtFileName) Table-&gtTableName = ExtractFileName(OpenDialog-&gtFileName) Table-&gtActive = true

RecordCount-&gtCaption = AnsiString((int)Table1-&gtRecordCount)

}

}

Рис 76 Форма перегляду баз даних

У даному коді ми спочатку перевіряємо, чи не відкрита чи вже база даних, оскільки користувач може спочатку відкрити одну базу, а потім вирішити відкрити ще одну Щоб не дратувати CBuilder спробами змінити імя бази даних і імя таблиці у вже відкритої бази, ми закриваємо її, встановлюючи властивість Active в false Код для визначення імені бази даних і імені таблиці абсолютно схожий з тим, що ми використовували раніше Ми встановлюємо властивість Active в true для відкриття обраної бази даних і потім відображаємо кількість записів у ній, отримуючи значення властивості RecordCount таблиці

Не всі бази даних підтримують властивість RecordCount У деяких випадках вам треба спочатку пройтися по всіх записах, щоб властивість RecordCount прийняло коректне значення І все ж більшість баз даних для IBM PC повернуть вам правильне значення в даному випадку

Наведений вище код не чинить практично нічого, окрім як відкриття бази даних Чому ж, запустивши цю ж програму з компакт-диска, ви побачите, що сітка даних, розташована на формі, автоматично завантажить в себе і відобразить всі записи з обраної бази Справа в тому, що ви упустили один крок (точніше, я не сказав вам про нього, що одне і те ж) Розташований ний на формі обєкт DBGrid має властивість DataSource, Яке представляє обєкт-джерело даних, що знаходиться на формі, з якого DBGrid і отримає дані Точно так само в обєкта DataSource є властивість DataSet, Що представляє таблицю бази даних (або запит), з якої він отримає дані Встановіть властивість DataSet вашого обєкта DataSource в Table1 Встановіть його ж властивість Enabled в true, щоб дозволити йому завантажувати дані Потім встановіть властивість DataSource обєкта DBGrid в DataSource1, Що є імям обєкта DataSource, Розташованого на формі Цим ви завершите ланцюжок між базою даних і сіткою даних

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

Для того щоб відфільтрувати дані, користувач повинен ввести вираз у поле редагування, яке представляє критерій фільтрування Критерій для фільтра має вигляд

«Поле вираз значення» Поле – це імя одного з полів, відображених у сітці даних Вираз – це оператор порівняння, такий як =, <> (Не дорівнює), <,>,> =, <= або like (подібно). І нарешті, значення - це те значення, з яким ви проводите порівняння. Якщо ви працюєте з адресною книгою з одного з попередніх прикладів і хочете побачити дані про тих, хто не живе в Нью-Йорку (цікаво, а чи багато ваших друзів там живе), вам треба ввести наступний рядок:

State &lt&gt &quotNY&quot

Тут використовується поле State бази даних, оператор <> (Не дорівнює) і рядок NY Відзначте, що оскільки рядок в результаті буде укладена в подвійні лапки, то якщо ви використовуєте рядок (в даному випадку NY), То повинні укласти її в одинарні лапки

Ось повний код для кнопки застосування фільтра, який треба додати в обробник події для неї OnClick:

void __fastcall TForm1::Button1Click(TObject *Sender)

{

if (Table1-&gtActive == true)

{

Table1-&gtFiltered = true Table1-&gtFilter = Edit1-&gtText RecordCount-&gtCaption =

AnsiString((int)Table1-&gtRecordCount)

}

}

Цей код просто встановлює фільтр в таблиці установкою прапора Filtered в true повідомляє таблиці, що треба скористатися властивістю Filter Це змусить таблицю відфільтрувати всі записи, у яких відповідні поля не задовольняють заданому значенню Крім того, ми заново перевизначають кількість записів, яке зазначено у нас на формі Дуже приємною річчю є те, що при фільтруванні автоматично перераховується кількість записів, – вважаються лише ті, які задовольняють критерію фільтра

На цьому написання універсальної програми перегляду баз даних закінчено трохи більше десятка рядків коду, парочка покладених на форму компонентів-і готово Цей приклад, як жоден інший в цьому розділі, демонструє дійсну потужність компонентів VCL CBuilder, що працюють з базами даних

Можливість перегляду вмісту таблиці – це, звичайно, здорово, але дуже мало реальні програми працюють з одним файлом бази даних Більш ймовірно, що дані для програми зберігаються в кількох таблицях бази даних і якось обєднуються за змістом Одна таблиця вашої бази даних може містити інформацію про покупців, інша – про продажі, а третя – про помилки, допущені корпорацією при відвантаженні товарів Швидше за все, таблиці обєднуються за якогось спільного полю У нашому новому прикладі ми розглянемо використання декількох таблиць, для наочності зробивши це у вигляді перегляду їх в одній формі

На рис 77 показана форма для відображення декількох таблиць Користувач зможе вибрати дві таблиці, а потім вибрати поле, по якому слід переглянути взаємовідношення двох таблиць Після того як він вибере по одному полю в кожній відкритій таблиці, ми спробуємо повязати ці два поля

Написання програми можна розбити на три основних етапи По-перше, ми повинні дозволити користувачеві відкрити довільний файл бази даних Ми вже кілька разів здійснювали це, так що даний етап НЕ представляє для нас складності Другий етап – це завантаження списків з іменами полів для кожної бази даних Знову ж, це не складно, оскільки це всього лише різновид програми перегляду полів бази даних, яку ми написали трохи раніше в цій главі Останнім етапом стане відображення в сітці даних записів, які містять всю інформацію з обох таблиць А це вже трохи складніше Давайте рухатися від простого до складного

Для того щоб дозволити користувачеві відкрити перший файл бази даних, додайте наступний код для обробника події OnClick кнопки ВиборТабліци1:

void __fastcall TForm1::Button1Click(TObject *Sender)

{

OpenDialog1-> Filter = Файли dBase | * Dbf; if (OpenDialog1-> Execute ())

{

/ / Намагаємося відкрити обрану базу даних

Table1-&gtDatabaseName =

ExtractFilePath(OpenDialog1-&gtFileName)

/ / Встановлюємо імя таблиці

Table1-&gtTableName = ExtractFileName(OpenDialog1-&gtFileName)

/ / Робимо її активної

Table1-&gtActive = true

for (int i=0 i&ltTable1-&gtFieldCount ++i)

{

ListBox1-&gtItems-&gt

Add(Table1-&gtFieldDefs-&gtItems[i]-&gtName)

}

}

}

Рис 77 Форма перегляду кількох таблиць

Цей код не тільки відкриває обрану користувачем таблицю, а й виконує ще одну задачу – завантажує імена полів у список Код для обробника

натискання на кнопку ВиборТабліци2 виглядає практично так само Ось його конкретний вигляд: void __ fastcall TForm1 :: Button2Click (TObject * Sender)

{

OpenDialog1-> Filter = Файли dBase | * Dbf; if (OpenDialog1-> Execute ())

{

/ / Намагаємося відкрити обрану базу даних Table2-> DatabaseName = ExtractFilePath (OpenDialog1-> FileName)

/ / Встановлюємо імя таблиці

Table2-&gtTableName = ExtractFileName(OpenDialog1-&gtFileName)

/ / Робимо її активної

Table2-&gtActive = true

for (int i=0 i&ltTable2-&gtFieldCount ++i)

{

ListBox1-&gtItems-&gt

Add(Table2-&gtFieldDefs-&gtItems[i]-&gtName)

}

}

}

Дам вам невеликий рада: якщо ви, як і я, працюєте з невеликим разрешени ем екрану, то вам, напевно, незручно перемикатися між великими формами типу цієї і вікном редактора коду Ви можете зробити це прямо в середовищі розробки: натиснувши кнопку F12, перебуваючи в редакторі форм, ви перейдіть у вікно редактора коду

Отже, ми розібралися з першими двома етапами Третій етап починається після того, як користувач щось вибрав з кожної таблиці Для втілення додайте по оброблювачу для події OnClick кожного списку Наступний код додайте в обидва обробника (тут показаний тільки один, але вони однакові) або до загального обробник для обох списків:

void __fastcall TForm1::ListBox1Click(TObject *Sender)

{

if (ListBox1-&gtItemIndex = -1 &amp&amp ListBox2-&gtItemIndex = -1) DoSQLProcess()

}

Тепер все, що нам залишилося зробити, – це визначити метод DoSQLProcess Цей метод створює динамічний запит SQL (Structural Query Language, структур рованний мова запитів) і повязує його з обєктом TQuery, Який ми використовуємо для завантаження даних у сітку Давайте спочатку поглянемо на код методу DoSQLProcess, А потім поговоримо про те, як він працює:

void  TForm1::DoSQLProcess(void)

{

int nList1Idx = ListBox1-&gtItemIndex AnsiString s1 =

ListBox1-&gtItems-&gtStrings[nList1Idx]c_str()

int nList2Idx = ListBox2-&gtItemIndex AnsiString s2 =

ListBox2-&gtItems-&gtStrings[nList2Idx]c_str() AnsiString s = &quotSELECT * FROM \&quot"

s += Table1-&gtDatabaseNamec_str() s += Table1-&gtTableNamec_str()

s += &quot\&quot as T1"

s += &quot,"

s += &quot\&quot"

s += Table2-&gtDatabaseNamec_str() s += Table2-&gtTableNamec_str()

s += &quot\&quot as T2"

s += &quot WHERE "

s += &quotT1&quot + s1 + &quot = T2 &quot + s2

/ / Привласнюємо рядок SQL Query1-> SQL-> Add (s) Query1-> Active = true

}

Властивість SQL обєкта TQuery являє собою список рядків, що утворюють команду SQL, яку ми хочемо передати базі даних Мова SQL як такої не відноситься до предмету розгляду даної книги, але деталі цього прикладу представляють для нас інтерес Спочатку ми створюємо рядок, що складається з стандартно го оператора SQL SELECT:

SELECT * from db1, db2

де db1 – Це імя першої таблиці бази даних, а db2 – Імя другого Біда в тому, що ми не використовуємо таких простих позначень, як db1 або db2 Замість цього імена таблиць мають вигляд диск: \ каталог \ імятабліциdbf Це істотно ускладнює роботу з іменами таблиць Мова SQL максимально наочний, тому ми укладаємо імена баз даних в лапки Перша частина оператора виглядає як

SELECT * from &quotd:\directory1\table1dbf&quot, &quotd:\directory2\table2dbf&quot

що є звичайним оператором SQL Наступна частина оператора – пропозиція WHERE, Яке виглядає приблизно як db1field = db2field Ця пропозиція повертає всі записи, в яких поле в db1 ідентично полю в db2 Проблема в тому, що SQL зламається і помре на затвердження типу:

WHERE d:\directory1\table1dbffield = d:\directory2\table2dbffield

Для того щоб впоратися з цією проблемою, ми використовуємо оператор SQL, що визначає псевдоніми (alias statements, AS), який дозволяє нам звертатися до таблиці за більш коротким імені У нашому випадку ми іменуємо звернення до першої таблиці як t1, а до другої – як t2 Після цього ми можемо звертатися до полів як t1field і t2field

Після того як рядки SQL створені, ми додаємо їх в поле Strings обєкта TQuery, А потім робимо запит активним Це потягне за собою вибір заданих нами записів з таблиць і їх завантаження в сітку Все дуже просто, чи не так Так, просто, але тільки якщо ви знаєте, що і як зробити

Джерело: Теллес М – Borland C + + Builder Бібліотека програміста – 1998

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*