select Code,Name from Table order by Code procedure BuildTree(TreeView: TTreeView; Query: TADOQuery); var I: Integer; PNodes: array[0..1024] of TTreeNode; //最多级别 PID: String; ALevel: Integer; begin TreeView.Items.Clear; for I := Low(PNodes) to High(PNodes) do PNodes[I] := nil; PNodes[0] := TreeView.Items.AddFirst(nil,'货品类别'); with Query, TreeView, Items do begin Close; Open; BeginUpdate; try while not Eof do begin Application.ProcessMessages; PID := FieldByName('Code').AsString; ALevel := Round(Log2(Length(PID))); //以两位为一个级别 if ALevel - 1 > High(PNodes) then Continue; PNodes[ALevel] := AddChild(PNodes[ALevel-1],FieldByName('Code').AsString + '.' + FieldByName('Name').AsString); Next; end; finally EndUpdate; Close; end; end; end; 没调试过,这应该是比较快的,时间复杂度为O(n)
Procedure DrawTreeTop(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String); var NodTop,Nodselect: Ttreenode; MyTree : PDrawTree; CdsTmp : TclientDataSet; begin CdsTmp :=TclientDataSet.Create(Nil); Try CdsTmp.Data:=CdsDest.Data; TreDest.Items.Clear; New(Mytree); Mytree.Name:=UserCorp; TreDest.Items.AddChildObject(nil,Mytree.Name,Tobject(Mytree)); NodTop:=TreDest.TopItem; NodTop.ImageIndex:=0; NodTop.SelectedIndex:=0; CdsDest.Filtered:=false; CdsDest.Filter:=fieldLevel+'=1'; CdsDest.Filtered:=True; CdsDest.First; while not CdsDest.eof do begin New(Mytree); Mytree.Code:=CdsDest.fieldbyname(FieldCode).asstring; MyTree.Name:=CdsDest.fieldbyname(FieldName).asstring; Nodselect:=TreDest.Items.AddChildObject(NodTop,'【'+Mytree.Code+'】' +MyTree.Name,Tobject(Mytree)); DrawTreeAll(TreDest,CdsTmp,FieldCode,FieldName, fieldLevel,Nodselect); If Nodselect.HasChildren Then Begin Nodselect.ImageIndex:=0; Nodselect.SelectedIndex:=2; End else Begin Nodselect.ImageIndex:=1; Nodselect.SelectedIndex:=3; end; CdsDest.Next; End finally CdsTmp.Free; end; If CdsDest.Filtered Then CdsDest.Filtered:=False; // treDest.FullExpand; end;Procedure DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode);Var MyTree:PDrawTree; Node : TtreeNode; i:Integer; Begin CdsDest.Filtered:=False; CdsDest.Filter:=FieldCode+'='''+PDrawTree(ParNode.Data)^.Code+'*'+''' and ' +fieldLevel+'='+Inttostr(parNode.level+1); CdsDest.Filtered:=True; CdsDest.first; While Not CdsDest.Eof Do Begin New(MyTree); MyTree.code:=CdsDest.fieldbyname(FieldCode).asstring; MyTree.name:=CdsDest.fieldbyname(FieldName).asstring; Node:=TreDest.Items.AddChildObject(ParNode,'【'+MyTree.Code+'】' +MyTree.Name,Tobject(MyTree)); CdsDest.Next; end; For i:=0 To ParNode.Count-1 Do Begin DrawTreeAll(TreDest,CdsDest, FieldCode,FieldName,fieldLevel,ParNode.Item[i]); If ParNode.Item[i].HasChildren Then Begin ParNode.Item[i].ImageIndex:=0; ParNode.Item[i].SelectedIndex:=2; end else Begin ParNode.Item[i].ImageIndex:=1; ParNode.Item[i].SelectedIndex:=3; end; end; end;
PDrawTree = ^TDrawTree; TDrawTree = Record Code : String; //编号 Name : String; //名称 end;
type PDrawTree = ^TDrawTree; TDrawTree = Record Code : String; //编号 Name : String; //名称 end; TForm1 = class(TForm) ..... ..... private Protected public { Public declarations } end;
这段代码是将表中的Code 字段与Name 存储到树形结构的节点上
................. type PDrawTree = ^TDrawTree; TDrawTree = Record Code : String; //编号 Name : String; //名称 end; TForm1 = class(TForm) ..... ..... private Protected public Procedure DrawTreeTop(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String); Procedure DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode);
end; var Form1: TForm1;implementation Procedure TForm1.DrawTreeTop(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String); var NodTop,Nodselect: Ttreenode; MyTree : PDrawTree; CdsTmp : TclientDataSet; begin CdsTmp :=TclientDataSet.Create(Nil); Try CdsTmp.Data:=CdsDest.Data; TreDest.Items.Clear; New(Mytree); Mytree.Name:=UserCorp; TreDest.Items.AddChildObject(nil,Mytree.Name,Tobject(Mytree)); NodTop:=TreDest.TopItem; NodTop.ImageIndex:=0; NodTop.SelectedIndex:=0; CdsDest.Filtered:=false; CdsDest.Filter:=fieldLevel+'=1'; CdsDest.Filtered:=True; CdsDest.First; while not CdsDest.eof do begin New(Mytree); Mytree.Code:=CdsDest.fieldbyname(FieldCode).asstring; MyTree.Name:=CdsDest.fieldbyname(FieldName).asstring; Nodselect:=TreDest.Items.AddChildObject(NodTop,'【'+Mytree.Code+'】' +MyTree.Name,Tobject(Mytree)); DrawTreeAll(TreDest,CdsTmp,FieldCode,FieldName, fieldLevel,Nodselect); If Nodselect.HasChildren Then Begin Nodselect.ImageIndex:=0; Nodselect.SelectedIndex:=2; End else Begin Nodselect.ImageIndex:=1; Nodselect.SelectedIndex:=3; end; CdsDest.Next; End finally CdsTmp.Free; end; If CdsDest.Filtered Then CdsDest.Filtered:=False; // treDest.FullExpand; end; Procedure TForm1.DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet; FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode); Var MyTree:PDrawTree; Node : TtreeNode; i:Integer; Begin CdsDest.Filtered:=False; CdsDest.Filter:=FieldCode+'='''+PDrawTree(ParNode.Data)^.Code+'*'+''' and ' +fieldLevel+'='+Inttostr(parNode.level+1); CdsDest.Filtered:=True; CdsDest.first; While Not CdsDest.Eof Do Begin New(MyTree); MyTree.code:=CdsDest.fieldbyname(FieldCode).asstring; MyTree.name:=CdsDest.fieldbyname(FieldName).asstring; Node:=TreDest.Items.AddChildObject(ParNode,'【'+MyTree.Code+'】' +MyTree.Name,Tobject(MyTree)); CdsDest.Next; end; For i:=0 To ParNode.Count-1 Do Begin DrawTreeAll(TreDest,CdsDest, FieldCode,FieldName,fieldLevel,ParNode.Item[i]); If ParNode.Item[i].HasChildren Then Begin ParNode.Item[i].ImageIndex:=0; ParNode.Item[i].SelectedIndex:=2; end else Begin ParNode.Item[i].ImageIndex:=1; ParNode.Item[i].SelectedIndex:=3; end; end; end; 调用方法: DrawTreetop(TreType,CdsType,GetCodeField,GetNameField,GetLevelField);
procedure TForm1.BitBtn1Click(Sender: TObject); var I:Integer; PNOde:array[0..1024] of TTreeNode; PID:string; ALevel:Integer; begin TreeView1.Items.Clear; for I:=Low(PNode) to High(PNode) do PNOde[I]:=nil; // PNOde[0]:=TreeView1.Items.AddFirst(nil,'客户类别'); ADOQuery1.Close; adoquery1.SQL.Clear; ADOQuery1.SQL.Add('select * from TreeDate order by code'); ADOQuery1.Open; TreeView1.Items.BeginUpdate; try while not ADOQuery1.Eof do begin Application.ProcessMessages; PID:=ADOQuery1.fieldbyname('code').AsString; if PID='100' then begin PNOde[0]:=TreeView1.Items.AddFirst(nil,adoquery1.fieldbyname('code').AsString+'-'+adoquery1.fieldbyname('name').AsString); adoquery1.Next; Continue; end; ALevel:=Round(Int(Length(PID))/3); if ALevel-1>High(PNode) then Continue; PNOde[ALevel]:=TreeView1.Items.AddChild(PNOde[Alevel-1],adoquery1.fieldbyname('code').AsString+'-'+adoquery1.fieldbyname('name').AsString); adoquery1.Next; end; finally TreeView1.Items.EndUpdate; ADOQuery1.Close; end; end;procedure TForm1.TreeView1Click(Sender: TObject); var PNOde:TTreeNode; str:string; sl:TStringList; begin PNOde:=TreeView1.Selected; sl:=TStringList.Create; str:=PNOde.Text; if PNOde.Parent<>nil then begin ExtractStrings(['-'],[],PChar(str),sl); Edit1.Text:=sl[0]; Edit2.Text:=sl[1]; // Edit3.Text:=leftstr(PNOde.Parent.Text,3); end else begin Edit2.Text:=str; Edit1.Text:='100'; Edit3.Text:='100'; end; end;procedure TForm1.BitBtn2Click(Sender: TObject); var PNOde:array[0..3] of Double; X:word; begin for X:=Low(PNode) to High(Pnode) do ShowMessage(IntToStr(X));end;procedure TForm1.BitBtn3Click(Sender: TObject); var S: string; SL: TStringList; begin S := '123,456,789'; SL := TStringList.Create; ExtractStrings([','], [], PChar(S), SL); Edit1.Text:=sl[1]; ShowMessage(SL.Text); SL.Free;end;procedure TForm1.N1Click(Sender: TObject); var str:string; PNode:TTreeNode; Maxcode:string; Newcode:string; begin str:=InputBox('请输入节点名称','请输入节点名称',''); PNOde:=TreeView1.Selected; if Edit1.Text='100' then begin ADOQuery2.Close; ADOQuery2.SQL.Clear; ADOQuery2.SQL.Add('select max(code) code from Treedate where code like ''1__'' '); ADOQuery2.Open; Maxcode:=ADOQuery2.FieldByName('code').AsString; Maxcode:=IntToStr(StrToInt(Maxcode)+1); Newcode:=Maxcode+'-'+str; end else begin ADOQuery2.Close; ADOQuery2.SQL.Clear; ADOQuery2.SQL.Add('select max(code) code from Treedate where code like '''+edit1.Text+'%'' '); ADOQuery2.Open; Maxcode:=ADOQuery2.FieldByName('code').AsString; if Maxcode<>Edit1.Text then begin Maxcode:=IntToStr(StrToInt(Maxcode)+1); Newcode:=Maxcode+'-'+str; end else begin Maxcode:=Edit1.Text+'001'; Newcode:=Maxcode+'-'+str; end; end; try TreeView1.Items.AddChild(PNode,Newcode); ADOCommand1.CommandText:='insert into Treedate([code],[name])values('''+maxcode+''','''+str+''') '; ADOCommand1.Execute; finally end;end;
大家看看我的代码,我已经改进了,程序正常了,但是算出来的“ALevel”只有在要目录的时候才等于1,如果我点的是0102的项目,则ALevel=0102,不知道为什么,如果ALevel能准确显示,那Code就有可能计算出来了。 procedure TClientSortForm.btnNewClick(Sender: TObject); var Str,Tempstr,CodeStr,PID:string; I,ALevel : Integer ; begin //代码中有一个异常:当跟节点被选中时提示“客户类别”不是Integer Str :=tvSort.Selected.Text ; //给Str赋值为树焦点的文本 TempStr := StrPos(PChar(Str),'-'); //从Str中取出以-开头的末端字符串,新的字符串包含- CodeStr :=Copy(str,0,length(Str)-length(TempStr)); //取出Code段字符串 I := 1; ALevel := Round (Int(Length(CodeStr))/2); dmForm.qryAll.SQL.Clear ; dmForm.qryAll.SQL.Add('select Code,Name from Client_Category order by Code'); dmForm.qryAll.Open; try while not dmForm.qryAll.Eof do begin Application.ProcessMessages; PID := dmForm.qryAll.FieldByName('Code').AsString; if Round(int(Length(PID))/2) < ALevel then Continue (I := I+1); dmForm.qryAll.Next; end; // edtCode.Text := tvSort.Items[I-1].Text ; edtCode.Text := IntToStr(ALevel ) ; edtCode.Text := '546545' ; edtName.Enabled := True; edtName.Text := ''; edtName.SetFocus ; Break ; finally dmForm.qryAll.Close; end;end;
TO:liuweiyc procedure TClientSortForm.btnNewClick(Sender: TObject); var Maxcode:string; //只计算新建的项目的Code begin if edtCode.Text='根节点无编号' then // edtCode.Text 显示的是当前的Code,'根节点无编号'是根Code begin dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like ''__'' '); // 提示"qryAll:Field 'Code' not found." // dmForm.qryAll.SQL.Add('select max(Code) as ''__''from Client_Category');// 提示"qryAll:Field 'Code' not found." dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; Maxcode:=IntToStr(StrToInt(Maxcode)+1); end else begin dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; //dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like '''+edtCode.Text+'%'' ');// 提示"qryAll:Field 'Code' not found." dmForm.qryAll.SQL.Add('select max(Code) as '''+edtCode.Text+'%'' from Client_Category');// 提示"qryAll:Field 'Code' not found." dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; if Maxcode <>edtCode.Text then begin Maxcode:=IntToStr(StrToInt(Maxcode)+1); end else begin Maxcode:=edtCode.Text+'01'; end; end; edtName.Enabled := True; edtName.Text := ''; edtName.SetFocus ; end;请liuweiyc帮忙看看为什么出现上面的提示,谢谢!!!
我把select max(Code) Code from Client_Category where Code like ''__'' ' 改为: select max(Code) from Client_Category where Code like ''__'' '原来的“select max(Code) Code from Client_Category where Code like ''__'' '”同样出错"__"我想是两位数的意思吗?
是'select max(code) code from Treedate where code like ''1__'' __ 是两个'_','_'是代表一位字符
我这样写也有问题,提示:“语法错误(操作符丢失)在查询表达式'max(code) code'中”
Treedate是不是tree在数据库中的表呢?直接用Treedate也是提示同样的错误
Treedate是树存放在数据库中的数据表就你上面两个字段一个code,一个name
我正是写了那个表,却总是提示错误: procedure TClientSortForm.btnNewClick(Sender: TObject); var { PID:string; //Str,Tempstr,CodeStr, I,MyLevel, MyInt,SQLInt: Integer ; }// str:string; PNode:TTreeNode; Maxcode:string; // Newcode:string;begin // str:=InputBox('请输入节点名称','请输入节点名称',''); PNOde:=tvSort.Selected; if edtCode.Text='根节点无编号' then begin dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; // dmForm.qryAll.SQL.Add('select max(dmForm.qryAll.Fieldbyname('Code')) from Client_Category where Code like ''__'' '); dmForm.qryAll.SQL.Add('select max(Code) code from Treedate where Code like ''1__'''); //dmForm.qryAll.SQL.Add('select max(Code) code from Client_Category'); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; Maxcode:=IntToStr(StrToInt(Maxcode)+1); // Newcode:=Maxcode+'-'+str; end else begin dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; // dmForm.qryAll.SQL.Add('select max(dmForm.qryAll.Fieldbyname('Code')) from Client_Category where Code like '''+edtCode.Text+'%'' '); // dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like '''+edtCode.Text+'%'' '); dmForm.qryAll.SQL.Add('select max(Code) code from Client_Category'); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; if Maxcode <>edtCode.Text then begin Maxcode:=IntToStr(StrToInt(Maxcode)+1); // Newcode:=Maxcode+'-'+str; end else begin Maxcode:=edtCode.Text+'01'; // Newcode:=Maxcode+'-'+str; end; end; edtName.Enabled := True; edtName.Text := ''; edtName.SetFocus ; end;====== 我测试了很多查询语句,总是有错误。
我使用最基本的查询: dmForm.qryAll.SQL.Add('select Max(Code) from Client_Category'); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; Maxcode:=IntToStr(StrToInt(Maxcode)+1); 提示没有Code段。
dmForm.qryAll.SQL.Add('select Max(Code) Code from Client_Category'); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString; Maxcode:=IntToStr(StrToInt(Maxcode)+1);提示类似语法错误的。
在liuweiyc帮助下,我已经完成了新建下级节点的功能,现在公布代码。 代码不考虑为用户自动填充闲置的Code,例如一个分类中只有--01、--99两个子类,则程序提示“本节点的下级最高节点已经存在,请检查您的分类表。” 为了完成算法,另外定义了一个方法,用作取字符串的最后两位。整个算法的核心是查找同级类的最大Code,再Code+1。 所有功能完成后,本人会发布完整的代码供大家下载。再次感谢所有提供帮助的朋友!//定义取字符串后面的两位数,以为判断未位是不是'99' function getRightStr(const AText: String; const ACount: Integer): AnsiString; begin Result := Copy(WideString(AText), Length(WideString(AText)) + 1 - ACount, ACount); end;procedure TClientSortForm.btnNewClick(Sender: TObject); var Maxcode,str,TempStr,MyCode:string; //MyCode为树焦点的Code I : Integer ; begin if tvSort.Selected.Text='客户类别' then begin dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; dmForm.qryAll.SQL.Add('select max(Code) as code from Client_Category where Code like ''__'''); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString ; if Maxcode <> '' then begin if Maxcode <> '99' then begin Maxcode:=IntToStr(StrToInt(Maxcode)+1); I := StrToInt(Maxcode ); if Length(IntToStr(I)) mod 2 = 0 then edtCode.Text := Maxcode else edtCode.Text := '0' + Maxcode end else Application.messagebox('本节点的下级最高节点已经存在,请检查您的分类表。','新建请求无效',0+64); end else edtCode.Text := '01' ; end else begin Str :=tvSort.Selected.Text ; //给Str赋值为树焦点的文本 TempStr := StrPos(PChar(Str),'-'); //从Str中取出以-开头的末端字符串,新的字符串包含- MyCode :=Copy(str,0,length(Str)-length(TempStr)); //取出Code段字符串,目的是固定Code的值 dmForm.qryAll.Close; dmForm.qryAll.SQL.Clear; dmForm.qryAll.SQL.Add('select Max(Code) as code from Client_Category where Code like '''+MyCode+'__'' '); dmForm.qryAll.Open; Maxcode:=dmForm.qryAll.FieldByName('Code').AsString ; if Maxcode <> '' then begin if getRightStr(Maxcode,2) <> '99' then begin Maxcode:=IntToStr(StrToInt(Maxcode)+1); I := StrToInt(Maxcode ); // 去掉MaxCode的'0' if Length(IntToStr(I)) mod 2 = 0 then edtCode.Text := Maxcode else edtCode.Text := '0' + Maxcode; end else Application.messagebox('本节点的下级最高节点已经存在,请检查您的分类表。','新建请求无效',0+64); end else begin Maxcode:=MyCode +'01'; edtCode.Text := Maxcode; end; end; edtName.Enabled := True; edtName.Text := ''; edtName.SetFocus ; end;
procedure BuildTree(TreeView: TTreeView; Query: TADOQuery);
var
I: Integer;
PNodes: array[0..1024] of TTreeNode; //最多级别
PID: String;
ALevel: Integer;
begin
TreeView.Items.Clear;
for I := Low(PNodes) to High(PNodes) do PNodes[I] := nil;
PNodes[0] := TreeView.Items.AddFirst(nil,'货品类别'); with Query, TreeView, Items do
begin
Close;
Open;
BeginUpdate;
try
while not Eof do
begin
Application.ProcessMessages;
PID := FieldByName('Code').AsString;
ALevel := Round(Log2(Length(PID))); //以两位为一个级别
if ALevel - 1 > High(PNodes) then Continue;
PNodes[ALevel] := AddChild(PNodes[ALevel-1],FieldByName('Code').AsString + '.' + FieldByName('Name').AsString);
Next;
end;
finally
EndUpdate;
Close;
end;
end;
end;
没调试过,这应该是比较快的,时间复杂度为O(n)
表的结构不方便改的,这样的表在数据库中有很多,我希望代码能有效移植。不过还是很感谢你回答。
TO:chenzhuo
我是编程的新手,没有系统的学习过Delphi,基本上是自己看资料,所以很多知识都不会。近来希望写一个报价单管理程序,上面的表是商品类别的存放表及其结构。感谢你写的代码,但是我还是不会套用到我的Unit里,希望你留下QQ,我把Unit发给你,同时详细的把数据库结构描述一下,希望能真正在本机上实现编译。不胜感激!
我的QQ:36519719
Delphi中没有log,我换成了下面的:
ALevel := Round(Int(Length(PID))/2); //以两位为一个级别
我改了一下代码:
procedure TClientSortForm.FormCreate(Sender: TObject);
var
I: Integer;
PNodes: array[0..1024] of TTreeNode; //最多级别
PID: String;
ALevel: Integer;
begin
tvClientSort.Items.Clear;
for I := Low(PNodes) to High(PNodes) do PNodes[I] := nil;
PNodes[0] := tvClientSort.Items.AddFirst(nil,'货品类别');
loginForm.qryAll.SQL.Clear ;
loginForm.qryAll.SQL.Add('select Code,Name from Goods_Category order by Code');
loginForm.qryAll.Open;
tvClientSort.Items.BeginUpdate;
try
while not loginForm.qryAll.Eof do
begin
Application.ProcessMessages;
PID := loginForm.qryAll.FieldByName('Code').AsString;
ALevel := Round(Int(Length(PID))/2); //以两位为一个级别
if ALevel - 1 > High(PNodes) then Continue;
PNodes[ALevel] := tvClientSort.Items.AddChild(PNodes[ALevel-1],loginForm.qryAll.FieldByName('Code').AsString + '-' + loginForm.qryAll.FieldByName('Name').AsString);
loginForm.qryAll.Next;
end;
finally
tvClientSort.Items.EndUpdate;
loginForm.qryAll.Close;
end;
end;
可以描绘了,不知道有没有需要改进的地方。另:编辑的话应该怎么做呢?
如果'-'前面的一段字符呢?
FieldCode,FieldName,fieldLevel:String);
var
NodTop,Nodselect: Ttreenode;
MyTree : PDrawTree;
CdsTmp : TclientDataSet;
begin
CdsTmp :=TclientDataSet.Create(Nil);
Try
CdsTmp.Data:=CdsDest.Data;
TreDest.Items.Clear;
New(Mytree);
Mytree.Name:=UserCorp;
TreDest.Items.AddChildObject(nil,Mytree.Name,Tobject(Mytree));
NodTop:=TreDest.TopItem;
NodTop.ImageIndex:=0;
NodTop.SelectedIndex:=0; CdsDest.Filtered:=false;
CdsDest.Filter:=fieldLevel+'=1';
CdsDest.Filtered:=True; CdsDest.First;
while not CdsDest.eof do
begin
New(Mytree);
Mytree.Code:=CdsDest.fieldbyname(FieldCode).asstring;
MyTree.Name:=CdsDest.fieldbyname(FieldName).asstring;
Nodselect:=TreDest.Items.AddChildObject(NodTop,'【'+Mytree.Code+'】'
+MyTree.Name,Tobject(Mytree));
DrawTreeAll(TreDest,CdsTmp,FieldCode,FieldName,
fieldLevel,Nodselect);
If Nodselect.HasChildren Then
Begin
Nodselect.ImageIndex:=0;
Nodselect.SelectedIndex:=2;
End
else
Begin
Nodselect.ImageIndex:=1;
Nodselect.SelectedIndex:=3;
end;
CdsDest.Next;
End
finally
CdsTmp.Free;
end; If CdsDest.Filtered Then
CdsDest.Filtered:=False;
// treDest.FullExpand;
end;Procedure DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet;
FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode);Var
MyTree:PDrawTree;
Node : TtreeNode;
i:Integer;
Begin
CdsDest.Filtered:=False;
CdsDest.Filter:=FieldCode+'='''+PDrawTree(ParNode.Data)^.Code+'*'+''' and '
+fieldLevel+'='+Inttostr(parNode.level+1);
CdsDest.Filtered:=True;
CdsDest.first;
While Not CdsDest.Eof Do
Begin
New(MyTree);
MyTree.code:=CdsDest.fieldbyname(FieldCode).asstring;
MyTree.name:=CdsDest.fieldbyname(FieldName).asstring;
Node:=TreDest.Items.AddChildObject(ParNode,'【'+MyTree.Code+'】'
+MyTree.Name,Tobject(MyTree));
CdsDest.Next;
end;
For i:=0 To ParNode.Count-1 Do
Begin
DrawTreeAll(TreDest,CdsDest,
FieldCode,FieldName,fieldLevel,ParNode.Item[i]);
If ParNode.Item[i].HasChildren Then
Begin
ParNode.Item[i].ImageIndex:=0;
ParNode.Item[i].SelectedIndex:=2;
end
else
Begin
ParNode.Item[i].ImageIndex:=1;
ParNode.Item[i].SelectedIndex:=3;
end;
end;
end;
TDrawTree = Record
Code : String; //编号
Name : String; //名称
end;
TDrawTree = Record
Code : String; //编号
Name : String; //名称
end;请问这段代码可以简单地存取Code及Name吗?
我写了这个代码来显示Code及Name,不知道是不是有更简单的办法:procedure TClientSortForm.tvChange(Sender: TObject; Node: TTreeNode);
var
I:Integer;
Str,Tempstr,CodeStr,NameStr:string;
begin
Str :=tvClientSort.Selected.Text ;
TempStr := StrPos(PChar(Str),'-');
CodeStr :=Copy(str,0,length(Str)-length(TempStr));
NameStr :=Copy(str,length(Str)-length(TempStr)+2,length(Str));
edtGoodsCode.Text := CodeStr;
edtGoodsName.Text := NameStr;
end;Str可以定义少一点,但是考虑到以为使用代码,我多定义了几个,反正现在的电脑配置好了,也没有什么。
TDrawTree = Record
Code : String; //编号
Name : String; //名称
end;
TForm1 = class(TForm)
.....
.....
private
Protected
public
{ Public declarations }
end;
type PDrawTree = ^TDrawTree;
TDrawTree = Record
Code : String; //编号
Name : String; //名称
end;
TForm1 = class(TForm)
.....
.....
private
Protected
public
Procedure DrawTreeTop(TreDest : TtreeView;CdsDest:TclientDataSet;
FieldCode,FieldName,fieldLevel:String);
Procedure DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet;
FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode);
end;
var
Form1: TForm1;implementation
Procedure TForm1.DrawTreeTop(TreDest : TtreeView;CdsDest:TclientDataSet;
FieldCode,FieldName,fieldLevel:String);
var
NodTop,Nodselect: Ttreenode;
MyTree : PDrawTree;
CdsTmp : TclientDataSet;
begin
CdsTmp :=TclientDataSet.Create(Nil);
Try
CdsTmp.Data:=CdsDest.Data;
TreDest.Items.Clear;
New(Mytree);
Mytree.Name:=UserCorp;
TreDest.Items.AddChildObject(nil,Mytree.Name,Tobject(Mytree));
NodTop:=TreDest.TopItem;
NodTop.ImageIndex:=0;
NodTop.SelectedIndex:=0; CdsDest.Filtered:=false;
CdsDest.Filter:=fieldLevel+'=1';
CdsDest.Filtered:=True; CdsDest.First;
while not CdsDest.eof do
begin
New(Mytree);
Mytree.Code:=CdsDest.fieldbyname(FieldCode).asstring;
MyTree.Name:=CdsDest.fieldbyname(FieldName).asstring;
Nodselect:=TreDest.Items.AddChildObject(NodTop,'【'+Mytree.Code+'】'
+MyTree.Name,Tobject(Mytree));
DrawTreeAll(TreDest,CdsTmp,FieldCode,FieldName,
fieldLevel,Nodselect);
If Nodselect.HasChildren Then
Begin
Nodselect.ImageIndex:=0;
Nodselect.SelectedIndex:=2;
End
else
Begin
Nodselect.ImageIndex:=1;
Nodselect.SelectedIndex:=3;
end;
CdsDest.Next;
End
finally
CdsTmp.Free;
end; If CdsDest.Filtered Then
CdsDest.Filtered:=False;
// treDest.FullExpand;
end; Procedure TForm1.DrawTreeAll(TreDest : TtreeView;CdsDest:TclientDataSet;
FieldCode,FieldName,fieldLevel:String;parNode:TtreeNode); Var
MyTree:PDrawTree;
Node : TtreeNode;
i:Integer;
Begin
CdsDest.Filtered:=False;
CdsDest.Filter:=FieldCode+'='''+PDrawTree(ParNode.Data)^.Code+'*'+''' and '
+fieldLevel+'='+Inttostr(parNode.level+1);
CdsDest.Filtered:=True;
CdsDest.first;
While Not CdsDest.Eof Do
Begin
New(MyTree);
MyTree.code:=CdsDest.fieldbyname(FieldCode).asstring;
MyTree.name:=CdsDest.fieldbyname(FieldName).asstring;
Node:=TreDest.Items.AddChildObject(ParNode,'【'+MyTree.Code+'】'
+MyTree.Name,Tobject(MyTree));
CdsDest.Next;
end;
For i:=0 To ParNode.Count-1 Do
Begin
DrawTreeAll(TreDest,CdsDest,
FieldCode,FieldName,fieldLevel,ParNode.Item[i]);
If ParNode.Item[i].HasChildren Then
Begin
ParNode.Item[i].ImageIndex:=0;
ParNode.Item[i].SelectedIndex:=2;
end
else
Begin
ParNode.Item[i].ImageIndex:=1;
ParNode.Item[i].SelectedIndex:=3;
end;
end;
end; 调用方法: DrawTreetop(TreType,CdsType,GetCodeField,GetNameField,GetLevelField);
TreType:表示树形控件
CdsType:表示数据集
GetCodeField:表示你的编号字段
GetNameField:表示你的名称字段
GetLevelField:表示节点所在的层次
修改 删除 举报 引用 回复
加为好友
发送私信
在线聊天
tzshu
tzshu
等级:
发表于:2008-06-15 15:25:348楼 得分:0
PDrawTree = ^TDrawTree;
TDrawTree = Record
Code : String; //编号
Name : String; //名称
end;
以下是我描绘的代码:procedure TClientSortForm.FormCreate(Sender: TObject);
var
I: Integer;
PNodes: array[0..1024] of TTreeNode; //最多级别
PID: String;
ALevel: Integer;
begin
tvSort.Items.Clear;
for I := Low(PNodes) to High(PNodes) do PNodes[I] := nil;
PNodes[0] := tvSort.Items.AddFirst(nil,'客户类别');
dmForm.qryAll.SQL.Clear ;
dmForm.qryAll.SQL.Add('select Code,Name from Client_Category order by Code');
dmForm.qryAll.Open;
tvSort.Items.BeginUpdate;
try
while not dmForm.qryAll.Eof do
begin
Application.ProcessMessages;
PID := dmForm.qryAll.FieldByName('Code').AsString;
ALevel := Round(Int(Length(PID))/2); //以两位为一个级别
if ALevel - 1 > High(PNodes) then Continue;
PNodes[ALevel] := tvSort.Items.AddChild(PNodes[ALevel-1],dmForm.qryAll.FieldByName('Code').AsString + '-' + dmForm.qryAll.FieldByName('Name').AsString);
dmForm.qryAll.Next;
end;
finally
tvSort.Items.EndUpdate;
dmForm.qryAll.Close;
end;
end;
现在有一个问题,我写的“新建”代码会导致程序死掉,请大家帮帮忙,解决后立即结贴:procedure TClientSortForm.btnNewClick(Sender: TObject);
var
Str,Tempstr,CodeStr,PID:string;
I,ALevel : Integer ;
begin
//代码中有一个异常:当跟节点被选中时提示“客户类别”不是Integer Str :=tvSort.Selected.Text ; //给Str赋值为树焦点的文本
TempStr := StrPos(PChar(Str),'-'); //从Str中取出以-开头的末端字符串,新的字符串包含-
CodeStr :=Copy(str,0,length(Str)-length(TempStr)); //取出Code段字符串
I := 0;
ALevel := Round(Int(Length(CodeStr))/2);
dmForm.qryAll.SQL.Clear ;
dmForm.qryAll.SQL.Add('select Code,Name from Client_Category order by Code');
dmForm.qryAll.Open;
try
while not dmForm.qryAll.Eof do
begin
Application.ProcessMessages;
PID := dmForm.qryAll.FieldByName('Code').AsString;
if Round(int(Length(PID))/2) <= ALevel then
I := I+1
else end;
dmForm.qryAll.Next;
finally
dmForm.qryAll.Close;
end; edtCode.Text := tvSort.Items[I].Text ;
edtName.Enabled := True;
edtName.Text := '';
edtName.SetFocus ;
end;
代码可以编译,却使程序死掉,急!!!
If then else..这句有问题吗?哎.....
var
I:Integer;
PNOde:array[0..1024] of TTreeNode;
PID:string;
ALevel:Integer;
begin
TreeView1.Items.Clear;
for I:=Low(PNode) to High(PNode) do
PNOde[I]:=nil;
// PNOde[0]:=TreeView1.Items.AddFirst(nil,'客户类别');
ADOQuery1.Close;
adoquery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from TreeDate order by code');
ADOQuery1.Open;
TreeView1.Items.BeginUpdate;
try
while not ADOQuery1.Eof do
begin
Application.ProcessMessages;
PID:=ADOQuery1.fieldbyname('code').AsString;
if PID='100' then
begin
PNOde[0]:=TreeView1.Items.AddFirst(nil,adoquery1.fieldbyname('code').AsString+'-'+adoquery1.fieldbyname('name').AsString);
adoquery1.Next;
Continue;
end;
ALevel:=Round(Int(Length(PID))/3);
if ALevel-1>High(PNode) then
Continue;
PNOde[ALevel]:=TreeView1.Items.AddChild(PNOde[Alevel-1],adoquery1.fieldbyname('code').AsString+'-'+adoquery1.fieldbyname('name').AsString);
adoquery1.Next;
end;
finally
TreeView1.Items.EndUpdate;
ADOQuery1.Close;
end;
end;procedure TForm1.TreeView1Click(Sender: TObject);
var
PNOde:TTreeNode;
str:string;
sl:TStringList;
begin
PNOde:=TreeView1.Selected;
sl:=TStringList.Create;
str:=PNOde.Text;
if PNOde.Parent<>nil then
begin
ExtractStrings(['-'],[],PChar(str),sl);
Edit1.Text:=sl[0];
Edit2.Text:=sl[1];
// Edit3.Text:=leftstr(PNOde.Parent.Text,3);
end
else
begin
Edit2.Text:=str;
Edit1.Text:='100';
Edit3.Text:='100';
end;
end;procedure TForm1.BitBtn2Click(Sender: TObject);
var
PNOde:array[0..3] of Double;
X:word;
begin
for X:=Low(PNode) to High(Pnode) do
ShowMessage(IntToStr(X));end;procedure TForm1.BitBtn3Click(Sender: TObject);
var
S: string;
SL: TStringList;
begin
S := '123,456,789';
SL := TStringList.Create;
ExtractStrings([','], [], PChar(S), SL);
Edit1.Text:=sl[1];
ShowMessage(SL.Text);
SL.Free;end;procedure TForm1.N1Click(Sender: TObject);
var
str:string;
PNode:TTreeNode;
Maxcode:string;
Newcode:string;
begin
str:=InputBox('请输入节点名称','请输入节点名称','');
PNOde:=TreeView1.Selected;
if Edit1.Text='100' then
begin
ADOQuery2.Close;
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add('select max(code) code from Treedate where code like ''1__'' ');
ADOQuery2.Open;
Maxcode:=ADOQuery2.FieldByName('code').AsString;
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
Newcode:=Maxcode+'-'+str;
end
else
begin ADOQuery2.Close;
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add('select max(code) code from Treedate where code like '''+edit1.Text+'%'' ');
ADOQuery2.Open;
Maxcode:=ADOQuery2.FieldByName('code').AsString;
if Maxcode<>Edit1.Text then
begin
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
Newcode:=Maxcode+'-'+str;
end
else
begin
Maxcode:=Edit1.Text+'001';
Newcode:=Maxcode+'-'+str;
end;
end;
try
TreeView1.Items.AddChild(PNode,Newcode);
ADOCommand1.CommandText:='insert into Treedate([code],[name])values('''+maxcode+''','''+str+''') ';
ADOCommand1.Execute;
finally end;end;
procedure TClientSortForm.btnNewClick(Sender: TObject);
var
Str,Tempstr,CodeStr,PID:string;
I,ALevel : Integer ;
begin
//代码中有一个异常:当跟节点被选中时提示“客户类别”不是Integer Str :=tvSort.Selected.Text ; //给Str赋值为树焦点的文本
TempStr := StrPos(PChar(Str),'-'); //从Str中取出以-开头的末端字符串,新的字符串包含-
CodeStr :=Copy(str,0,length(Str)-length(TempStr)); //取出Code段字符串
I := 1;
ALevel := Round (Int(Length(CodeStr))/2);
dmForm.qryAll.SQL.Clear ;
dmForm.qryAll.SQL.Add('select Code,Name from Client_Category order by Code');
dmForm.qryAll.Open;
try while not dmForm.qryAll.Eof do
begin
Application.ProcessMessages;
PID := dmForm.qryAll.FieldByName('Code').AsString;
if Round(int(Length(PID))/2) < ALevel then Continue (I := I+1);
dmForm.qryAll.Next; end;
// edtCode.Text := tvSort.Items[I-1].Text ;
edtCode.Text := IntToStr(ALevel ) ;
edtCode.Text := '546545' ;
edtName.Enabled := True;
edtName.Text := '';
edtName.SetFocus ;
Break ;
finally dmForm.qryAll.Close; end;end;
---
以上是思路,可惜没有实现。
TO:liuweiyc
感谢你的代码,这些似乎是全套的,我要研究一下了。感谢所有回答的朋友,是大家推动了国家的发展啊!!中国好样的!
你的'100'是什么意思呢?
procedure TClientSortForm.btnNewClick(Sender: TObject);
var
Maxcode:string; //只计算新建的项目的Code
begin
if edtCode.Text='根节点无编号' then // edtCode.Text 显示的是当前的Code,'根节点无编号'是根Code
begin
dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like ''__'' '); // 提示"qryAll:Field 'Code' not found."
// dmForm.qryAll.SQL.Add('select max(Code) as ''__''from Client_Category');// 提示"qryAll:Field 'Code' not found."
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
end
else
begin dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
//dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like '''+edtCode.Text+'%'' ');// 提示"qryAll:Field 'Code' not found."
dmForm.qryAll.SQL.Add('select max(Code) as '''+edtCode.Text+'%'' from Client_Category');// 提示"qryAll:Field 'Code' not found."
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
if Maxcode <>edtCode.Text then
begin
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
end
else
begin
Maxcode:=edtCode.Text+'01';
end;
end;
edtName.Enabled := True;
edtName.Text := '';
edtName.SetFocus ;
end;请liuweiyc帮忙看看为什么出现上面的提示,谢谢!!!
改为:
select max(Code) from Client_Category where Code like ''__'' '原来的“select max(Code) Code from Client_Category where Code like ''__'' '”同样出错"__"我想是两位数的意思吗?
procedure TClientSortForm.btnNewClick(Sender: TObject);
var
{
PID:string; //Str,Tempstr,CodeStr,
I,MyLevel, MyInt,SQLInt: Integer ; }// str:string;
PNode:TTreeNode;
Maxcode:string;
// Newcode:string;begin
// str:=InputBox('请输入节点名称','请输入节点名称','');
PNOde:=tvSort.Selected;
if edtCode.Text='根节点无编号' then
begin
dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
// dmForm.qryAll.SQL.Add('select max(dmForm.qryAll.Fieldbyname('Code')) from Client_Category where Code like ''__'' ');
dmForm.qryAll.SQL.Add('select max(Code) code from Treedate where Code like ''1__''');
//dmForm.qryAll.SQL.Add('select max(Code) code from Client_Category');
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
// Newcode:=Maxcode+'-'+str;
end
else
begin dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
// dmForm.qryAll.SQL.Add('select max(dmForm.qryAll.Fieldbyname('Code')) from Client_Category where Code like '''+edtCode.Text+'%'' ');
// dmForm.qryAll.SQL.Add('select max(Code) from Client_Category where Code like '''+edtCode.Text+'%'' ');
dmForm.qryAll.SQL.Add('select max(Code) code from Client_Category');
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
if Maxcode <>edtCode.Text then
begin
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
// Newcode:=Maxcode+'-'+str;
end
else
begin
Maxcode:=edtCode.Text+'01';
// Newcode:=Maxcode+'-'+str;
end;
end;
edtName.Enabled := True;
edtName.Text := '';
edtName.SetFocus ;
end;======
我测试了很多查询语句,总是有错误。
dmForm.qryAll.SQL.Add('select Max(Code) from Client_Category');
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
提示没有Code段。
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString;
Maxcode:=IntToStr(StrToInt(Maxcode)+1);提示类似语法错误的。
Treedate
code name
100 客户类别
101 电子电路维修
... ....要不你加我QQ270356735
代码不考虑为用户自动填充闲置的Code,例如一个分类中只有--01、--99两个子类,则程序提示“本节点的下级最高节点已经存在,请检查您的分类表。”
为了完成算法,另外定义了一个方法,用作取字符串的最后两位。整个算法的核心是查找同级类的最大Code,再Code+1。
所有功能完成后,本人会发布完整的代码供大家下载。再次感谢所有提供帮助的朋友!//定义取字符串后面的两位数,以为判断未位是不是'99'
function getRightStr(const AText: String; const ACount: Integer): AnsiString;
begin
Result := Copy(WideString(AText), Length(WideString(AText)) + 1 - ACount, ACount);
end;procedure TClientSortForm.btnNewClick(Sender: TObject);
var
Maxcode,str,TempStr,MyCode:string; //MyCode为树焦点的Code
I : Integer ;
begin
if tvSort.Selected.Text='客户类别' then
begin
dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
dmForm.qryAll.SQL.Add('select max(Code) as code from Client_Category where Code like ''__''');
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString ;
if Maxcode <> '' then
begin
if Maxcode <> '99' then
begin
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
I := StrToInt(Maxcode );
if Length(IntToStr(I)) mod 2 = 0 then
edtCode.Text := Maxcode
else
edtCode.Text := '0' + Maxcode
end
else
Application.messagebox('本节点的下级最高节点已经存在,请检查您的分类表。','新建请求无效',0+64);
end
else
edtCode.Text := '01' ;
end
else
begin
Str :=tvSort.Selected.Text ; //给Str赋值为树焦点的文本
TempStr := StrPos(PChar(Str),'-'); //从Str中取出以-开头的末端字符串,新的字符串包含-
MyCode :=Copy(str,0,length(Str)-length(TempStr)); //取出Code段字符串,目的是固定Code的值
dmForm.qryAll.Close;
dmForm.qryAll.SQL.Clear;
dmForm.qryAll.SQL.Add('select Max(Code) as code from Client_Category where Code like '''+MyCode+'__'' ');
dmForm.qryAll.Open;
Maxcode:=dmForm.qryAll.FieldByName('Code').AsString ;
if Maxcode <> '' then
begin
if getRightStr(Maxcode,2) <> '99' then
begin
Maxcode:=IntToStr(StrToInt(Maxcode)+1);
I := StrToInt(Maxcode ); // 去掉MaxCode的'0'
if Length(IntToStr(I)) mod 2 = 0 then
edtCode.Text := Maxcode
else
edtCode.Text := '0' + Maxcode;
end
else
Application.messagebox('本节点的下级最高节点已经存在,请检查您的分类表。','新建请求无效',0+64);
end
else
begin
Maxcode:=MyCode +'01';
edtCode.Text := Maxcode;
end;
end;
edtName.Enabled := True;
edtName.Text := '';
edtName.SetFocus ;
end;
程序从ClientSort模块区开始开发,一直使用最简单的SQL函数,最后是报价单录入窗体,使用了事务操作的方式。这也是我个人进步的过程。程序中包含大部分初学者需要学习的知识(个人认为),比如打印、导出到Excel、搜索、主从表的结构和处理、异常现象的处理、外接打印报表的设计、开发打印组建、DB窗体的使用。这里需要强调的,主从表在Access设计阶段已经使用了“实施参照完整性”。程序的代码行有详细的说明,大家可以共同学习。
大虾就不要下载了,因为很多算法都是很基本的。
程序的下载地址:
http://download.csdn.net/source/534051
程序另外还使用了以下控件:
FastReport Enterprise Edition 4.6.8
http://download.csdn.net/source/513053
Raize Components v4.3.2
http://www.delphifans.com/SoftView/SoftView_23.html
ExcelExport3.5
http://www.delphifans.com/SoftView/SoftView_2376.html
踏血流红 2008年7月10日 15时44分11秒