用树型结构表示科目代码

   一、表结构

    首先建立如下结构的数据表Code.DB,并输入一些测试数据

    其中,科目代码aCode的数据类型一定要字符型(一定),长度按具

体要求而定,假如要

支持六级编码,且代码结构是"3-2-2-2-2-2",则该字段的长度不小于1

8,而其他字段则不

作要求 。另外,要为字段aCode建一索引(切记),因为要用它来排序。

    二、编写程序

    1. 新建一Project:CodeTree.drp,主窗体命名为frmMain,单元存

Main.Pas。在fr

mMain上添加一个TtreeView控件,命名为tveCode,一个TImageList,命

名为imgIcon,并装

入三个Icon和Bmp,最后添加一个Ttable控件,命名tblCode。

    2. 单元main.pas的完整源代码如下:

    unit Main;

    interface

    uses

    Windows, Messages, SysUtils, Classes, Graphics, Controls

, Forms, Dialogs

    Db, DBTables, ComCtrls, ImgList, StdCtrls;

    type

    TForm1 = class(TForm)

    tvwCode: TTreeView;

    tblCode: TTable;

    ImageList1: TImageList;

    btnClose: TButton;

    procedure FormCreate(Sender: TObject);

    procedure btnCloseClick(Sender: TObject);

    private

    { Private declarations }

    function LoadCode(crTbl:TDBDataSet):Integer;

    function GetLevel(sFormat,sCode:String):Integer;

    public

    { Public declarations }

    end;

    var

    Form1: TForm1;

    const

    SCodeFormat =‘322222'; //科目代码结构

    SFirstNodeTxt =科目代码'; //首节点显示的文字

    implementation

    {$R *.DFM}

    //以下函数是本文的重点部分,其主要功能是用一循环将Code.db

表中的科目代码和

科目代码名称显示出来

    function TForm1.LoadCode(crTbl:TDBDataSet):Integer;

    var NowID,sName,ShowTxt:String;

    i,Level:Integer;

    MyNode:array[0..6]of TTreeNode;//保存各级节点,最长支持6

(重点)

    begin

    Screen.Cursor:=crHourGlass;

    Level:=0;

    With crTbl do

    begin

     try

     if not Active then Open;

    First;

     tvwCode.Items.Clear;

     //以下是增加第一项

    MyNode[Level]:=tvwCode.Items.Add(tvwCode.TopItem,SFirstN

odeTxt);

    MyNode[Level].ImageIndex:=0;

    MyNode[Level].SelectedIndex:=0;

     //以上是增加第一项

    While Not Eof do

     begin

    NowID:=Trim(FieldByName(‘aCode').AsString);

    ShowTxt:=NowID+‘ '+FieldByName(‘aName').AsString;

    Level:=GetLevel(SCodeFormat,NowID); //返回代码的级数

     //以下是增加子项

     //以下用上一级节点为父节点添加子节点

     if Level>0 then//确保代码符合标准

     begin

    MyNode[Level]:=tvwCode.Items.AddChild(MyNode[Level-1],Sh

owTxt);

    MyNode[Level].ImageIndex:=1;

    MyNode[Level].SelectedIndex:=2;

    end;

     //以上是增加子项

    Next;

    end;

    finally

    Close;

    end;

    end;

    MyNode[0].Expand(False);//将首节点展开

    Screen.Cursor:=crDefault;

    end;

    //以上函数将Code.db表中的科目代码和科目代码名称显示出来

    //下面函数的功能是返回一代码的级数,参数sFormat传递科目代

码结构;

    //参数sCode传递某一科目代码

    function TForm1.GetLevel(sFormat,sCode:String):Integer;

    var i,Level,iLen:Integer;

    begin

    Level:=-1;//如果代码不符合标准,则返回-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;

    //上面函数的功能是返回一代码的级数

    procedure TForm1.FormCreate(Sender: TObject);

    begin

     with tblCode do

     begin

    DatabaseName:=ParamStr(1); //使tblCode的DatabaseName指向

应用程序所在的路

    TableName:=‘Code.DB';

     //指向数据表Code.DB

    Open;

    IndexFieldNames:=‘aCode'; //按字段aCode排序(不要漏掉)

     end;

    LoadCode(tblCode);

    end;

    procedure TForm1.btnCloseClick(Sender: TObject);

    begin

    Close;

    end;

    end.

    其中,常量ScodeFormat是科目代码的代码结构,其定义的规则一

定要和数据表Code.

.DB中的字段aCode的值相符。所以在实际应用中,让用户新增科目代

码时,必须严格检查

其规范性,只有完全符合事先定义的代码结构,才能添加入库。

函数GetLevel是求某一科目代码的级数,例如,有一科目代码"101

02",在代码结构是

"322222"的情况下,调用函数GetLevel(‘322222',‘10102')将返回

整数2 。

    当然,本文的核心是LoadCode函数,该函数用了一个循环来遍历数

据表Code.DB的所有

记录,将字段aCode和aName的内容按层次显示出来。而在该函数中定

义的二维数组MyNod

e[0..6],则显得尤为重要,在这里,它的作用类似于递归中的栈。因为

TTreeView添加子

节点的方法AddChild(Node: TTreeNode; const S: string)中,要为

其指定一父节点作为

参数,而父节点的代码级数一定是要添加节点的代码级数减1,所以只

要用一数组来动态保

存和指定父节点就成功了。

    三、运行结果

    好了,现在把Code.DB复制到和可执行文件相同的目录下,按下F9

键编译运行,运行的

效果如图。只要在它的基础上加以完善,如增加维护功能,就可搬到实

际应用中了。当然

,本算法不单能用在科目代码上,其他类似的树型结构都能奏效。

    以上程序在中文Windows 9x、Delphi 4 C/S环境下编译通过。

转载于:https://www.cnblogs.com/myamanda/articles/1527916.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值