您的位置:首页 > 数据库

基于数据库(access)层次编码记录对TreeView的操作(实现自动编码,灵活控制编码规则和编码层次)

2008-10-17 22:33 671 查看


{-----------------------------------------------------------------------------

根据有规则的编码层次结构数据构建TreeView

使用时直接引用此单元即可。

最后修改:米铁强

最后完成日期:2009-7-7

-----------------------------------------------------------------------------}

unit U_LevelDBTree;

interface

uses ComCtrls, ADODB, DB, Classes, SysUtils, StrUtils, windows, Controls, forms,

math;

{-----------------------------------------------------------------------------

定义的常量值,通过更改此处的内容,可以灵活的改变树的编码格式及层次。

-----------------------------------------------------------------------------}

const

cTreeCodeFormat = '222'; //编码格式为 XX XX XX

cTreeMaxLevel = 3; //最大编码层次

cTreeRootTxt = '商品类别'; //树根结点名称

{-----------------------------------------------------------------------------

函数名称:LoadTree

功能:根据数据库记录初始化树

参数及说明:tree:目标Treeview,treeDB:数据集,sID:字段名称,sCaption:字段名称。

返回值:无

-----------------------------------------------------------------------------}

procedure LoadTree(tree: Ttreeview; treeDB: TADOTable; sID, sCaption: string);

{-----------------------------------------------------------------------------

函数名称:GetNodeLevel

功能:获取某一节点的层次

参数及说明:sFormat:编码格式, sCode:编码。

返回值:integer

-----------------------------------------------------------------------------}

function GetNodeLevel(sFormat, sCode: string): integer;

{-----------------------------------------------------------------------------

函数名称:MaxCount

功能:得到某一层次的最大允许节点数量

参数及说明:sLevel:层次。

返回值:integer

-----------------------------------------------------------------------------}

function MaxTotal(sLevel: integer): Integer;

{----------------------------------------------------------------------------

函数名称:GetCurrentNodeCode

功能:得到当前节点的编码

参数及说明:curNode:当前节点。

返回值:string

-----------------------------------------------------------------------------}

function GetCurrentNodeCode(curNode: TTreeNode): string;

{-----------------------------------------------------------------------------

函数名称:GetNewCode

功能:得到新建节点的编码

参数及说明:TempDB:临时查询;sID:字段名称;sTable:表名称,curNode:当前节点,

Child:新建节点是否为子节点。

返回值:string

-----------------------------------------------------------------------------}

function GetNewCode(TempDB: TAdoquery; sID, sTable: string; curNode: TTreenode;

Child: boolean): string;

{-----------------------------------------------------------------------------

函数名称:UpdateTreeAndDB

功能:同步更新树结构和数据库内容(包括新增、删除、修改)

参数及说明:tree: 需要操作的树; CurTreeNode: 当前节点; treeDB: 数据表; sid, sCaption:字段名称;

nodeTxt:字段值, state: 操作状态; NewID: 新节点编号,默认为''。

返回值:无

-----------------------------------------------------------------------------}

procedure UpdateTreeAndDB(tree: TTreeView; CurTreeNode: TTreeNode; treeDB:

TADOTable; sid, sCaption, nodeTxt, state: string; NewID: string = '');

{-----------------------------------------------------------------------------

函数名称:UpdateTable

功能:同步数据库内容(包括新增、删除、修改)(内部参数)

参数及说明:treeDB: 关联的数据表; sid, sCaption:字段名称; ClassID, ClassName:

字段值; state: 操作状态。

返回值:无

-----------------------------------------------------------------------------}

procedure UpdateTable(treeDB: TADOTable; sid, sCaption, ClassID, ClassName:

string; state: string);

implementation

procedure LoadTree(tree: Ttreeview; treeDB: TADOTable; sID, sCaption: string);

//初始化树

var

curID, nodeTxt: string;

level: integer;

mynode: array[0..cTreeMaxLevel] of TTreenode;

begin //初始化变量

tree.Items.BeginUpdate;

tree.Enabled := True;

tree.Items.Clear;

level := 0;

//设置根节点

mynode[level] := tree.items.add(Tree.Topitem, cTreeRootTxt);

mynode[level].ImageIndex := 1;

//遍历数据表,利用编码字段记录排序规律,依次添加树节点

with treeDB do

begin

try

Filtered := False;

if not Active then

open;

first;

while not Eof do

begin

curID := trim(FieldByName(sID).AsString);

nodeTxt := curID + '-' + trim(FieldByName(sCaption).AsString);

level := GetNodeLevel(cTreeCodeFormat, curID);

//这里返回代码的层次数

if level > 0 then

begin

//增加下一节点时,用添加子节点的方法可轻松实现节点间的层次关系

//注意:这里的父节点是用当前节点的上一级节点mynode[level-1]

mynode[level] := tree.items.addchild(mynode[level - 1], nodeTxt);

mynode[level].ImageIndex := 2;

end;

next; //下一条记录

end;

finally

close;

end;

mynode[0].expand(true); //这里指明根节点是否展开;

tree.Items.EndUpdate;

mynode[0].Selected := True; //选择根节点

tree.SetFocus;

end;

end;

function 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

else

if (sFormat <> '') and (sCode = '') then

level := 0;

result := level;

end;

function MaxTotal(sLevel: integer): Integer; //得到某一层次的最大允许节点数量

var

m, i: integer;

tmp: string;

begin

tmp := '';

m := StrToInt(ctreecodeformat[slevel]);

for i := 1 to m do

begin

tmp := tmp + '9';

end;

Result := StrToInt(tmp);

end;

//给新建节点自动编码

function GetNewCode(TempDB: TAdoquery; sID, sTable: string; curNode: TTreenode;

Child: boolean): string;

var

tmpSQL: string;

i, NodeLevel, n: Integer;

NodeCode: string;

preZero, surZero, Prefix, surfix: string; //前缀 ,后缀

min, max: string; //查询区间

cMaxTotal, ChildMaxTotal, icount: Integer;

begin

icount := 0;

NodeCode := getcurrentNodeCode(curNode);

NodeLevel := GetNodeLevel(cTreeCodeFormat, nodecode);

tmpSQL :=

'select %s from %s where (%s > "%s") and (%s <= "%s") and (len(%s) = len("%s"))order by %s';

{ tmpSQL :=

'select %s from %s where (cvar(%s) > %s) and (cvar(%s) <= %s) order by %s';}

preZero := ''; //初始化前缀补零数量

surZero := ''; //初始化后缀补零数量

for i := 1 to StrToInt(cTreeCodeFormat[1]) - 1 do

preZero := preZero + '0'; //前面需补零的数量,这是固定的

if Child then //如果新建节点是子节点

begin

if NodeLevel = ctreemaxlevel then

begin

MessageBox(Application.Handle,

PChar(Format('系统允许的最大嵌套层次为%d层,无法添加子项。',

[ctreemaxlevel])),

'警告', MB_OK + MB_ICONWARNING);

end;

Prefix := NodeCode;

//cMaxTotal := MaxTotal(NodeLevel);

ChildMaxTotal := MaxTotal(Nodelevel + 1);

for i := 1 to StrToInt(cTreeCodeFormat[NodeLevel + 1]) - 1 do

begin

surZero := surZero + '0'

end;

surfix := surZero + '1';

end

else //如果是新增同级节点

begin

if NodeLevel < 1 then //根目录无法增加同级节点

begin

MessageBox(application.Handle, '根目录下只能新增子项目。', '警告', MB_OK +

MB_ICONWARNING);

Result := '';

Exit;

end

else

begin

for i := 1 to NodeLevel - 1 do

icount := icount + StrToInt(MidStr(cTreeCodeFormat, i, 1));

Prefix := LeftStr(nodecode, icount);

//cMaxTotal := MaxTotal(NodeLevel - 1);

ChildMaxTotal := MaxTotal(Nodelevel);

for i := 1 to StrToInt(cTreeCodeFormat[NodeLevel]) - 1 do

begin

surzero := surzero + '0'

end;

surfix := surzero + '1';

end;

end;

min := prefix + surzero + '0';

max := Prefix + IntToStr(Childmaxtotal);

tmpSQL := Format(tmpSQL, [sID, sTable, sID, min, sID, max, sID, max, sID]);

TempDB.Close;

TempDB.SQL.text := tmpsql;

TempDB.Open;

TempDB.last;

if TempDB.RecordCount < 1 then //如果没有节点,则从第1个节点编起。

Result := Prefix + surfix

else

if TempDB.fieldbyname(sID).asstring < max then

begin

if Child then

for i := 1 to NodeLevel + 1 do

n := n + strtoint(midstr(cTreeCodeFormat, NodeLevel - 1, 1))

else

for i := 1 to NodeLevel do

n := n + strtoint(midstr(cTreeCodeFormat, NodeLevel - 1, 1));

if (Length(IntToStr(TempDB.fieldbyname(sID).AsInteger)) < n) and (TempDB.fieldbyname(sID).AsInteger <> 9)then //自动补"0"

result := prezero + IntToStr(TempDB.fieldbyname(sID).asinteger + 1)

else

result := IntToStr(TempDB.fieldbyname(sID).asinteger + 1);

end

else

begin

MessageBox(Application.Handle,

'当前项目已达到允许的最大数量,无法继续添加。',

'警告', MB_OK + MB_ICONWARNING);

Result := '';

end;

end;

function GetCurrentNodeCode(curNode: TTreeNode): string;

//获得当前节点的编码

var

li_pos: integer;

ClassID: string;

begin

li_pos := pos('-', curNode.Text);

ClassID := MidStr(curNode.Text, 1, li_pos - 1);

result := ClassID;

end;

//以下过程在新增、删除、修改记录时,同步更新树形结构和数据库

procedure UpdateTreeAndDB(tree: TTreeView; CurTreeNode: TTreeNode; treeDB:

TADOTable; sid, sCaption, nodeTxt, state: string; NewID: string = '');

var

tmpNode: TTreeNode;

oldid: string;

begin

oldid := GetCurrentNodeCode(CurTreeNode);

if UpperCase(state) = 'ADD' then //添加平级节点

begin

CurTreeNode := tree.items.add(curtreenode, NewID + '-' + nodeTxt);

CurTreeNode.ImageIndex := 2;

end;

if UpperCase(state) = 'ADDCHILD' then //添加子节点

begin

CurTreeNode := tree.items.addchild(curtreenode, NewID + '-' + nodeTxt);

CurTreeNode.ImageIndex := 2;

end;

if UpperCase(state) = 'DEL' then

begin

if CurTreeNode.Level = 0 then

begin

MessageBox(Application.Handle, '根节点无法删除。', '错误', MB_OK +

MB_ICONSTOP);

exit;

end;

try

tmpNode := CurTreeNode.GetPrev;

except

try

tmpNode := CurTreeNode.Getnext;

except

tmpNode := CurTreeNode.Parent;

end;

end;

NewID := GetCurrentNodeCode(CurTreeNode);

CurTreeNode.DeleteChildren;

CurTreeNode.delete;

CurTreeNode := tmpNode;

end;

if UpperCase(state) = 'EDIT' then

begin

CurTreeNode.Text := NewID + '-' + nodeTxt;

end;

CurTreeNode.Selected := true;

treeDB.Active := true;

treeDB.Locate(sid, oldID, []);

UpdateTable(treeDB, sid, sCaption, Newid, nodetxt, state); //更新表

end;

//以下过程在新增、删除、修改记录时,同步更新数据库表

procedure UpdateTable(treeDB: TADOTable; sid, sCaption, ClassID, ClassName:

string; state: string);

begin

if (UpperCase(state) = 'ADD') or (UpperCase(state) = 'ADDCHILD') then

begin

//treeDB.Active := True;

treeDB.Insert;

treeDB.SetFields([ClassID, ClassName]);

treeDB.Post;

end;

if UpperCase(state) = 'DEL' then

begin

//treeDB.Active := True;

treeDB.Filtered := False;

treeDB.Filter := sid + ' like ' + QuotedStr(classid + '%');

treeDB.Filtered := True;

treeDB.First;

while not treeDB.Eof do

begin

treeDB.Delete;

end;

treeDB.Filtered := False;

end;

if UpperCase(state) = 'EDIT' then

begin

//treeDB.Active := True;

treeDB.Edit;

treeDB.FieldByName(sid).AsString := ClassID;

treeDB.FieldByName(scaption).AsString := ClassName;

treeDB.Post;

end;

end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: