delphi7 treeview + 數據庫 實現動態節點維護


首先說下樹節點對應的表的基本結構,必需要有的字段(節點編號,父節點編號,節點名稱),其他字段根據你開發的需要添加
從添加節點開始,一開始就取出表中最大節點編號,每次添加節點的時候,該節點編號增加1;
添加節點的時候我們有2個步驟,首先是給treeview樹種建立節點;其次是給數據庫中添加相應的節點記錄;
添加節點樹的時候,需要注意的是要把該節點的節點編號加入到該節點的data屬性中.
在數據庫中加入節點記錄的時候,節點編號和父節點編號都不能少,如果是第0層節點,那么該節點的父節點編號是'0'(這種情況你自己定義,我在這里設為'0')
顯示節點我寫了一個通用函數來實現的
刪除節點由於要刪除該節點及其所有后代節點在表中的記錄,這個在sql server中好像沒有什么好的語句,我寫了一個存儲過程來實現的

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ShellAPI, DB, ADODB;

type
  TForm1 = class(TForm)
    tv1: TTreeView;
    btn_addtj: TButton;
    btn_addzjd: TButton;
    btn_del: TButton;
    edt_jdmc: TEdit;
    Label1: TLabel;
    btn_xs: TButton;
    con1: TADOConnection;
    qry1: TADOQuery;
    qry2: TADOQuery;
    procedure btn_addtjClick(Sender: TObject);
    procedure btn_addzjdClick(Sender: TObject);
    procedure btn_delClick(Sender: TObject);
    procedure btn_xsClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  maxdwbh: integer;
procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery); overload;
procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery; tab, jdbh, jdmc, fjdbh, nilfjdbh: string); overload;
implementation

{$R *.dfm}
{
功能:在一個treeview中顯示數據庫中父子節點,並且把節點的編號存入自己的data屬性中
參數:tv    展示樹
     fnode 表示tv中的節點,第一次調用通常這個節點取nil
     qry   一個ADOQuery控件,用來做查詢
     tab   我們的父子節點存放的數據庫表名稱
     jdbh  tab中節點編號代表的字段名稱
     jdmc  tab中節點名稱代表的字段名稱
     fjdbh tab中父節點編號代表的字段名稱
     nilfjdbh 樹中第0級節點的父節點字段給分配的值
注意:我們的樹在添加(子)節點的時候也要把它的節點的編號存入到該節點的data屬性中
}

procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery; tab, jdbh, jdmc, fjdbh, nilfjdbh: string);
var
  sql, fdwbh: string;
  node, newnode: TTreeNode;
  pinteger: ^string;
begin
  //判斷表中有沒有節點,如果連第0級節點都不存在,我們也就不需要顯示樹了
  sql := 'select * from tab where fjdbh=''' + nilfjdbh + '''';
  qry.Close;
  qry.SQL.Clear;
  qry.SQL.Add(sql);
  qry.Open;
  if not qry.IsEmpty then
  begin
    if fnode = nil then
      fdwbh := nilfjdbh
    else
      fdwbh := string(fnode.data^);
    //取出節點fnode的全部子節點的記錄
    sql := 'select ' + jdbh + ',' + jdmc + ',' + fjdbh + ' from ' + tab + ' where ' + fjdbh + '=''' + fdwbh + ''' order by ' + jdbh;
    qry.Close;
    qry.SQL.Clear;
    qry.SQL.Add(sql);
    qry.Open;
    //樹中加入子節點
    if not qry.IsEmpty then //有子節點
    begin
      //添加一個節點的所有子節點
      qry.First;
      while not qry.Eof do
      begin
        newnode := tv.Items.AddChild(fnode, qry.fieldbyname(jdmc).AsString);
        New(pinteger);
        pinteger^ := qry.fieldbyname(jdbh).AsString;
        newnode.Data := pinteger;
        qry.Next;
      end;
      //定位下一個該操作的節點
      if fnode = nil then
        node := tv.Items.GetFirstNode
      else
        node := fnode.getFirstChild;
      //遞歸調用對下一個子節點進行同樣的操作
      addChildNodes(tv, node, qry, tab, jdbh, jdmc, fjdbh, nilfjdbh);
    end else //沒有子節點的情況,取它的下一個兄弟節點遞歸調用
    begin
      node := fnode.GetNext;
      if node <> nil then
        addChildNodes(tv, node, qry, tab, jdbh, jdmc, fjdbh, nilfjdbh);
    end;
  end;
end;

procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery);
var
  fdwbh: Integer;
  sql: string;
  node, newnode: TTreeNode;
  Pdata: ^Integer;
begin
  if fnode = nil then
    fdwbh := 0
  else
    fdwbh := Integer(fnode.data^);
  //取出節點fnode的全部子節點的記錄
  sql := 'select dwbh,dwmc,fdwbh from zzjgbmb where fdwbh=' + inttostr(fdwbh) + ' order by dwbh';
  qry.Close;
  qry.SQL.Clear;
  qry.SQL.Add(sql);
  qry.Open;
  //樹中加入子節點
  if not qry.IsEmpty then //有子節點
  begin
    //添加一個節點的所有子節點
    qry.First;
    while not qry.Eof do
    begin
      newnode := tv.Items.AddChild(fnode, qry.fieldbyname('dwmc').AsString);
      New(Pdata);
      Pdata^ := qry.fieldbyname('dwbh').AsInteger;
      newnode.Data := Pdata;
      qry.Next;
    end;
    //定位下一個該操作的節點
    if fnode = nil then
      node := tv.Items.GetFirstNode
    else
      node := fnode.getFirstChild;
    //遞歸調用對下一個節點進行同樣的操作
    addChildNodes(tv, node, qry);
  end else //沒有子節點的情況
  begin
    node := fnode.GetNext;
    if node <> nil then
      addChildNodes(tv, node, qry);
  end;
end;


procedure TForm1.btn_addtjClick(Sender: TObject);
var
  jdmc, sql: string;
  fdwbh: integer;
  node, newnode: TTreeNode;
  pinteger: ^integer;
begin
  try
    node := tv1.Selected;
    jdmc := edt_jdmc.text;
    newnode := tv1.Items.add(node, jdmc);
    maxdwbh := maxdwbh + 1;
    New(pinteger);
    pinteger^ := maxdwbh;
    newnode.data := pinteger;

    if node = nil then
      fdwbh := 0
    else if node.Level = 0 then
      fdwbh := 0
    else
      fdwbh := Integer(node.Parent.data^);
    sql := 'insert into zzjgbmb(dwbh,fdwbh,dwmc) values(' + inttostr(maxdwbh) + ',' + inttostr(fdwbh) + ',''' + jdmc + ''')';
    qry1.Close;
    qry1.SQL.Clear;
    qry1.SQL.Add(sql);
    qry1.ExecSQL;
    ShowMessage('單位"' + jdmc + '"添加成功!');
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TForm1.btn_addzjdClick(Sender: TObject);
var
  jdmc, sql: string;
  fdwbh: integer;
  node, newnode: TTreeNode;
  pinteger: ^integer;
begin
  try
    jdmc := edt_jdmc.text;
    node := tv1.Selected;
    newnode := tv1.Items.AddChild(node, jdmc);
    maxdwbh := maxdwbh + 1;
    New(pinteger);
    pinteger^ := maxdwbh;
    newnode.Data := pinteger;
    if node = nil then
      Exit
    else
      fdwbh := Integer(node.data^);

    sql := 'insert into zzjgbmb(dwbh,fdwbh,dwmc) values(' + inttostr(maxdwbh) + ',' + inttostr(fdwbh) + ',''' + jdmc + ''')';
    qry1.Close;
    qry1.SQL.Clear;
    qry1.SQL.Add(sql);
    qry1.ExecSQL;
    ShowMessage('單位"' + jdmc + '"添加成功!');
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TForm1.btn_delClick(Sender: TObject);
var
  node: TTreeNode;
  dwbh: integer;
  sql: string;
begin
  try
    node := tv1.Selected;
    node.Delete;
    dwbh := Integer(node.data^);
    sql := 'exec p_zzjgbmb_delnode ' + inttostr(dwbh);
    qry1.Close;
    qry1.SQL.Clear;
    qry1.SQL.Add(sql);
    qry1.ExecSQL;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TForm1.btn_xsClick(Sender: TObject);
begin
  try
    tv1.Items.Clear;
    addChildNodes(tv1, nil, qry1, 'zzjgbmb', 'dwbh', 'dwmc', 'fdwbh', '0');
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  sql: string;
begin
  try
    maxdwbh := 0;
    sql := 'select max(dwbh) maxdwbh from zzjgbmb';
    qry1.Close;
    qry1.SQL.Clear;
    qry1.SQL.Add(sql);
    qry1.Open;
    if not qry1.isempty then
    begin
      qry1.First;
      maxdwbh := qry1.fieldbyname('maxdwbh').AsInteger;
    end;
  except
    on e: Exception do
      showmessage(e.message);
  end;
end;

end.

刪除節點及其后代節點的存儲過程

create procedure [dbo].[p_zzjgbmb_delnode](@dwbh int)
as
begin
  declare @tmp1 table (dwbh int)
  declare @tmp2 table (dwbh int)
  declare @tmp3 table (dwbh int)
  
  insert into @tmp1 select dwbh from zzjgbmb where fdwbh=@dwbh
  insert into @tmp3 select dwbh from @tmp1
  
  while exists(select dwbh from zzjgbmb where fdwbh in (select dwbh from @tmp1))
  begin
    delete @tmp2
    insert into @tmp2 select dwbh from zzjgbmb where fdwbh in (select dwbh from @tmp1)    
    delete @tmp1
    insert into @tmp1 select dwbh from @tmp2   
    insert into @tmp3 select dwbh from @tmp1 
  end 
  
  delete from zzjgbmb where dwbh in (select dwbh from @tmp3); 
  delete from zzjgbmb where dwbh = @dwbh
end

簡單的界面

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM