(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

SQLite и FireMonkey. Учимся заполнять таблицы.

Vlad

С появлением в Delphi XE2 FireMonkey иногда ощущаю себя прям каким-то первоклассником =) Не сказать, чтобы прям уж так совсем все непонятно и сложно...скорее немного не привычно использовать новые FMX-контролы. Вот и сегодня от темы статьи так и напоминает что-то из разряда "Delphi для начинающих". Но, как говориться, из песни слов не выкинешь - раз решил поработать с FireMonkey, то начинать надо с простых вещей. Ну, а так как в статье про SQLite  для Delphi XE2 было предложение расписать работу с Grid'ами в FMX, то попробуем написать небольшое приложение, которое будет заполнять табличку на основании запроса к базе SQLite.

И в начале несколько слов про SQLite в Delphi, а точнее про ту обертку с которой я буду работать. Дело в том, что это, наверное, самая простая обертка из всех, что мне встречались (собственно этим она мне и понравилась). Здесь нет компонентов, все объекты в модуле SQLiteTable3 - это классы-наследники от TObject, а вся работа напрямую связана с запросами к библиотеке SQLite (в Win-приложениях - это будет sqlite3.dll). Естественно, такая организация работы с SQLite накладывает некоторые ограничения на работу с БД SQLite. Например, я не могу взять и без лишних заморочек использовать TDataSet или использовать также просто как и при работе, например, с MSSQL DBGrid - придется искать свое решение, использовать TClientDataSet'ы и т.д. Но, мне такие решения в принципе не нужны были. Единственный раз когда мне приходилось использовать TDataSet, TDBGrid и т.д. был лет эдак пять-семь назад и то всё это "творчество" тогда использовало BDE.  В общем, если у кого-то возникнет желание/потребность связать эту обертку с TDataSet - знайте, что сделать это просто и быстро врядли получится. Ну, а я рассмотрю пример того, как, используя SQLiteTable2.pas можно формировать таблицы в приложении Firemonkey.

В качестве примера, воспользуемся базой данных, в которой будет содержаться таблица, рассмотренная в предыдущей статье про SQLite:

CREATE TABLE [TestTable] (
  [id] INTEGER PRIMARY KEY AUTOINCREMENT,
  [StringRow] TEXT,
  [NumberRow] INTEGER,
  [DateTimeRow] DATETIME);

Теперь посмотрим, что нам необходимо знать для того, чтобы заполнить таблицу.

Для того, чтобы заполнить таблицу на форме (не важно какую - из FMX или VCL) нам необходимо знать помимо значений полей набора данных ещё как минимум два значения: количество полей (столбцов) и количество записей (строк) в таблице. Иначе мы просто не сможем правильно установить количество строк и столбцов у нашего контрола на форме.

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

Для примера создадим новое приложение "Firemonkey HD Application" и разместим на форме следующие элементы:
TMemo - здесь мы будем просматривать/редактировать SQL-запросы
TStringGrid (со вкладки Grids) - сюда будем выводить результат выполнения запроса
2 TButton для выполнения операции подключения к БД и выполнения SQL-запроса
TComboBox - для хранения списка таблиц БД
TOpenDialog - для выбора файла БД.
Внешний вид приложения у меня получился вот такой:

 

При нажатии на кнопку "Connect" мы будем подключаться к базе данных и считывать из неё названия всех таблиц. Я предложил использовать БД из предыдущей статьи, но фактически приложение сможет работать с любой указанной вами БД, поэтому списочек получать мы будем так:
Подключаем в uses модули

uses
  [..], SQLite3, SQLiteTable3;

создаем в секции private класса формы следующие переменные:

type
  TForm1 = class(TForm)
    [...]
  private
    FBase: TSQLiteDatabase;
    FStmt: TSQLitePreparedStatement;
    FTable: TSQLiteUniTable;
  public
 
  end;
 На OnClick кнопки "Connect" пишем
 if dlgOpenBase.Execute then
    begin
      try
        FBase:=TSQLiteDatabase.Create(dlgOpenBase.FileName);
        FBase.GetTableStrings('SELECT name FROM sqlite_master WHERE type="table" ORDER BY name',cbTables.Items);
        ShowMessage('Подключились. Названия таблиц прочитали');
      except
        ShowMessage('Не смогли подключиться к базе данных');
      end;
    end;

Здесь стоит отметить следующие моменты.

Во-первых, что за таблица sqlite_master к которой я так смело обратился? Это специальная таблица, которая содержится в любой БД SQLite и содержит сведения по базе данных. В моем случае я выбрал из sqlite_master только те записи, в которых содержатся сведения по таблицам БД, т.е. проверил значение поля type на присутствие в нем значения "table". Можно было бы запросить и всю таблицу целиком. sqlite_master выглядит следующим образом:

CREATE TABLE sqlite_master (
  TYPE TEXT,
  name TEXT,
  tbl_name TEXT,
  rootpage INTEGER,
  SQL TEXT
);

Более подробно про эту таблицу можно почитать в официальном FAQ.

Во-вторых, стоит немного рассказать про метод GetTableStrings у TSQLiteDatabase. Дело в том, что не важно какого содержания SELECT вы отправите к базе данных, этот метод всегда вернет строковые значения из первого столбца (с индексом 0). Ну, а так как у меня результат запроса и содержит всего одно поле, то я без лишних проверок записал все значения в ComboBox.

Следующий момент - это отправка запроса к произвольной таблице БД. Здесь все довольно просто. Например, на OnChange ComboBox'а можно написать такой код:

TableName:=;
  FStmt:=TSQLitePreparedStatement.Create(FBase,'SELECT * FROM '+ComboBox1.Items[cbTables.ItemIndex]);
  FTable:=FStmt.ExecQuery;
  Memo1.Lines.Clear;
  Memo1.Lines.Add(FStmt.SQL);

То есть после выбора названия таблички в ComboBox'е просто считываем все значения.

Ну, а теперь подходим к главному. Получили мы все, что хотели из БД, а как теперь эти значения "вытянуть" на наш StringGrid? Вот здесь мы сделаем небольшое отступление от работы над приложением и проясним некоторые моменты по поводу FMX.

StringGrid в FireMonkey

Помните в начале статьи я сказал, что работать с контролами в FMX мне несколько непривычно? Про это я немного говорил в "Знакомстве с FireMonkey", теперь же постараюсь рассказать более подробно.

Итак, раз вы (и я с вами) решили использовать в проекте FireMonkey, то первое, что стоит для себя уяснить - это то, что несмотря на схожесть названий контрол в FMX - это вообще не тоже самое, что контрол в VCL. У них общего столько же сколько у мопеда и мотоцикла Harley Davidson - оба на двух колесах.

 

Например, все, что общего у двух TButton - это родитель TComponent.

В FMX любой компонент - это контейнер. Контейнер может содержать в себе ещё один контейнер, а в том ещё 5 контейнеров и т.д. и при этом чем сложнее контрол - тем сложнее иерархия объектов.  Все компоненты FMX собираются из базовых элементов, таких как TLayout, TRectangle и т.д. Вот она та самая "необычность" к которой надо привыкать в случае работы с FireMonkey.

Теперь, что касается StringGrid в FMX. Чтобы разобраться из чего состоит таблица обратимся к StyleBook. Бросаем на форму компонент TStyleBook, дважды кликаем по нему мышкой и в дереве ищем запись gridstyle:

 

Как видите в таблице FMX заголовок таблицы (header) и основное содержимое (content) - это разные элементы. То есть мы можем изменять стиль заголовков, не затрагивая при этом стиль строк таблиц. Но до этого нам пока ещё рано - надо разобраться как вообще управляться с таблицей.

Для того, чтобы добавить в таблицу новый столбец, достаточно дважды кликнуть по таблице на форме и в редакторе нажать кнопку AddItem. Например, на рисунке ниже представлен редактор в котором я добавил в таблицу пять столбцов и вид окна Structure, чтобы дать вам небольшое предстовление о том, что в итоге получится, так сказать "концепция контейнеров в действии":

 

Можно через тот же редактор сделать и так, что каждый столбец таблицы будет содержать в себе ещё с десяток столбцов, но в визуальном плане это никак не отразиться - таблица в приложении так и будет двухмерная. Для каждого столбца таблицы мы можем задать свои особые свойства, например, для нас сегодня будет важно свойство Header:string - заголовок столбца.

Что касается ячеек таблицы, то каждый столбец (TStringColumn) содержит поле FCells, которое представляет собой массив строк. Свойства для этого поля нет, а вся работа с ячейками и строками осуществляется в родителе, т.е. с TStringGrid. И здесь отличий никаких в названиях свойств и методов от VCL нет. Например, чтобы указать количество строк, надо указать значение свойства RowCount:

  MyStringGrid.RowCount:=10;

А чтобы указать значение для ячейки, воспользоваться свойством Cells:

  MyStringGrid.Cells[0,0]:='Ячейка 0,0'

При этом помните, что заголовок таблицы и содержимое таблицы - разные элементы (см. структуру компонента выше). То есть значение индексов строк в VCL и FMX.StringGrid'ах будут различаться на 1 (см. рисунок ниже):

 

Двигаемся далее. Раз решал рассмотреть свойства, то стоит отметить, что у FMX.StringGrid нет свойства ColCount для изменения количества столбцов в runtime. Вместо него есть свойство только для чтения под названием ColumnCount. Но это отнюдь не означает, что мы не в состоянии поменять количество столбцов у FXM.StringGrid в runtime. Сделать это можно, например так:

//удаляем все столбцы из таблицы
  for I := StringGrid1.ColumnCount-1 downto 0 do
    StringGrid1.Columns[i].Release;
//добавляем 4 новых столбца
for i:=1 to 4 do
  StringGrid1.AddObject(TStringColumn.Create(nil));

В целом это все особенности, которые нам необходимо уяснить для дальнейшей работы с FMX.StringGrid. Резюмируем и двигаемся обратно в наше приложение:
Количество строк меняется также как и в VCL - через свойство RowCount
Строка с индексом 0 в FMX.StringGrid - это то же самое, что строка с индексом 1 в VCL, т.к. заголовок таблицы и набор строк - разные элементы компонента.
У FMX.StringGrid нет свойства ColCount - изменение количества столбцов необходимо проводить через работу со свойством Columns и добавление новых столбцов как дочерних элементов, используя метод AddObject.

Краткий экскурс в FMX.StringGrid закончили - продолжим работу над приложением. Нам осталось только правильно заполнять табличку и научить программу выполнять произвольные запросы. Начнем с таблицы и напишем метод, с помощью которого будет строится таблица с данными из запроса:
procedure TForm1.DrawTable(ATable: TSQLiteUniTable);


var i:integer;
    delta: integer;
begin
  //смотрим сколько надо удалить/добавить столбуов
  delta:=StringGrid1.ColumnCount-ATable.FieldCount;
  if delta>0 then //в таблице столбцов больше чем надо - удаляем
    begin
      for I := 1 to delta do
        StringGrid1.Columns[StringGrid1.ColumnCount-1].Release;
    end
  else //не хватает столбуов - добавляем
    begin
      for I := 1 to abs(delta) do
        StringGrid1.AddObject(TStringColumn.Create(nil));
    end;
  StringGrid1.RowCount:=0;//обнуляем количество строк
try
  StringGrid1.BeginUpdate;
  //заполняем табличку данными
  while not ATable.EOF do
    begin
      {увеличиваем количество строк на 1}
      StringGrid1.RowCount:=StringGrid1.RowCount+1;
      for I := 0 to ATable.FieldCount-1 do
        begin
        {задаем заголовок столбца}
        StringGrid1.Columns[i].Header:=ATable.Fields[i].Name;
        {выписываем в ячейку последнее значение}
        StringGrid1.Cells[i,ATable.Row-1]:=ATable.FieldAsString(i);
        end;
      ATable.Next
    end;
finally
  StringGrid1.EndUpdate;
end;
end;

Здесь мы вначале определяем сколько столбцов надо добавить/удалить из таблицы. Затем приводим таблицу в исходное состояние, т.е. устанавливаем необходимое количество столбцов и строк. И наконец, проходимя по каждой записи в TSQLiteUniTable выводим значения полей в соответствующие ячейки FMX.StringGrid.

Теперь остается только "навесить" необходимое событие на кнопку "Выполнить SQL" и вызвать только что созданный метод. Обработчик OnClick кнопки будет следующим:
if not Assigned(FStmt) then

  FStmt:=TSQLitePreparedStatement.Create(FBase);
FStmt.SQL:=Memo1.Text;//запомнили и подготовили запрос
FTable:=FStmt.ExecQuery();//выполнили запрос и получили объект-таблицу
DrawTable(FTable)//передали таблицу в метод и отрисовали StringGrid

Ну и в заключение вид приложения в котором показана таблица FMX.StringGrid, содержащая ту самую 1000 записей, которые мы добавляли в прошлый раз:

 

На отрисовку таблички ушло чуть больше 1 секунды.

Исходник приложения (без DLL и базы данных) можно скачать по ссылке ниже:

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 11.11.2011 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Enterprise Connectors (1 Year term)
Delphi Professional Named User
Rational ClearCase Multisite Floating User License
Quest Software. TOAD for SQL Server Xpert Edition
Allround Automation PL/SQL Developer - 5 user license
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Реестр Windows. Секреты работы на компьютере
СУБД Oracle "с нуля"
Работа в Windows и новости компании Microsoft
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100