以前在论坛中有看到大侠们讨论的用treeview显示一张表内的树型结构。
但是我现在必须得做成多张表!如下:
表1:
____________________________
|_Index_Id_A_|_Field_Name_A_|
|_______1____|__A班_________|
|_______2____|__B班_________|表2:
_____________________________________________
|__Index_Id_B_|_Index_Id_A___|__Field_Name__|
|_______1_____|____2_________|____小王______|
|_______2_____|____1_________|____小名______|
|_______3_____|____2_________|___小朱_______|
|_______4_____|____1_________|____小强______|结果:
   +--A班
   |  |__小名 
     |   |__小强
   |
     +----B班
      |__小王
         |__小朱
怎么办呢?

解决方案 »

  1.   

    参考我的联系人名单的树形代码:
    type
      PMyDataRec = ^TMyDataRec;
      TMyDataRec = record
        ID: string;
        IDP: string;
        GroupID: string;
        Mobile: string;
      end;const
      IMGMan = 0;
      IMGWoman = 1;
      IMGUnknown = 2;
    procedure TDM.AddContactInfoToTreeView(ATreeView: TTreeView);  procedure ClearTreeViewItems(ATreeView: TTreeView);
      var
        Node: TTreeNode;
      begin
        Node := ATreeView.Items.GetFirstNode;
        while Node <> nil do
        begin
          if Node.Data <> nil then
          begin
            Dispose(Node.Data);
          end;
          Node := Node.GetNext;
        end;
        ATreeView.Items.Clear;
      end;var
      GroupID: string;
      MyDataRec: PMyDataRec;
      Node1, Node2, Node3, Node4: TTreeNode;
    begin
      ClearTreeViewItems(ATreeView);
      New(MyDataRec);
      Node1 := ATreeView.Items.Add(nil, '联系人');
      MyDataRec.ID := '';
      MyDataRec.IDP := '';
      Node1.Data := MyDataRec;
      Node1.ImageIndex := IMGroot;
      Node1.SelectedIndex := IMGroot;
      with ADOQAddContactInfoToTreeView do
      begin
        ADOQGroup.Close;
        ADOQGroup.SQL.Clear;
        ADOQGroup.SQL.Add('Select * from Group1');
        ADOQGroup.Open;
        while not ADOQGroup.Eof do
        begin
          New(MyDataRec);
          GroupID := ADOQGroup.FieldByName('GroupID').AsString;
          MyDataRec.ID := GroupID;
          MyDataRec.GroupID := GroupID;
          Node2 := ATreeView.Items.AddChildObject(Node1, ADOQGroup.FieldValues['Name'], MyDataRec);
          if not Node1.Expanded then
            Node1.Expanded := True;
          Node2.ImageIndex := IMGGROUP;
          Node2.SelectedIndex := IMGGROUP;
          ADOQCompany.Close;
          ADOQCompany.SQL.Clear;
          ADOQCompany.SQL.Add('Select distinct Company.ID as cid, Company.Name as cname from Company, UClient');
          ADOQCompany.SQL.Add('Where (UClient.IDP Like Company.ID + ''%'') and (UClient.GroupID = :GroupID)');
          ADOQCompany.Parameters.ParamByName('GroupID').Value := GroupID;
          ADOQCompany.Open;
          while not ADOQCompany.Eof do
          begin
            New(MyDataRec);
            MyDataRec.ID := ADOQCompany.FieldByName('cid').Value;
            Node3 := ATreeView.Items.AddChildObject(Node2, ADOQCompany.FieldValues['CName'], MyDataRec);
            if not Node2.Expanded then
              Node2.Expanded := True;
            Node3.ImageIndex := IMGCONTACT;
            Node3.SelectedIndex := IMGCONTACT;
            ADOQPerson.Close;
            ADOQPerson.SQL.Clear;
            ADOQPerson.SQL.Add('select distinct * from UClient');
            ADOQPerson.SQL.Add('where (IDP Like :cid + ''%'') and (GroupID = :GroupID)');
            ADOQPerson.Parameters.ParamByName('CID').Value := MyDataRec.ID;
            ADOQPerson.Parameters.ParamByName('GroupID').Value := GroupID;
            ADOQPerson.Open;
            while not ADOQPerson.Eof do
            begin
              New(MyDataRec);
              MyDataRec.ID := ADOQPerson.FieldValues['ID'];
              MyDataRec.IDP := ADOQPerson.FieldValues['IDP'];
              MyDataRec.Mobile := ADOQPerson.FieldValues['Mobile'];
              Node4 := ATreeView.Items.AddChildObject(Node3, ADOQPerson.FieldValues['Name'], MyDataRec);
              case ADOQPerson.FieldByName('Sex').AsInteger of
                1:
                  begin
                    Node4.ImageIndex := IMGMan;
                    Node4.SelectedIndex := IMGMan;
                  end;
                2:
                  begin
                    Node4.ImageIndex := IMGWoman;
                    Node4.SelectedIndex := IMGWoman;
                  end;
                else
                  begin
                    Node4.ImageIndex := IMGUnknown;
                    Node4.SelectedIndex := IMGUnknown;
                  end;
              end;
              ADOQPerson.Next;
            end;
            ADOQCompany.Next;
          end;
          ADOQGroup.Next;
        end;
        Close;
      end;
    end;
      

  2.   

    可以帮忙加上注释吗?我自己也在做,是用的ttreeview   ttable  datasource 来做的,因为表比较多,我都有些晕了~  :(
      

  3.   

    postren小虫哥哥你不要抛弃我啊:~
    你的程序我看得稀里糊涂的
    我也想用SQL来完成,可是我用的是delphi自带的数据库Desktop database
    好象这样的数据库不支持SQL的查询操作是吗?
    我的多表都不是建在一个数据库里,而是很多独立的表文件……
    还有救吗?……
      

  4.   

    //好象这样的数据库不支持SQL的查询操作是吗?
    没用过Desktop database ,应该不会有不支持SQL的数据库吧也可参考一下这个
     with AdoQuery1 do
        begin
          AdoQuery1.close;
          AdoQuery1.sql.Clear;
          AdoQuery1.sql.Add('select WX_MSCMC from WX_MSCXX where WX_SSDS=:SSDS order by wx_mscmc');
          AdoQuery1.Parameters.ParamByName('SSDS').Value:=Ls_ssds;
          AdoQuery1.open;
          AdoQuery1.first;
          while not AdoQuery1.eof do
            begin
              NewNode[MS]:=TV.Items.AddChild(Nodex,AdoQuery1.FieldByName('WX_MSCMC').AsString);
              NewNode[MS].ImageIndex:=1;
              begin
              with AdoQuery2 do
                begin
                  AdoQuery2.close;
                  AdoQuery2.sql.Clear;
                  AdoQuery2.sql.Add('select WX_BSCMC from WX_BSCXX where WX_SSMSC=:SSMSC order by wx_bscmc');
                  AdoQuery2.Parameters.ParamByName('SSMSC').Value:=AdoQuery1.FieldByName('WX_MSCMC').AsString;
                  AdoQuery2.Open;
                  AdoQuery2.First;
                  while not AdoQuery2.eof do
                  begin
                    BscNode[BS]:=TV.Items.AddChild(NewNode[MS],AdoQuery2.FieldByName('WX_BSCMC').AsString);
                    BscNode[BS].ImageIndex:=1;
                    begin
                    with AdoQuery3 do
                      begin
                        AdoQuery3.close;
                        AdoQuery3.sql.Clear;
                        AdoQuery3.sql.Add('select WX_JZMC from WX_JZXX where WX_GSBSC=:GSBSC order by wx_jzmc');
                        AdoQuery3.Parameters.ParamByName('GSBSC').Value:=AdoQuery2.FieldByName('WX_BSCMC').AsString;
                        AdoQuery3.Open;
                        AdoQuery3.First;
                        while not AdoQuery3.eof do
                        begin
                          BtsNode[BT]:=TV.Items.AddChild(BscNode[BS],AdoQuery3.FieldByName('WX_JZMC').AsString);
                          BtsNode[BT].ImageIndex:=1;
                          begin
                          with AdoQuery4 do
                            begin
                              AdoQuery4.close;
                              AdoQuery4.sql.Clear;
                              AdoQuery4.sql.Add('select WX_CELLID from WX_JZXQXX WHERE WX_SSBTS=:LS_SSBTS order by wx_cellid');
                              AdoQuery4.Parameters.ParamByName('LS_SSBTS').Value:=AdoQuery3.FieldByName('WX_JZMC').AsString;
                              AdoQuery4.Open;
                              AdoQuery4.First;
                              while not AdoQuery4.eof do
                              begin
                                CellNode[CE]:=TV.Items.AddChild(BtsNode[BT],AdoQuery4.FieldByName('WX_CELLID').AsString);
                                CellNode[CE].ImageIndex:=1;
                                AdoQuery4.Next;
                                //CE:=CE+1;
                              end;
                            end;
                          end;
                          AdoQuery3.Next;
                          BT:=BT+1;
                        end;
                      end;
                    end;
                    AdoQuery2.next;
                    BS:=BS+1;
                  end;
                end;
              end;
              AdoQuery1.next;
              MS:=MS+1;
            end;
        end;
      

  5.   

    不过可以组合查询,然后填充到树,速度更快
    type
      Pstr=^string;procedure TBS04F.TreeNew(thetree: TTreeview;thedata: TDataSet);
    var
      p: Pstr;
      plevel: integer;
      tempnode: array[0..4] of TTreeNode;
    begin
      thedata.Open;
      thetree.Items.Clear;
      thetree.Items.BeginUpdate;
      new(p);
      p^ := '000000000';
      thetree.TopItem := thetree.Items.AddObjectFirst(nil,'区域设置',p);
      while not thedata.Eof do
        begin
          plevel := thedata['FLAG']-1;
          new(p);
          p^ := thedata['ARNO'] + inttostr(thedata['FLAG']);
          if plevel = 0 then tempnode[plevel] := thetree.TopItem;
          tempnode[plevel+1] := thetree.Items.AddChildObject(tempnode[plevel],thedata['NAME'] +'('+thedata['ARNO']+')',p);
          thedata.Next;
        end;
      thetree.Items.EndUpdate;
      thetree.TopItem.Expand(false);
      thedata.Close;
    end;
      

  6.   

    参考我的联系人名单的树形代码:
    type
      PMyDataRec = ^TMyDataRec;   //定义记录指针, 以便在树结点的Data指针域保存
      TMyDataRec = record
        ID: string;
        IDP: string;
        GroupID: string;
        Mobile: string;
      end;const
      IMGMan = 0;
      IMGWoman = 1;
      IMGUnknown = 2;
    procedure TDM.AddContactInfoToTreeView(ATreeView: TTreeView);  procedure ClearTreeViewItems(ATreeView: TTreeView);
      var                   //清空树的结点, 重新初始化树, 由于使用了Data指针域,因此
                            //不能直接用 ATreeView.Items.Clear;清空, 还要把Data指针
                            //释放掉, 否则引起内存泄露
        Node: TTreeNode;
      begin
        Node := ATreeView.Items.GetFirstNode; //获得树的第一个结点
        while Node <> nil do
        begin
          if Node.Data <> nil then //可能并不是所有的Data都放了指针, 先检查
                                   //是否为nil, 不为nil才能Dispose
          begin
            Dispose(Node.Data);
          end;
          Node := Node.GetNext;  //获得树的下一个结点
        end;
        ATreeView.Items.Clear;  // 此时树中的Data指针域已经全部释放, 可以清空结点了
                                // 必须放在清空指针的后面
      end;var
      GroupID: string;
      MyDataRec: PMyDataRec;
      Node1, Node2, Node3, Node4: TTreeNode;
    begin
      ClearTreeViewItems(ATreeView);     //清空树
      New(MyDataRec);                    //分配一个记录指针
      Node1 := ATreeView.Items.Add(nil, '联系人'); //增加第一个结点
      MyDataRec.ID := '';              //第一个结点中的数据为空
      MyDataRec.IDP := '';
      Node1.Data := MyDataRec;         //把记录指针保存到第一个结点的Data中
      Node1.ImageIndex := IMGroot;     //给第一个结点指定图标
      Node1.SelectedIndex := IMGroot;  //给第一个结点指定选中时的图标, 在此为同一图标
      with ADOQAddContactInfoToTreeView do
      begin
        ADOQGroup.Close;
        ADOQGroup.SQL.Clear;
        ADOQGroup.SQL.Add('Select * from Group1');  //查找组名, 按组分类
        ADOQGroup.Open;
        while not ADOQGroup.Eof do
        begin
          New(MyDataRec);        //分配一个指针
          GroupID := ADOQGroup.FieldByName('GroupID').AsString;  //获得组号
          MyDataRec.ID := GroupID;                             //把组号保存到指针中
          MyDataRec.GroupID := GroupID;       //重复保存是为了方便配合我的其他程序      //添加一个子结点(带Data指针的), 用AddChild不带指针,显示为组名
          Node2 := ATreeView.Items.AddChildObject(Node1, ADOQGroup.FieldValues['Name'], MyDataRec);  
          if not Node1.Expanded then  //新添加的结点是没有展开的, 展开该结点
            Node1.Expanded := True;
          Node2.ImageIndex := IMGGROUP;        //设置图标
          Node2.SelectedIndex := IMGGROUP;    {以下类似, 就不一一注释了}
          ADOQCompany.Close;
          ADOQCompany.SQL.Clear;
          ADOQCompany.SQL.Add('Select distinct Company.ID as cid, Company.Name as cname from Company, UClient');
          ADOQCompany.SQL.Add('Where (UClient.IDP Like Company.ID + ''%'') and (UClient.GroupID = :GroupID)');
          ADOQCompany.Parameters.ParamByName('GroupID').Value := GroupID;
          ADOQCompany.Open;
          while not ADOQCompany.Eof do
          begin
            New(MyDataRec);
            MyDataRec.ID := ADOQCompany.FieldByName('cid').Value;
            Node3 := ATreeView.Items.AddChildObject(Node2, ADOQCompany.FieldValues['CName'], MyDataRec);
            if not Node2.Expanded then
              Node2.Expanded := True;
            Node3.ImageIndex := IMGCONTACT;
            Node3.SelectedIndex := IMGCONTACT;
            ADOQPerson.Close;
            ADOQPerson.SQL.Clear;
            ADOQPerson.SQL.Add('select distinct * from UClient');
            ADOQPerson.SQL.Add('where (IDP Like :cid + ''%'') and (GroupID = :GroupID)');
            ADOQPerson.Parameters.ParamByName('CID').Value := MyDataRec.ID;
            ADOQPerson.Parameters.ParamByName('GroupID').Value := GroupID;
            ADOQPerson.Open;
            while not ADOQPerson.Eof do
            begin
              New(MyDataRec);
              MyDataRec.ID := ADOQPerson.FieldValues['ID'];
              MyDataRec.IDP := ADOQPerson.FieldValues['IDP'];
              MyDataRec.Mobile := ADOQPerson.FieldValues['Mobile'];
              Node4 := ATreeView.Items.AddChildObject(Node3, ADOQPerson.FieldValues['Name'], MyDataRec);
              case ADOQPerson.FieldByName('Sex').AsInteger of
                1:
                  begin
                    Node4.ImageIndex := IMGMan;
                    Node4.SelectedIndex := IMGMan;
                  end;
                2:
                  begin
                    Node4.ImageIndex := IMGWoman;
                    Node4.SelectedIndex := IMGWoman;
                  end;
                else
                  begin
                    Node4.ImageIndex := IMGUnknown;
                    Node4.SelectedIndex := IMGUnknown;
                  end;
              end;
              ADOQPerson.Next;
            end;
            ADOQCompany.Next;
          end;
          ADOQGroup.Next;
        end;
        Close;
      end;
    end;
      

  7.   

    Paradox也是支持SQL的啊, 怎么可能不支持呢?! 呵呵
      

  8.   

    Delphi中用了New()不用Dispose了吗?是编译器自己会去Dispose的吗?
      

  9.   

    这样会不会很慢啊,Delphi中有没有类似C++ 中STL 里的Map 容器啊?