我有一个数据库结构如下:  
字段名  字段类型
编号      字符型
部门名称 字符型数据库中的记录如下:
编号       部门名称  
0001        创业公司软件部  
000101      业务部  
00010101    业务部一号小组  
00010102    业务部二号小组  
000102      开发部  问题一、
现在我需要把数据库中记录在Treeview中按以下结构显示出来,
用Query数据控件(我以前是用Table不太好用),我对SQL语法不是很熟。
创业公司软件部  
 |---业务部  
 |   |  
 |   |-----业务部一号小组  
 |   |  
 |   |-----业务部二号小组  
 |  
 |---开发部  问题二、
我要在创业公司软件部下面在增加子项时编号要求自动生成,
或要在开发部下面增加子项时编号要求自动生成,
例如:在一个窗体上有一个Edit框中输入部门名称,编号不用输入自动生成,
这个树形结构是用部门名称来产生的,上面的数据库编号记录已有0001、000101、00010101、00010102、000102,
那如果我在树形结构中点击 0001 创业公司软件部增加子项时那产生的是记录编号和记录就是000103 资源部;
那如果我在树形结构中点击000102 开发部增加子项时那产生的记录编号和记录就是00010201 开发部一号小组,
也就是说不能产生重复的编号,数据增加完毕后要在树形结构中显示出来(就是要把数据添加进数据库);
请高手指教!

解决方案 »

  1.   

    我自己尝试着作了一个,但在运行中出现错误,有谁能帮我改一下呀!
    请留下E-Mail址,我把源代码发给你,谢谢。
      

  2.   

    自己写个函数吧 我以前做过的,说说思路:
    问题1:因为节点的位置信息都存在编号字段中,所以可以根据它就可以显示treeview了,先select 编号,部门名称,(select count(*) from 你的表 where 编号<=left(编号,len(编号)-2)) as theparent from 你的表 order by 编号
    这样就会按照treeview节点的绝对index的顺序排序了,然后一个节点一个节点的添加就行了,添加时他的父节点的绝对index就是theparent字段值,这样就应该ok了
    问题2:添加时可以先在treeview中添加,然后根据新加的节点信息再生成编号值插到库中就行了,这你可以再写一个函数,参数是节点的index 返回string类型的编号值。
      

  3.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Grids, DBGridEh, ComCtrls, ExtCtrls, DB, ADODB,
      DBGrids, Menus, DBCtrls;type
      PMyRec = ^TMyRec;
      TMyRec = record
        DepartName : string;
        DepartNo   : string;
      end;
      TForm1 = class(TForm)
        DataSource1: TDataSource;
        Panel2: TPanel;
        Panel3: TPanel;
        TreeView1: TTreeView;
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
        tmp: TADOTable;
        PopupMenu1: TPopupMenu;
        N1: TMenuItem;
        N2: TMenuItem;
        ADOConnection1: TADOConnection;
        N3: TMenuItem;
        N4: TMenuItem;
        N5: TMenuItem;
        N6: TMenuItem;
        N7: TMenuItem;
        procedure InsertNode;
        procedure delNode;
        procedure fetchdata(DepartNo: string; CurNode:TTreeNode);
        procedure deletedata(DepartNo: string);
        procedure updatedata(DepartNo, departname: string);
        procedure AddDataToTable(DEPARTNAME,DEPARTNO,PREDEPART:String);
        procedure FormShow(Sender: TObject);
        procedure N1Click(Sender: TObject);
        procedure N2Click(Sender: TObject);
        procedure N4Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure N5Click(Sender: TObject);
        procedure TreeView1Edited(Sender: TObject; Node: TTreeNode;
          var S: String);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.AddDataToTable(DEPARTNAME,DEPARTNO,PREDEPART:String);
    begin
      if not tmp.Active then
        tmp.Active := true;  tmp.Append;
      tmp.FieldByName('DEPARTNAME').Value := DEPARTNAME;
      tmp.FieldByName('DEPARTNO').Value := DEPARTNO;
      tmp.FieldByName('PREDEPART').Value := PREDEPART;
      tmp.Post;  if tmp.Active then
        tmp.Close;
      tmp.Active := true;
    end;procedure TForm1.fetchdata(DepartNo: string; CurNode:TTreeNode);
    var
      MyRecPtr: PMyRec;
      zIndex : integer;
      tmpStr:String;
      Node1  : TTreeNode;
      tmpadq:TADOQuery;
    begin
      tmpadq := TADOQuery.Create(nil);
      try
        tmpadq.Connection := ADOConnection1;
        tmpStr:= ' SELECT * FROM DEPART2 WHERE PREDEPART = ' + QuotedStr(DepartNo) + ' ORDER BY PREDEPART, DEPARTNO';
        tmpadq.Close;
        tmpadq.SQL.Clear;
        tmpadq.SQL.Add(tmpStr);
        tmpadq.Open;
        tmpadq.First;
        if tmpadq.RecordCount > 0 then
        begin
          for zindex:= 1 to tmpadq.RecordCount do
          begin
            NEW(MyRecPtr);
            MyRecPtr.DepartName := tmpadq.FieldByName('DEPARTNAME').AsString;
            MyRecPtr.DepartNo   := tmpadq.FieldByName('DEPARTNO').AsString;
            TreeView1.Selected := CurNode;
            Node1 := TreeView1.Items.AddChildObject(CurNode, tmpadq.FieldByName('DEPARTNAME').AsString,MyRecPtr);
            fetchdata(tmpadq.FieldByName('DEPARTNo').AsString, Node1);
            tmpadq.Next;
          end;
        end else
        begin
          exit;
        end;
      finally
        tmpadq.Close;
        tmpadq.Free;
      end;end;procedure TForm1.FormShow(Sender: TObject);
    begin
      if not tmp.Active then
        tmp.Active := true;
      //读入树
      fetchdata('0',TreeView1.TopItem);
    end;procedure TForm1.InsertNode;
    var
      MyRecPtr: PMyRec;
      CHNode  : TTreeNode;
      StrName : String;
    begin
      if not Assigned(Pointer(TreeView1.Selected)) then
         exit;  case TreeView1.Selected.Level of
        0:
            StrName:=InputBox('新增公司','请输入公司名称:','');
        1:
            StrName:=InputBox('新增部门','请输入部门名称:','');
        2:
            StrName:=InputBox('新增项目组','请输入项目组名称:','');
        else
           exit;
      end;
      if Trim(StrName) = '' then
        exit;
      NEW(MyRecPtr);
      MyRecPtr.DepartName := StrName;
      MyRecPtr.DepartNo  := IntToStr(TreeView1.Items.Count);
      CHNode := TreeView1.Items.AddChildObject(TreeView1.Selected, StrName, MyRecPtr);  if TreeView1.Selected.Level = 0 then
      begin
          AddDataToTable(StrName, IntToStr(TreeView1.Items.Count -1), '0');
      end else
      begin
          AddDataToTable(StrName, IntToStr(TreeView1.Items.Count - 1), PMyRec(TreeView1.Selected.Data)^.DepartNo);
      end;
      TreeView1.Refresh;
      TreeView1.Selected := CHNode;
    end;procedure TForm1.N1Click(Sender: TObject);
    begin
      TreeView1.FullExpand;
    end;procedure TForm1.N2Click(Sender: TObject);
    begin
      TreeView1.FullCollapse;
    end;
    procedure TForm1.N4Click(Sender: TObject);
    begin
      InsertNode;
    end;procedure TForm1.delNode;
    var
      tmpStr:STring;
    begin
      if Assigned(Pointer(TreeView1.Selected)) and (TreeView1.Selected.Level > 0)then
      begin
        case TreeView1.Selected.Level of
          1:
            tmpStr := '是否删除公司及下属部门数据';
          2:
            tmpStr := '是否删除部门及下属工作组数据';
          3:
            tmpStr := '是否删除工作组及下属数据';
        end;
        if (MessageBox(Handle, PChar(tmpStr), PChar('提示信息'), MB_YESNO or MB_ICONSTOP) = IDYES) then
        begin
          deletedata(PMyRec(TreeView1.Selected.Data)^.DepartNo);
          TreeView1.Selected.Delete;
        end;
      end;end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      InsertNode;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
      delNode;
    end;procedure TForm1.N5Click(Sender: TObject);
    begin
      delNode;
    end;procedure TForm1.deletedata(DepartNo: string);
    var
      tmpStr:String;
      tmpadq:TADOQuery;
    begin
      tmpadq := TADOQuery.Create(nil);
      try
        tmpadq.Connection := ADOConnection1;
        tmpStr:= ' DELETE FROM DEPART2 WHERE PREDEPART = ' + QuotedStr(DepartNo) + ' or DepartNo =' + QuotedStr(DepartNo);
        tmpadq.Close;
        tmpadq.SQL.Clear;
        tmpadq.SQL.Add(tmpStr);
        tmpadq.ExecSQL;
      finally
        tmpadq.Close;
        tmpadq.Free;
      end;end;procedure TForm1.updatedata(DepartNo, departname: string);
    var
      tmpStr:String;
      tmpadq:TADOQuery;
    begin
      tmpadq := TADOQuery.Create(nil);
      try
        tmpadq.Connection := ADOConnection1;
        tmpStr:= ' update DEPART2 set DEPARTNAME = ' + QuotedStr(departname) + ' where  DepartNo = ' + QuotedStr(DepartNo);
        tmpadq.Close;
        tmpadq.SQL.Clear;
        tmpadq.SQL.Add(tmpStr);
        tmpadq.ExecSQL;
      finally
        tmpadq.Close;
        tmpadq.Free;
      end;end;procedure TForm1.TreeView1Edited(Sender: TObject; Node: TTreeNode;
      var S: String);
    begin
      updatedata(PMyRec(Node.Data)^.DepartNo, s);
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      ShowMessage(PMyRec(TreeView1.Selected.Data)^.DepartNo);
    end;end.
      

  4.   

    object Form1: TForm1
      Left = 310
      Top = 166
      BorderStyle = bsSingle
      Caption = #26641#31034#20363
      ClientHeight = 250
      ClientWidth = 337
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      OnShow = FormShow
      PixelsPerInch = 96
      TextHeight = 13
      object Panel2: TPanel
        Left = 0
        Top = 209
        Width = 337
        Height = 41
        Align = alBottom
        BevelInner = bvLowered
        TabOrder = 0
        object Button1: TButton
          Left = 8
          Top = 9
          Width = 75
          Height = 25
          Caption = #22686#21152
          TabOrder = 0
          OnClick = Button1Click
        end
        object Button2: TButton
          Left = 88
          Top = 9
          Width = 75
          Height = 25
          Caption = #20462#25913
          TabOrder = 1
          OnClick = Button2Click
        end
        object Button3: TButton
          Left = 168
          Top = 9
          Width = 75
          Height = 25
          Caption = #21024#38500
          TabOrder = 2
          OnClick = Button3Click
        end
        object Button4: TButton
          Left = 248
          Top = 9
          Width = 75
          Height = 25
          Caption = #36864#20986
          TabOrder = 3
        end
      end
      object Panel3: TPanel
        Left = 0
        Top = 0
        Width = 337
        Height = 209
        Align = alClient
        BevelInner = bvLowered
        TabOrder = 1
        object TreeView1: TTreeView
          Left = 2
          Top = 2
          Width = 333
          Height = 205
          Align = alClient
          HideSelection = False
          Indent = 19
          PopupMenu = PopupMenu1
          TabOrder = 0
          OnEdited = TreeView1Edited
          Items.Data = {
            010000001F0000000000000000000000FFFFFFFFFFFFFFFF0000000000000000
            06D7DCB9ABCBBE}
        end
      end
      object DataSource1: TDataSource
        DataSet = tmp
        Left = 168
        Top = 16
      end
      object tmp: TADOTable
        Connection = ADOConnection1
        CursorType = ctStatic
        TableName = 'DEPART2'
        Left = 216
        Top = 40
      end
      object PopupMenu1: TPopupMenu
        Left = 168
        Top = 80
        object N1: TMenuItem
          Caption = #21069#37096#23637#24320
          OnClick = N1Click
        end
        object N2: TMenuItem
          Caption = #38065#37096#25910#32553
          OnClick = N2Click
        end
        object N3: TMenuItem
          Caption = '-'
        end
        object N4: TMenuItem
          Caption = #22686#21152#33410#28857
          OnClick = N4Click
        end
        object N5: TMenuItem
          Caption = #21024#38500#33410#28857
          OnClick = N5Click
        end
        object N6: TMenuItem
          Caption = '-'
        end
        object N7: TMenuItem
          Caption = #36864#20986
        end
      end
      object ADOConnection1: TADOConnection
        Connected = True
        ConnectionString = 
          'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=E:\db' +
          '1.mdb;Mode=Share Deny None;Extended Properties="";Persist Securi' +
          'ty Info=False;Jet OLEDB:System database="";Jet OLEDB:Registry Pa' +
          'th="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet' +
          ' OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops' +
          '=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database P' +
          'assword="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encr' +
          'ypt Database=False;Jet OLEDB:Don'#39't Copy Locale on Compact=False;' +
          'Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=Fal' +
          'se'
        LoginPrompt = False
        Mode = cmShareDenyNone
        Provider = 'Microsoft.Jet.OLEDB.4.0'
        Left = 104
        Top = 24
      end
    end
      

  5.   

    TO: delphiseabird(沙鸥)
    我自己尝试着作了一个,但在运行中出现错误,有谁能帮我改一下呀!
    请留下E-Mail址,我把源代码发给你,谢谢。
      

  6.   

    第一个是.pas 第二个时.dfm 用到一个数据表 DEPART2
                   字段为:DEPARTNAME,DEPARTNO,PREDEPART
    你可以Access建立一个数据库然后用OLE 连接由于编码用的是树的节点的个数,所以最好别用删除,你可以自己定义一个编码方式然后编码
    存到数据库中
      

  7.   

    TO: zhanghw20030303(冰山一角)
    我给发给你的源代码的数据库是用dbisam4.05作的,你现在是用Access的数据库,
    我要的是用dbisam4.05作的,你可以帮我改一下我发给你的源代码里面的错误吗?
    谢谢。
      

  8.   

    TO:xiaosq2000(书虫) yanyouwei(yyw)你们的邮箱我发不过去,总是系统退信。
    请在此下载源码吧
    JnOnlie.meibu.com/TREEVIEW.rar改完的话,发E-Mail给我吧([email protected]
      

  9.   

    TreeView的数据使用咋有问题?
    type
      PData=^MyData;
      MyData=Record
        id:string;//integer;
        name:string;
        AlLoad:boolean;
      end;
    增加数据:
          New(NData);
          NData.id:=tqr.FieldByName('id').AsString;//.AsInteger;
          Ndata.name:=tqr.FieldByName('Name').AsString;
          Ndata.AlLoad:=false;
          tmpNode:=Tree.Items.AddChildObject(root,tqr.FieldByName ('Name').AsString,Ndata); 
          tmpNode.Text:=tqr.FieldByName('Name').AsString;
    使用:点击TreeView时的处理
    procedure TFrmMain.TVDirClick(Sender: TObject);
    var
    tmpNode:TTreeNode;begin
      tmpNode:=TVDir.Selected;
      if tmpNode=nil then exit;
      if PData(tmpNode.Data)^.AlLoad then exit;
                       //  tqr.FieldByName('id').AsString  LoadSubTreeCon(PData(tmpNode.Data)^.id,tmpNode);
    end;提示出错!why??????
      

  10.   

    使用New不需要用Dispose释放??
      

  11.   

    [email protected],可否把源码也发我一份。
      

  12.   

    第一个错误已经解决,是因为没有判断是否为nil在TreeView中使用New不需要用Dispose释放??
      

  13.   

    type
      PMyRecord = ^MyRecord;
      MyRecord = record
               ID : integer;
               Name:string;
               ParentID : integer;
    end;//end of recordprocedure pCreateTreeView(Node:TTreeNode;ParentID:integer;
              AtvnViewNode:TTreeView;AadoConnection:TADOConnection;AstrSQL:String;
              AImageIndex,ASelectedIndex:Integer;AstrFieldName:String);
    var
      tmpNode : TTreeNode;
      ADOTree : TADOQuery;
      p : PMyRecord;
    begin
      ADOTree := TADOQuery.Create(application);
      ADOTree.Connection := AadoConnection;
      ADOTree.close;
      ADOTree.SQL.clear;
     //SELECT lx_bh, lx_mc,lx_parentID FROM ESMDqxlx_1  ADOTree.SQL.Text := AstrSQL+' where '+AstrFieldName +' ='+inttostr(ParentID);
      ADOTree.open;
      if ADOTree.recordcount > 0  then
      begin
        ADOTree.First;
        while not ADOTree.Eof do
        begin
          new(p);
          p.ID := ADOTree.Fields[0].AsInteger;
          p.name :=ADOTree.Fields[1].AsString;
          p.ParentID := ADOTree.Fields[2].AsInteger;
          tmpNode := AtvnViewNode.Items.AddChildObject(Node,p.name,p);      if  AtvnViewNode.Images<>nil then  //有图标时设置图标
           begin
             tmpNode.SelectedIndex := ASelectedIndex; //选中时图标
             tmpNode.ImageIndex := AImageIndex;       //没选中时图标
           end;  {== End If ==}      pCreateTreeView(tmpNode,ADOTree.Fields[0].AsInteger,AtvnViewNode,AadoConnection,AstrSQL,AImageIndex,ASelectedIndex,AstrFieldName);
          ADOTree.next;
          //dispose(p);//一定要去掉这条语句,不然的话,Treeview中的Data也被dispose掉了。
        end;
      end;
      ADOTree.Free;
    end;
      

  14.   

    Treeview 的部分用法
    http://expert.csdn.net/Expert/topic/2946/2946450.xml?temp=.8297998
      

  15.   

    TO: fcjg(★飘来飘去!★(一天18小时在线))
    我现用的是数据库是DBISAM,不是ADO的(如果是ADO的话早就没问题了)
    能我看看源代码里的错误怎么改吗?
    JnOnlie.meibu.com/TREEVIEW.rar
      

  16.   

    修改你的源代码:
    1.我在调试时,要我给出,一些BISAM 的部分*.pas文件,所以我在delphi的 project --> Options -->directories/conditionals引入了他们,你注意看看 
    2.是这个出错提示吗?
    Access violation at address 0054DA9C in module 'Project1.exe'. Read of address 00000058.
    这个出错提示是这个引起的
    LSTDM.QryTmp.SQL.Add('select * from tb1');  //出错 
    原因在 LSTDM.QryTmp 没有初始化,虽然你在 LSBMTreeDMdata.pas单元中已经配置了,但是,还有个问题:在Project1.dpr中.
    原来的
     program Project1;uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1},
      LSBMTreeDMdata in 'LSBMTreeDMdata.pas' {LSTDM: TDataModule};{$R *.res}begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.CreateForm(TLSTDM, LSTDM);<<===问题在此,产生
      Application.Run;
    end.
      

  17.   

    Application,初始化LSBMTreeDMdata.pas单元的对象比你要调用该单元的对象要晚,所以出错了.
    修改办法:只需要调换初始化的位置:
     begin
      Application.Initialize;
      Application.CreateForm(TLSTDM, LSTDM);<<=== 
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
    在我这里调试通过.
      

  18.   

    To:
    回复人: fcjg(★飘来飘去!★(一天18小时在线)) 
    你的这段代码看了,现在有一个问题:
    如果这个treeview有几万(甚至十几万个)个node,那么
    在每个节点都使用了data指针:
          new(p);
          p.ID := ADOTree.Fields[0].AsInteger;
          p.name :=ADOTree.Fields[1].AsString;
          p.ParentID := ADOTree.Fields[2].AsInteger;
          tmpNode := AtvnViewNode.Items.AddChildObject(Node,p.name,p);
    由于p的使用,计算机内存是否会溢出而崩溃?
    我观察过,只要node增加,程序所需要的内存就不断增加~~~不知道其他各位是否注意了这个问题?还是这么做有问题?????