
Delphi是Borland公司研发的基于PASCAL语言的Windows平台应用程式研发工具,他将可视化编程(Visual Programming)和面向对象(Object-Oriented)的卓越长处结合在PASCAL语言研发平台上,而且同时能够支持Client/Server模式的SQL数据库访问和ODBC(研发数据库互连),是个真正面向对象的研发工具。
Delphi最吸引人的特点是他的强大的数据库访问能力,他主要通过使用数据库引擎(Borland Database Engine,简称BDE)来访问本地数据库和远程数据库。但对于用户而言,不必直接编程访问BDE,而只需通过采用窗体(FORM)和大量方便且实用的数据库访问元件(Component)来实现,通过ReportSmith报表生成器能够生成多种随心所欲的报表。
但是,用ReportSmith制作的各类报表,只便于输出至打印机上打印出来,若想把报表在屏幕上显示,则还需调用ReportView。而ReportView窗口界面对不太懂Delphi和Windows操作的普通用户来说,不直观,也不易操作。怎样制作并在屏幕上显示出直观的二维统计报表,这是本文所要阐述的主要问题。
以表格形式显示数据库内容一般地采用下面两种方式: ●纵向列表(如图1) ●交叉统计列表(如图2)
一、纵向列表 Delphi能够用TDBGRID控件,以表格形式很方便地显示单一或多数据库纵向列表。一般采用两种方法实现: (一)采用TTable和Tdatasource、TDbgrid控件 在窗体中引入上述三个控件,并在Ttable中控件指出要访问的数据库存放路径及数据库名,在Tdatasource控件中指出数据源和Ttable相连,在TDbgrid控件中指出显示Tdatasource数据源内容,程式运行后,则显示出如图1所示的数据库纵向列表。 该种方法一般用来显示单数据库表格或一对多两个数据库表格。
(二)采用TQuery和Tdatasource、TDbgrid控件
同样,在窗体中引入上述三个控件,并在TQuery控件中用SQL语句给出对有关数据库的查询,在Tdatasource控件中指出数据源和TQuery相连,在TDbgrid控件中指出显示查询的结果。程式运行后,则显示出如图1所示的数据库纵向列表。 该种方法一般用于两个以上的多数据库查询。 在TQuery控件中建立SQL查询有两种方法,一种是在程式设计阶段使用SQL查询,即为静态查询,第二种是在程式运行阶段使用SQL查询,即为动态查询。 1. 静态查询 编写程式时,在窗体中放置Tquery元件,并配置对象名称,如Query1。使用Delphi对象检测器Object,双击Query 1对象的SQL属性,则激活SQL语句输入框,根据需要输入SELECT语句。当程式运行后,则显示出数据库纵向列表。静态查询比较简单,但实用性差。对于较复杂的查询,一般采用动态查询。 2. 动态查询同样,在编写程式时,在窗体中放置TQUERY元件,并配置对象名称,如Query 1。在相关的事件函数中输入SQL语句,例如:
WITH QUERY 1 DO BEGIN SQL.CLEAR; SQL.ADD(SELECTDW,COUNT(DW)FROM B_BASETJ F,B_INFO E); SQL.ADD(WHERE F.”SHBZCODE”=E.”SHBZCODE”GROUP BY DW); OPEN; END;
当程式运行后,由某一事件激发,则显示出查询结果纵向列表。
二、交叉统计列表 在Delphi环境下,无论用上述哪种方法制作数据库纵向列表,都是相对容易的。但要生成如图2所示二维统计报表,则并非易事。 下面以笔者研发的《社会养老保险管理系统--统计管理》中的一段程式为例,周详说明图2所示交叉统计列表的制作。
(一)调用数据库B_BASETJ.DB和B_INFO.DB 上述两数据库的结构分别为: B_BASETJ.DB B_INFO.DB
| 字段名 |
字段类型 |
字段长度 |
字段名 |
字段类型 |
字段长度 |
| dw |
a |
4(单位代码) |
shbzcode |
a |
21(社会保障号码) |
| shbzcode |
a |
21(社会保障号码) |
attribution |
a |
10(工作属性) |
| cadre_zw |
a |
4(干部职务) |
sex |
a |
2(性别) |
在B_INFO.DB数据库中存放着各人的基本情况,其中ATTRIBUTION字段包含固定工、农民合同工等工作属性;CADRE_ZW字段包含干部职务,若该字段内容为空,则表示为工人。
(二)窗口界面设计及各组件属性说明 用到的重要组件及其属性如下: QYERYTB1:TQUERY; DataSourceTB1:Tdatasource; Datasourcename=DataSourceTB1 Dataset=QYERYTB1 SG11:TstringGrid; BTNEXIT:Tbutton;
(三)程式代码及其分析 程式中主要通过使用TStringGrid和TQUERY控件来生成交叉统计列表。其中TStringGrid控件以二维网格形式显示字符型数据表格,CELL[I,K]为表格中的一个数据单元,K为行号,I为列号,K、I的起始值为0;TQUERY控件的作用是利用SQL语句统计出表格中某一列数据,如图2表格中共有6列,则需6次调用TQUERY。
本程式还配置了公共程式段procedure COL(var I,k:INTEGER),这一子程式将被多次调用,用于填写表格中某一列数据。 主要程式代码如下: unit T1; interface uses
SysUtils,WinTypes,WinProcs,Messages,Classes,Graphics,Controls,Forms,Dialogs, StdCtrls,ExtCtrls,Grids,DB,DBTables, DBGrids,Report;
type TT1FORM=class(TForm) BTNEXIT:TButton; SG11:TStringGrid; Labell:TLabel; QueryTB1:TQuery; DataSourceTB1:TDataSource; procedure FormCreate(Sender:TObject); procedure BTNEXIT Click(Sender:TObject); private PROCEDURE COL(VAR I,K:INTEGER); PROCEDURE CC(VAR I,K:INTEGER); {Private declarations} public {Public declarations} end;
var T1FORM:TT1FORM;
implementation
PROCEDURE tt1form.COL(VAR I,K:INTEGER);{用FOR...DO循环填写SG11表格中第I列的VAR J:INTEGER;值} BEGIN WITH SG11 DO BEGIN QUERYTB1.FIRST; FOR J:=2 TO K-1 DO BEGIN IF CELLS[0,J]=QUERYTB1.FIELDS[0].ASSTRING THEN BEGIN CELLS[I,J]:=QUERYTB1.FIELDS[1].ASSTRING; QUERYTB1.NEXT; CELLS[I,1]:=INTTOSTR(STRTOINT(CELLS[I,1])+STRTOINT(CELLS[I,J])); END ELSE CELLS[I,J]:=INTTOSTR(0); END; END; END;
PROCEDURE Tt1form.CC(VAR I,K:INTEGER); VAR J:INTEGER; BEGIN WITH SG11 DO BEGIN FOR J:=1 TO K-1 DO CELLS[I,J]:=INTTOSTR(STRTOINT(CELLS[1,J]-STRTOINT(CELLS[I-1,J]))); END; END;
procedure TT1FORM.FormCreate(Sender:TObject); VAR R,I,K,J:INTEGER; begin WITH SGLL DO BEGIN CELLS[0,0]:=单位 CELLS[1,0]:=总人数; CELLS[2,0]:=固定; CELLS[3,0]:=合同; CELLS[4,0]:=干部; CELLS[5,0]:=工人; FOR I:=1 TO 5 DO BEGIN CELLS[I,1]:=INTTOSTR(0); END; END;
WITH QUERYTB1 DO BEGIN SQL.CLEAR; SQL.ADD(SELECT DW,COUNT(DW)FROM B_BASETJ F,B_INFO E); SQL.ADD(WHERE F.”SHBZCODE”=E.”SHBZCODE”GROUP BY DW); OPEN; R:=RECORDCOUNT+2; SG11.ROWCOUNT:=R; SG11.CELLS[0,1]:=合计; FIRST; K:=R; FOR J:=2 TO K DO BEGIN SG11.CELLS[0,J]:=FIELDS[0].ASSTRING; NEXT; END;
I:=1; COL(I,K); SQL.CLEAR; SQL.ADD(SELECT DW,COUNT(E.”DW”)); SQL.ADD(FROM “B_BASETJ.DB”E,B_INFO F WHERE E.”SHBZCODE”=F.”SHBZCODE” AND F
.”ATTRIBUTION”=”固定职工”GROUP BY DW);
I:=2; OPEN; COL(I,K); SQL.CLEAR; SQL.ADD(SELECT DW,COUNT(E.”DW”)); SQL.ADD(FROM “B_BASETJ.DB”E,B_INFO F WHERE E.”SHBZCODE”=F.”SHBZCODE” AND F.”
ATTRIBUTION”=”农民合同工”GROUP BY DW);
I:=3; CC(I,K); SQL.CLEAR; SQL.ADD(SELECT DW,COUNT(E.”DW”)); SQL.ADD(FROM “B_BASETJ.DB”E,B_INFO F WHERE E.”SHBZCODE”=F.”SHBZCODE”AND F.”
CADRE_ZW”$#@60;$#@62;””GROUP BY DW);
I:=4; OPEN; COL(I,K);
I:=5; CC(I,K); END; end;
......
end.
查看本文来源 |