怎样根据数据库的内容动态部门树

dulei115 2003-09-20 10:11:43
数据库结构:
部门ID 部门名称 上级部门ID
1 总部门 -1
2 部门1 1
3 部门2 1
4 部门3 1
5 分部门1 2
6 分部门2 2
7 分部门3 2
8 子部门1 5
9 子部门1 5
。。。。。。。。。。。
我想用递规的方法生成Treeview,程序如下:
PROCEDURE newtreeview(部门ID,部门名称)
Begin
//Treeview1。。。添加部门名称;
//Treeview1。。。添加附带数据部门ID
ADOQuery1.close;
ADOQuery1.SQL.clear;
ADOQuery1.SQL.Text:=select * from 部门表 where 上级部门ID='+inttostr(部门ID)
ADOQuery1.open;
If ADOQuery1..recordcount>0 then
Begin
//Treeview1。。。准备添加子节点
ADOQuery1.First;
For i:=o to ADOQuery1.recordcount do
Begin
Newtreeview(ADOQuery1.FieldByName(‘ID’),
ADOQuery1.FieldByName(‘部门名称’))
ADOQuery1.next;
End;
End;
//Treeview如果有上层节点,则回到上层节点
End;
要求:当输入(1,总部门)时生成树为
总部门
部门1
分部门1
子部门1
子部门2
分部门2
分部门3
部门2
部门3
。。。
当输入(2,部门1)时生成树为
部门1
分部门1
子部门1
子部门2
分部门2
分部门3
(即生成自己部门和下属部门,且各名称附带数据为其ID号)
因为对Treeview不太熟悉,所以请高手帮忙改一下程序,
如果有更好的方法更好。


...全文
69 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhengtao1980 2004-03-22
  • 打赏
  • 举报
回复
我试了一下,如果递归调用,查询结果ADOQUERY1.RECORDCOUNT=0时怎么办,也就是说如果一个节点没有子节点了,IF以后的语句怎么能够得到执行呢,结果只能输出第一个分支啊
roczhao 2003-10-18
  • 打赏
  • 举报
回复
好好好,值得学习
webfly 2003-09-27
  • 打赏
  • 举报
回复
nil是什么意思?是不是添加到根上?
dulei115 2003-09-22
  • 打赏
  • 举报
回复
本贴正确答案:hmzgz81(哩翱)
PROCEDURE TForm1.newtreeview(Node:TTreeNode;ID,Name:String);
var
tmpNode : TTreeNode;
ADOquery1 : TADOQuery;
Begin
tmpNode := TreeView1.Items.AddChild(Node,Name);
ADOQuery1 := TADOQuery.Create(self);
ADOQuery1.Connection := ADOConnection1;
ADOQuery1.close;
ADOQuery1.SQL.clear;
ADOQuery1.SQL.Text := 'select * from 部门表 where 上级部门ID='+ID;
ADOQuery1.open;
If ADOQuery1.recordcount > 0 then
Begin
ADOQuery1.First;
while not ADOQuery1.Eof do
Begin
Newtreeview(tmpNode,ADOQuery1.FieldByName('ID').AsString,
ADOQuery1.FieldByName('部门名称').AsString);
ADOQuery1.next;
End;
End;
End;
或者:zswangII(伴水清清)(职业清洁工)
function DataSetToTreeNode(mDataSet: TDataSet;
mFieldNameParent: string; //父节点标识字段名
mFieldNameTreeText: string; //节点文本字段名
mFieldNameTreeId: string; //节点标识字段名
mTreeView: TTreeView; mTreeNode: TTreeNode;
mParentText: string): Boolean;
var
vTreeNode: TTreeNode;
vFieldValues: Variant;
vFieldNames: string;
begin
Result := False;
if not Assigned(mDataSet) then Exit;
if not Assigned(mTreeView) then Exit;
if not mDataSet.Active then Exit;
vFieldNames := Format('%s;%s;%s',
[mFieldNameParent, mFieldNameTreeText, mFieldNameTreeId]);
mDataSet.Filtered := False;
mDataSet.Filter := Format('%s=%s', [mFieldNameParent, QuotedStr(mParentText)]);
mDataSet.Filtered := True;
if mDataSet.RecordCount = 0 then Exit;
mDataSet.First;
while not mDataSet.Eof do begin
vTreeNode := mTreeView.Items.AddChild(mTreeNode,
mDataSet.FieldByName(mFieldNameTreeText).AsString);
vFieldValues := mDataSet[vFieldNames];
DataSetToTreeNode(mDataSet, mFieldNameParent, mFieldNameTreeText,
mFieldNameTreeId, mTreeView, vTreeNode,
mDataSet.FieldByName(mFieldNameTreeId).AsString);
///////Begin 恢复位置
mDataSet.Filtered := False;
mDataSet.Filter := Format('%s=%s', [mFieldNameParent, QuotedStr(mParentText)]);
mDataSet.Filtered := True;
mDataSet.Locate(vFieldNames, vFieldValues, []);
///////End 恢复位置
mDataSet.Next;
end;
Result := True;
end;
//当前如下调用~~
begin
TreeView1.Items.Clear;
DataSetToTreeNode(Table1, '上级部门ID', '部门名称', '部门ID',
TreeView1, nil, '-1');
ADOTable1.Filter := '';
end;
dulei115 2003-09-22
  • 打赏
  • 举报
回复
谢谢! zswangII(伴水清清)(职业清洁工)
dulei115 2003-09-20
  • 打赏
  • 举报
回复
终于可以生成树了,谢谢hmzgz81(哩翱)
不过有个问题:节点从一开始就在第二层,怎样使它到第一层
还有:怎样使树展开一点(比如:展开第一层;全部展开)
hmzgz81 2003-09-20
  • 打赏
  • 举报
回复
PROCEDURE TForm1.newtreeview(Node:TTreeNode;ID,Name:String);
var
tmpNode : TTreeNode;
ADOquery1 : TADOQuery;
Begin
//Treeview1。。。添加部门名称;
//Treeview1。。。添加附带数据部门ID
tmpNode := TreeView1.Items.AddChild(Node,Name);
ADOQuery1 := TADOQuery.Create(self);
ADOQuery1.Connection := ADOConnection1;
ADOQuery1.close;
ADOQuery1.SQL.clear;
ADOQuery1.SQL.Text := 'select * from 部门表 where 上级部门ID='+ID;
ADOQuery1.open;
If ADOQuery1.recordcount > 0 then
Begin
//Treeview1。。。准备添加子节点
ADOQuery1.First;
while not ADOQuery1.Eof do
Begin
Newtreeview(tmpNode,ADOQuery1.FieldByName('ID').AsString,
ADOQuery1.FieldByName('部门名称').AsString);
ADOQuery1.next;
End;
End;
End;
dulei115 2003-09-20
  • 打赏
  • 举报
回复
PROCEDURE TForm1.newtreeview(Node:TTreeNode;ID,Name:String);
var
tmpNode : TTreeNode;
ADOquery1 : TADOQuery;
Begin
//Treeview1。。。添加部门名称;
//Treeview1。。。添加附带数据部门ID
tmpNode := TreeView1.Items.Add(Node,Name);
ADOQuery1 := TADOQuery.Create(self);
ADOQuery1.Connection := ADOConnection1;
ADOQuery1.close;
ADOQuery1.SQL.clear;
ADOQuery1.SQL.Text := 'select * from 部门表 where 上级部门ID='+ID;
ADOQuery1.open;
If ADOQuery1.recordcount > 0 then
Begin
//Treeview1。。。准备添加子节点
tmpNode := tmpNode.getFirstChild;
//////////////////////////////////////////
现在的程序能生成树了,可是都在第一层,哪位懂Treeview控件的帮我改一下,我想应该是上面的一句的问题。谢谢了。
/////////////////////////////////////////
ADOQuery1.First;
while not ADOQuery1.Eof do
Begin
Newtreeview(tmpNode,ADOQuery1.FieldByName('ID').AsString,
ADOQuery1.FieldByName('部门名称').AsString);
ADOQuery1.next;
End;
End;
if tmpNode <> Treeview1.TopItem then
tmpNode := tmpNode.Parent;
//Treeview如果有上层节点,则回到上层节点
End;
zhboy 2003-09-20
  • 打赏
  • 举报
回复
兄弟,最好的方法是用递归,但是AdoQuery不能这样用,这样不会出正确结果
dulei115 2003-09-20
  • 打赏
  • 举报
回复
还是没出来,请高手指点。
uusong 2003-09-20
  • 打赏
  • 举报
回复
最好还是用递归了!
tiexinliu 2003-09-20
  • 打赏
  • 举报
回复
使用递归.每次创建当前部门的所有下级部门,包括下级的下级
procedure Tcustomer_treefrm.CreateSubTree_all(FNodeName: string; Node: TTreeNode = nil);
var
mLocalName: string;
TreeNode: TTreeNode;
Ads_Tmp: Tclientdataset;
p:pstr;
begin
ADS_Tmp := Tclientdataset.Create(Self);
ADS_Tmp.RemoteServer:=mainfrm.SocketConnection1;
ADS_Tmp.ProviderName:='datasetprovider3';
with ADS_Tmp do
begin
Close;
CommandText :='QUERY_customer_By_Parent_No_sec '+''''+FNodeName+''''+','+''''+userid+'''';;
Open;
First;
while not Eof do
begin
mLocalName := FieldbyName('ID').Asstring;
new(p);
p^:=mlocalName;
TreeNode :=self.tv_zb.Items.AddChildObject(Node, FieldByName('Name').AsString,p);
CreateSubTree_all(mLocalName, TreeNode);
Next;
end;
end;
Ads_Tmp.Free;
end;
PrgmLover 2003-09-20
  • 打赏
  • 举报
回复
PROCEDURE TForm1.newtreeview(Node:TTreeNode;ID,Name:String);
var
tmpNode: TTreeNode;
P: Pointer;
Begin
//Treeview1。。。添加部门名称;
//Treeview1。。。添加附带数据部门ID
tmpNode:=TreeView1.Items.Add(Node,Name);
ADOQuery1.close;
ADOQuery1.SQL.clear;
ADOQuery1.SQL.Text:=select * from 部门表 where 上级部门ID='+inttostr(部门ID)
ADOQuery1.open;
If ADOQuery1..recordcount>0 then
Begin
//Treeview1。。。准备添加子节点
ADOQuery1.First;
For i:=o to ADOQuery1.recordcount do
Begin
Newtreeview(tmpNode,ADOQuery1.FieldByName(‘ID’),
ADOQuery1.FieldByName(‘部门名称’))
ADOQuery1.next;
End;
End;
//Treeview如果有上层节点,则回到上层节点
End;

上边是按照搂主的思路添加的,建议使用TfctreeView. 建树的速度要快一些,并且存放附加字符串比较简便
雨后阳光2000 2003-09-20
  • 打赏
  • 举报
回复
仅供参考
雨后阳光2000 2003-09-20
  • 打赏
  • 举报
回复
procedure TFrameTree.LoadTree(treeDB:TDBDataSet);//初始化树
//initial tree when main form create
var
curID,nodeTxt:string;
level,chindex,cnode,num:integer;
mynode:array[0..6] of TTreenode;
begin
//初始化变量
Screen.Cursor:=crHourGlass;
tree.Enabled:=True;
tree.Items.Clear;
level:=0 ;
num:=1;
tree.items.clear;
//设置根节点
mynode[level]:=tree.items.add(Tree.Topitem,cTreeRootTxt);
mynode[level].ImageIndex:=1;
//遍历数据表,利用编码字段记录排序规律,依次添加树节点
with treeDB do
begin
try
if not Active then
open;
first;
while not Eof do
begin
curID:=trim(FieldByName('dwbm').AsString);
nodeTxt:=curID+'-'+trim(FieldByName('dwqc').AsString);
level:=GetNodeLevel(cTreeCodeFormat,curID);
//这里返回代码的层次数
if level>0 then
begin
//增加下一节点时,用添加子节点的方法可轻松实现节点间的层次关系。
//注意:这里的父节点是用当前节点的上一级节点mycode[level-1]
mynode[level]:=tree.items.addchild(mynode[level-1],nodeTxt);
if level>4 then
mynode[level].ImageIndex:=3
else
mynode[level].ImageIndex:=1;
// mynode[level].tag:=curID;
end;
next;
end;
finally;
close;
End;
mynode[0].expand(False);
Screen.Cursor:=crDefault;
end;
end;

function TFrameTree.GetNodeLevel(sFormat,sCode:string):integer;
var
i,level,iLen:integer;
begin
level:=-1 ;
iLen:=0;
if (sFormat<>'') and (sCode<>'') then
for i:=1 to Length(sFormat) do
begin
iLen:=iLen+StrToInt(sFormat[i]);
if Length(sCode)=iLen then
begin
level:=i;
break;
end;
end;
result:=level;
end;
dulei115 2003-09-20
  • 打赏
  • 举报
回复
自己改正一下:For i:=o to ADOQuery1.recordcount do
改为:For i:=1 to ADOQuery1.recordcount do
说明一下:本人知道可以用while not ADOQuery1.EOF do
所以请各位把重点放在Treeview的生成上面,不要太在意我写的语法。谢谢了。
zswangII 2003-09-20
  • 打赏
  • 举报
回复
begin
TreeView1.Items.Clear;
DataSetToTreeNode(ADOTable1, '上级部门ID', '部门名称', '部门ID',
TreeView1, nil, '-1');
ADOTable1.Filter := ''; //加上~~
end;
dulei115 2003-09-20
  • 打赏
  • 举报
回复
问题基本解决,随时准备结贴。
dulei115 2003-09-20
  • 打赏
  • 举报
回复
to zswangII(伴水清清)(职业清洁工)
好像把数据集都改了,ADOTable1对应的DBGrid1就显示一条记录了:1 总部门 -1
怎么回事?
dulei115 2003-09-20
  • 打赏
  • 举报
回复
to zswangII(伴水清清)(职业清洁工)
还没,一定会测的,如果有问题,我发个消息给你。
加载更多回复(11)

5,392

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧