分享
 
 
 

用树型结构表示科目代码的一种高效算法

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

用树型结构表示科目代码的一种高效算法

松本电工实业有限公司电脑部

舒嵩嵩

---- 在很多常见的财务软件中,科目代码一般都用树型结构来显示。要实现这一点,通常的做法是用多个(嵌套)循环,甚至递归等算法,将科目表中的代码"织"成树,但这样不但算法复杂,而且执行效率低。本人在实际的开发应用中,摸索出一种简单高效的算法,在此和盆托出,只在抛砖引玉,找出最佳解决方案。下面介绍在Delphi中的实现方法。

一.表结构

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

字段名 类型 长度 说明

aCode 字符型 20 科目代码

aName 字符型 30 科目代码名称

...... ...... ...... ......

表(一)

---- 其中,科目代码aCode的数据类型一定要字符型(一定),长度按具体要求而定,假如要支持六级编码,且代码结构是"3-2-2-2-2-2",则该字段的长度不小于18,而其他字段则不作要求 。另外,要为字段aCode建一索引(切记),因为要用它来排序。

二.编写程序

---- 1.新建一Project:CodeTree.drp,主窗体命名为frmMain,单元存为Main.Pas。在frmMain上添加一TtreeView控件,命名为tveCode,一个TImageList,命名为imgIcon,并装入三个Icon和Bmp,最后添加一Ttable控件,命名tblCode。

frmMain和各控件的属性按表(二)设置:

组件 属性 设置

FrmMain Caption '科目代码'

Font 宋体 9号

BorderStyle BsDialog

TvwCode Images ImgIcon

ReadOnly True

ImgIcon ImageList 装入三个图标

BtnClose Caption 关闭(C)

表(二)

---- 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,SFirstNodeTxt);

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],ShowTxt);

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是求某一科目代码的级数,例如,有一科目代码"10102",在代码结构是"322222"的情况下,调用函数GetLevel('322222','10102')将返回整数2 。

---- 当然,本文的核心是LoadCode函数,该函数用了一个循环来遍历数据表Code.DB的所有记录,将字段aCode和aName的内容按层次显示出来。而在该函数中定义的二维数组MyNode[0..6],则显得优为重要,在这里,它作用类似于递归中的栈。因为在TTreeView添加子节点的方法AddChild(Node: TTreeNode; const S: string)中,要为其指定一父节点作为参数,而父节点的代码级数一定是要添加节点的代码级数减1,所以只要用一数组来动态保存和指定父节点就成功了。

三.运行结果

---- 好了,现在把Code.DB复制到和可执行文件相同的目录下,按下F9键编译运行,本人运行的效果如图(一)。只要在以上的基础上加以完善,如增加维护功能,就可搬到实际应用中了。当然,本算法不单能用在科目代码上,其他类似的树型结构都能奏效。本人就已将此算法应用于[科目代码]、[物料清单(BOM)]、[库房管理]和[物料主文件]等多个模块中,取得令人满意的效果。

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有