Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Программирование под Windows > Delphi
Перезагрузить страницу Как заполнить дерево TreeView из базы данных Access
Ответ
 
Опции темы Опции просмотра
  (#1 (permalink)) Старый
makem
Guest
 
Сообщений: n/a
Thumbs up Как заполнить дерево TreeView из базы данных Access - 22.07.2006, 11:00

Есть необходимость заполнения TreeView из БД Access используя ADO. Структура БД следующая

ID - автоинкремент
Parent_ID - указатель на родителя
Name - имя ветки

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

Сейчас БД не очень большая, современем будет расти. На данный момент опыта в программировании на Delphi не много, поэтому прошу рассказать по подробнее. Пожалуйста!
Ответить с цитированием
  (#2 (permalink)) Старый
PerfectStranger PerfectStranger вне форума
Member
 
Сообщений: 240
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 19.05.2006
По умолчанию 24.07.2006, 11:24

Можно заполнить все дерево сразу:
Код:
uses ..., AdoInt, ...;

procedure TMainForm.ADOConnection1AfterConnect(Sender: TObject);
begin
  FillLevel(nil, 0);
end;

procedure TMainForm.FillLevel(ParentNode: TTreeNode; iParentID: Integer);
const
  SQL_SELECT_LEVEL =
    'SELECT Name, ID FROM Table1 WHERE Parent_ID%0:s';
  SQL_PARENT_IS_NULL = ' IS NULL';
  SQL_PARENT_EQ = ' = %0:d';
var
  sParentCond,
  sSQL: string;
  rs: _Recordset;
  Node: TTreeNode;
begin
  if iParentID = 0 then
    sParentCond := SQL_PARENT_IS_NULL
  else
    sParentCond := Format(SQL_PARENT_EQ, [iParentID]);
  sSQL := Format(SQL_SELECT_LEVEL, [sParentCond]);
  ShowMessage(sSQL);
  rs := ADOConnection1.Execute(sSQL);
  while not rs.EOF do begin
    Node := TreeView1.Items.AddChild(ParentNode, rs.Fields['Name'].Value);
    FillLevel(Node, rs.Fields['ID'].Value);
    rs.MoveNext;
  end;
end;
Но при большом объеме данных это будет, конечно, очень тормозно. Поэтому поступают обычно так: запрашивают уровень дерева по необходимости. Например: из метода FillLevel надо удалить рекурсивный вызов самого себя. При открытии соединения вызываем метод FillLevel, но внутри у него при добавлении узла: 1) запоминаем ID узла, например, в свойстве Data у добавляемого TTreeNode (нужно будет Integer привести к Pointer'у, как-то так: Pointer(Integer(rs.Fields['ID'].Value)) ); 2) добавляем виртуальный дочерний узел для узла Node, чтобы этот виртуальный узел можно было отличить от "нормального" узла, можно ему занести в Data несуществующий ID, например, значение Pointer(-1).
Затем при раскрытии какого-либо узла дерева (событие OnExpanding у TreeView) смотрим: если есть только один дочерний узел и у него свойство Data содержит наше специальное значение Pointer(-1), то значит что раскрываемый узел еще не заполнен, значит чистим его деток (убираем специальный узел) и заполняем его "нормальными" детями вызовом метода FillLevel c раскрываемым узлом и ID считанной из его свойства Data.
И будет Вам шастье!!!

ЗЫ: Если не нравится ситуация, как будут вести себя узлы не имеющие детей (жмешь на узел, а он не раскрывается, просто крестик исчезает, как на сетевых папках в проводнике), то можно усложнить алгоритм и считывать на один уровень больше. Но я бы с этим не заморачивался - при больших объемах данных, опять-таки, может быть тормозно.
Ответить с цитированием
  (#3 (permalink)) Старый
SH@DOW SH@DOW вне форума
Member
 
Сообщений: 2,085
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 18.09.2002
По умолчанию 24.07.2006, 12:54

Чивота я не понял?

Так есть же куча трилистов и тривью для в которых есть и KeyField и ParentField. И там никаких скюэлей не надо. Возьми DevExpres dxDBTreeList
Ответить с цитированием
  (#4 (permalink)) Старый
Mark_Titan Mark_Titan вне форума
Новичок
 
Сообщений: 3
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 25.01.2018
По умолчанию Нармуль - 25.01.2018, 17:22

Мне такой вариант подошел, конечно, не с первого раза запустилось как надо, но разобрался. Спасибо.

не было указано сам запрос в ADOQuery1 -sql запись - 'SELECT * FROM tree WHERE ID' (закинул так)
FillLevel(nil, 0); - с таким параметром не начинается, FillLevel(nil, 1), так пошло))

пока работал с базой, и смотрел как оно все выводит добавил кнопку "пере подключения", и обработчик бросил на него:

Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
 ADOQuery1.Active:=False;
 TreeView1.Items.Clear;
 ADOQuery1.Active:=True;
    FillLevel(nil, 1);
end;
у меня трудности возникли именно с базой ((
через научный метод "тыка" разобрался))

таблица в Access
|id|ParentID|Name|
|1 | 0 |имя 1|
|2 | 1 |имя 2|
|3 | 2 |имя 3|
|4 | 2 |имя 4|
|5 | 1 |имя 5|
|6 | 5 |имя 6|

дальше просто пишем какое-то имя, и в колонке "ParentID" вписываем "ID" продукта в которого появиться ребенок))

главное чтобы "ID» не совпадал с "ParentID" а то получается Отец сам себе ребенок, и все весит, и начинается образовываться черная дыра, и прошлое становится будущим))))

Последний раз редактировалось Mark_Titan; 25.01.2018 в 17:25
Ответить с цитированием
  (#5 (permalink)) Старый
Mark_Titan Mark_Titan вне форума
Новичок
 
Сообщений: 3
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 25.01.2018
По умолчанию 25.01.2018, 17:39

ADOQuery1 вообще не надо))
Ответить с цитированием
Ads.
  (#6 (permalink)) Старый
Mark_Titan Mark_Titan вне форума
Новичок
 
Сообщений: 3
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 25.01.2018
По умолчанию 25.01.2018, 17:52

кажется, вот так более правильно:

Код:
if iParentID < 0 then
    sParentCond := SQL_PARENT_IS_NULL
  else


Код:
 
unit tree_Parent;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,Data.DBXMySQL, Data.DB, Data.SqlExpr,
  Data.Win.ADODB, Vcl.Menus, Vcl.ExtCtrls, Vcl.StdCtrls,
  Vcl.ComCtrls;

type
  TFormTree = class(TForm)
    ADOConnection1: TADOConnection;
    TreeView1: TTreeView;
    Button2: TButton;
    procedure ADOConnection1AfterConnect(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormTree: TFormTree;

implementation

{$R *.dfm}

procedure FillLevel(ParentNode: TTreeNode; iParentID: Integer);
const
  SQL_SELECT_LEVEL =
    'SELECT * FROM tree WHERE ParentID%0:s';
  SQL_PARENT_IS_NULL = ' IS NULL';
  SQL_PARENT_EQ = ' = %0:d';
var
  sParentCond,
  sSQL: string;
  rs: _Recordset;
  Node: TTreeNode;
begin

  if iParentID < 0 then
    sParentCond := SQL_PARENT_IS_NULL
  else
    sParentCond := Format(SQL_PARENT_EQ, [iParentID]);
  sSQL := Format(SQL_SELECT_LEVEL, [sParentCond]);
//  ShowMessage(sSQL);
  rs := FormTree.ADOConnection1.Execute(sSQL);


  while not rs.EOF do begin
    Node := FormTree.TreeView1.Items.AddChild(ParentNode, rs.Fields['name'].Value);
    FillLevel(Node, rs.Fields['ID'].Value);
    rs.MoveNext;
  end;
end;


procedure TFormTree.ADOConnection1AfterConnect(Sender: TObject);

begin
 FillLevel(nil, 0);
end;

procedure TFormTree.Button2Click(Sender: TObject);
begin
 ADOConnection1.Connected:=False;
 TreeView1.Items.Clear;
 ADOConnection1.Connected:=True;
end;

end.
Ответить с цитированием
Ads
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обучение SQL Базы Данных Access MySQL Обучение Access - прекрасная возможность получи rezultatkurs Коммерческий раздел 0 24.03.2012 19:39
Загрузка базы данных Access в Excel maksi Visual Basic 8 07.05.2011 22:50
Как отобразить таблицу из базы данных Access в DataGrid Sphinx .NET 2 21.12.2007 18:22
Базы данных Visual C++, DAO и Access. Alex Dyller Вопросы начинающих программистов 0 04.07.2007 15:05
Сортировка в базы данных Access и Paradox Alex_Sosim C++ Builder 1 11.10.2006 13:42
ADO + Access + Builder 6 создание базы данных удаленно Jinjo C++ Builder 7 12.02.2006 22:13
Создание базы данных Access программно Anonymous C++ Builder 13 06.10.2005 09:03
Создание дерево которое тянет данные из Базы данных s_vad C++ Builder 4 23.08.2005 01:02
Delphi и базы данных MS Access snaip Delphi 6 19.06.2005 12:56
Запрос базы данных Access из VC++ St. Andrew Visual C++ 2 09.06.2005 11:00
Базы данных access 97 под WinXP Anonymous Вопросы начинающих программистов 0 04.02.2004 14:09
Как автматичски заполнить таблицу базы данных Китайский сварщик C++ Builder 0 04.12.2003 02:05



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов