怎样实现数据的TreeView按某个列 ,级别排列(100分)

  • 主题发起人 主题发起人 delphifans_hx
  • 开始时间 开始时间
D

delphifans_hx

Unregistered / Unconfirmed
GUEST, unregistred user!
000000 //树的根接点 0级
010000 //1级
020000 //1
030000 //1
030100 //2
030101 //3
030102 //3
030103 //3
030200 //2
040000 //1
 
使用队列呀
用一个TList来做
 
你是不是展開BOM啊
 
我做的時候前面加空格
 
你是不是想对TreeView 进行排序?
 
说明白点,到底是直接对数据操作‘类treeview’排列,还是在treeview上进行等级排列,
到底和treeview有没有关系?
 
也就是说数据表为
ID OtherField1 OtherField2
000000 一大公司
010000 市场部
000100 第一市场分部
000101 第一分部第一子部
000102 第一分部第二子部
020000 人事部
030000 财务部
040000 学术部


然后将这表的按ID的级别排成树行置于TreeView里面
 
是不是按你前面的ID,把这些东西放到 TreeView 里面?
按ID分级
--+ 一大公司
+-- 市场部
+-- 第一市场分部
+-- 第一分部第一子部
+-- 第一分部第二子部
+-- 人事部
如此而已 ???


 
用一个递归就可以了。
先增加第一即节点,安两位一级,00的保留两为,其他的去掉末尾的零作为第一即code
然后这样看思路何不和你的要求:
createnode(anode : treenode;code:string)//增加儿子
var
tmpnode : ttreenode;
idstr,textstr:string;
begin
sql语句:‘select * from table where id like ''’+code+'%''' and id <>'''+code+'''';
while not eof do
begin
idstr := fieldbyname('id').asstring;
textstr := fieldbyname('text').asstring;
tmpnode :=treeview.items.addchild(node,textstr);
// idstr去末尾的令
createnode(tmpnode,idstr)
next;
end;
end;
 
不就是一棵树吗?
你如果是3为3为定长的就更简单了
//******建树之前先调用FreeNode******************************
//******建树调用CreateTree或CreateMyTree********************
//创建编码层次树 treeview:树控件名;Fdatabasename:数据库名,Fsqlstring:SQL语句
//fbm:编码,fmc:名称,level:层次,long:长度
procedure CreateTree(treeview:ttreeview;Fdatabasename,Fsqlstring,fbm,fmc:string;level,long:integer);Overload;
procedure CreateTree(treeview:ttreeview;Fdatabasename,Fsqlstring,fbm,fmc:string;level,long:integer);
var query:TQuery;
code,bh:string;
FNode:pchar;
begin
try
query:=TQuery.Create(nil);
except
exit;
end;
query.DatabaseName:=fdatabasename;
query.close;
query.sql.Clear;
query.sql.Add(fsqlstring+' order by '+fbm);
query.Prepare;
try
query.open;
except
exit;
end;

query.First;
while not query.Eof do
begin
bh:=query.FieldByName(Fbm).asstring;
code := query.FieldByName(Fmc).asstring ;
try
getmem(fnode,length(bh)+1);//得到指针的内存空间
except
exit;
end;
move(bh[1],fnode^,length(bh)+1);//指针指出结点对应的编码
if (length(bh)=long)and(level=1) then //第一层
begin
treeview.Items.AddObject(nil,code, fnode);
end;
if level in [2..10] then //其他层
begin
AddItem(treeview,bh,code,long,level,fnode);
end;
query.Next;
end;
query.free;
end;

//释放节点内存
procedure FreeNode(TREEVIEW:TTREEVIEW);
procedure FreeNode(TREEVIEW:TTREEVIEW);
VAR
I:INTEGER;
pnode:pchar;
begin
FOR I:=0 to treeview.Items.Count-1 do
begin
pnode:=pchar(treeview.Items.Data);
Freemem(pnode);
end;
end;

如果你建的是结构树(就是有父亲的那种),再跟我说,我给你个例子
 
非常感谢各位的赐教
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
procedure TBook.ListAllSubNode(Code: string;Node:TTreeNode);
var
LevelNum : integer;
CurrentNode : TTreeNode;
CurrentCode : string;
BookName : string;
//BookQuery : TQuery;
SavePlace : TBookMark;
CurrentLevel: Integer;
begin
SavePlace := nil;
if LibDM.Book.Active = False then
LibDM.Book.Active := True;
//ookQuery.Database := LibDM.
LibDM.Book.First();
LevelNum := GetLevelNum(Code, '222');
while not LibDM.Book.eof do
begin
CurrentCode := LibDM.Book['book_ID'];
BookName := LibDM.Book['Book_Name'];
CurrentLevel:= GetLevelNum(CurrentCode, '222');
if (CurrentLevel = LevelNum+1) {如果处于下级} then
if ComparePrefix(Code, CurrentCode) then
if (ComparePrefix(Code, CurrentCode)){LevelNum级前的代码相同} then
begin
SavePlace := LibDM.Book.GetBookmark;
CurrentNode := ArchTree.Items.AddChild(Node, CurrentCode+'->'+ BookName);
if CurrentLevel < 3 then
begin
ListAllSubNode(CurrentCode, CurrentNode);
if SavePlace<>nil then
LibDM.Book.GotoBookmark(SavePlace); //为了这句代码的正确位置,我花了一个晚上加一个早晨,我激动不已,我对前途............. end;
end;//
LibDM.Book.Next();
end;
end;
//我将这段代码贴出来,也是想抛砖引玉,换取更好的代码
//虽然还有些子程序没贴出来,只要大家要,我会公布的
 
你的这种情况按ID索引一下不就可以了!!!!

以下是我的一种做法:
13. 由数据库表构造树一:好的编码和节点顺序
假设数据库表中有两个字段,分别为产品代码(CPDM)和产品名称(CPMC),代码为8位数字符型。
XX000000:前两位为大类代码,大类编码的后六位全为0;
XXY000000:第三位为中类代码,中类编码的后五位全为0;
XXXY0000:第四位为小类代码,小类编码的后四位全为0;
XXXXYY00:第五、六位为产品代码,产品编码的后六位全为0;
XXXXXXYY:最后两位为规格品代码,规格品代码的后两位一定不全为0。
大类下面可以没有中类或小类或产品,中类下可以没有小类或产品,小类下可没有产品。
所有的代码在库中按从小到大的顺序排列,所以子节点肯定在父节点后。

这样的库结构对构造树是非常有利的,一次扫描就可以了。PIII550近一万条记录不到9秒。
function getLevel(s:string):integer;
begin
Result:=1;
if copy(s,3,6)='000000' then exit;
Result:=2;
if copy(s,4,5)='00000' then exit;
Result:=3;
if copy(s,5,4)='0000' then exit;
Result:=4;
if copy(s,7,2)='00' then exit;
Result:=5;
end;

function getNormalCode(s:string):string;
const n:array[1..5] of integer=(2,3,4,6,8);
begin
result:=Copy(s,1,n[getLevel(s)]);
end;
procedure TForm1.Button1Click(Sender: TObject);
const MinLevel=5;
var
s:string;
n,L,i,nL:dword;
Node:array[0..MinLevel] of TTreeNode;
begin
n:=gettickcount();
for i:=0 to MinLevel do Node:=nil;
s:=getVFConnStr('d:/dbTest');
Treeview1.items.BeginUpdate;
Treeview1.Items.Clear;
with AdoTable1 do
begin
ConnectionString:=s;
TableName:='gypcbz';
active:=true;
First;
while not(eof) do
begin
s:=FieldByName('cpdm').asstring;
L:=getLevel(s);
s:='['+getNormalCode(s)+']'+
Trim(FieldByName('cpmc').asstring);
nL:=0;
for i:=L-1 downto 1 do
if Node<>nil then
begin
nL:=i;
break;
end;
Node[L]:=Treeview1.Items.AddChild(Node[nL],s);
for i:=L+1 to MinLevel-1 do Node:=nil;
next;
end;
active:=false;
end;
TreeView1.items.EndUpdate;
n:=gettickcount()-n;
label1.caption:=inttostr(n);
end;


 
你可先在ADOQUERY中将数据库表进行排序,然后再一条记录一条记录的添加到TREEVIEW中,
OVER后,再用同样的方法将二级节点进行插入,就OK了!!!
 
多人接受答案了。
 
后退
顶部