用PowerBuilder5.0开发“指标分析系统”
山东 刘茂诚
“指标类”查询软件一般情况下都作成图、表、文查询的形式,在表格中描述出具体的数据,在图中形象地作一描述和对比,有的还要用一段文字作为补充说明。笔者在作了大量的分析之后,觉得用PB5和ORACLE7开发“指标分析系统”最为合适,中间还有通过ODBC,调用DBASE(FOXBASE)库的操作,现将开发和应用中的一些体会总结成文,供同行们参考。
本系统的运行结构呈CLIENT/SERVER型,SERVER为COMPAQ5/166服务器
,上边安装了UNIX操作系统和ORACLE7数据库。CLIENT端通过HUB、ROUTER(远程接MODEM)与SERVER连接,开发、运行平台和工具是WINDOWS3.1、WIN95、PB5,CLIENT端通过FTP、SQL*NET
V2或NFS进网工作。系统总体网络协议为TCP/IP。
通过该系统可查询到历年的一些指标数据,包括劳资、财务、生产、经营、文教卫生等方面的一些指标信息,并由此数据绘出相应的对比图形,并附有文字说明和历史图片等。查询数据多以动态数据窗口产生,图形的数据是源于数据窗口的。文字说明部分存入ORACLE库中,用MLE(多行编辑器)输入、输出,PB5中的MLE可存放较大的文本文件,突破了PB4中32K的限制,所以,可将大量文字资料存放、查询。一些原始资料,如建筑、生产场地、历史背景图等作成了BMP图片,存入ORACLE库中,查询时调入图形框。
技术难点及解决的方法
1.PB5和ORACLE7及其它库的连接
PB5可通过本身提供的功能和ORACLE7做连接,举例如下:
(a)和某一数据库作固定连接
//数据库标识符
SQLCA.DBMS =″o71″
//要访问的ORACLE用户
SQLCA.LogID =″lnzb″
SQLCA.LogPass =″lnzbpwd″
SQLCA.UserID =″lnzb″
//用SQL*NET2和ORACLE库连接
SQLCA.ServerName=″@ora7″
Connect using sqlca;
以上的Script语句描述了和某一台SERVER上的ORACLE库的连接过程。
(b)和多个ORACLE数据库的活动连接
所谓活动连接,指的是通过修改参数,PB5可随机地连接于网上的每个ORACLE库,实现方法如下:
// This script will read all the database values from PB.INI
SQLCA.DBMS =ProfileString(″PB.INI″,″Database″,″DBMS″, ″ ″)
SQLCA.Database =ProfileString(″PB.INI″,″Database″,″DataBase″, ″ ″)
SQLCA.LogID =ProfileString(″PB.INI″,″Database″,″LogID″, ″ ″)
SQLCA.LogPass =ProfileString(″PB.INI″,″Database″,″LogPassword″, ″ ″)
SQLCA.ServerName =ProfileString(″PB.INI″,″Database″,″ServerName″, ″
″)
SQLCA.UserID =ProfileString(″PB.INI″,″Database″,″UserID″, ″ ″)
SQLCA.DBPass =ProfileString(″PB.INI″,″Database″,″DatabasePassword″, ″
″)
SQLCA.Lock =ProfileString(″PB.INI″,″Database″,″Lock″, ″ ″)
SQLCA.DbParm =ProfileString(″PB.INI″,″Database″,″DbParm″, ″ ″)
以上语句在执行过程中,查找可搜索路径中的PB.INI文件,因为要连接的库的一些参数就存放于该文件中。
举一个PB.INI文件的例子如下:
[Database]
DBMS=O71 ORACLE v7.1
Database=
UserId=
DatabasePassword=
LogPassword=lnzbpsd
ServerName=@ora7
LogId=lnzb
Lock=
DbParm=
Prompt=0
通过修改以上PB.INI中的参数,就可以改变要连接的库和连接方式(比如说用SQL*NET
TCP1还是SQL*NET V2等),所以称其为活动连接。
PB5 也可以通过ODBC和ORACLE库连接,但速度较慢,没必要采用这种方式,不过可以用来和其它库(如:DBASE等)作连接,举一个例子说明PB5调用DBASE库的方法:
odbcdbf=CREATE TRANSACTION;
odbcdbf.DBMS = ″ODBC″
odbcdbf.database = ″″
odbcdbf.userid = ″public″
odbcdbf.dbpass = ″″
odbcdbf.logid = ″″
odbcdbf.logpass = ″″
odbcdbf.servername = ″lnzb.dbs″
odbcdbf.dbparm=″Connectstring='DSN=lnzb.dbs;DBQ=c:\1nzb\dbs;FIL=dBase3;'″
Connect using odbcdbf;
上面介绍的是和DBASE库作固定连接的例子,当然也可以作成活动的,将在Configure
ODBC中创建和配置好的参数存入参数文件(如:PB.INI)中,通过修改参数,就能够操作多个“目录”下的DBASE库。
2.灵活使用动态数据窗口
动态数据窗口指的是在程序的运行过程中通过SQL语句的改变动态地创建、修改数据窗口的内容和表现形式,它多用在对同类型对象的描述过程中,“指标类”的查询软件用动态数据窗口来编制,表现形式一致、构造界面统一、编程效率高,当然还有其它一些优点。
创建一个数据窗口,并由此绘出图形,动态地创建数据窗口dw_1:
dw_1.create(syntaxFromSQL(SQLCA, ″SELECT sj,swdz FROM hyscjszb where swdz>0&
and ytmh='″+rowcha+″' order by sj″,″style=(type=grid)″,err))
根据dw_1中的数据绘出图形:
rows = rowcount(dw_1)
if rows>0 then
gr_1.SetRedraw(False)
gr_1.reset(all!)
gr_1.addseries(″dz1″)
sum=0
fromn=mid(getitemstring(dw_1,1,1),1,4)
endofn=mid(getitemstring(dw_1,rows,1),1,4)
for i =1 to rows
xis=mid(getitemstring(dw_1,i,1),3,2)
yis=getitemnumber(dw_1,i,2)
if isnull(yis) then
yis=0
end if
sum=sum+yis
gr_1.adddata(1, yis,xis)
next
gr_1.SetRedraw(True)
st_7.text=string(sum)
if mc=″21″ or mc=″22″ then
st_6.visible=false
st_7.visible=false
end if
st_6.text=″累计:″+″(″+fromn+″----″+endofn+″)″
动态数据窗口的表头部分在建表时或通过修改表结构做好,不然会出现表中的字段名(英文字符)作为表头,不直观。
小数点位数、显示方式也要在表结构中定义好,不然,动态数据窗口将会用“General”方式显示数据,不会作到小数位数一致和小数点自动对齐等。举一个例子,要想使显示数据自动保留两位小数并使小数点自动对齐,就要在表结构中将“Format”设为
“0.00”。
数据变量类型的定义:一些整型指标值尽量不要定义成INT类型,因为一旦超过32767就会出错,一定要定义成LONG类型;带小数的指标值要定义成DOUBLE型,若定义成LONG类型,会自动舍去小数部分,出现数据错误。
自动汇总有关数据项,用EXCEL输出汇总表
用PB5做正规表的输出不是很方便,但通过PB5,可将数据窗口中的数据生成EXCEL文件簿格式,再通过EXCEL的数据链接,将对应数据调入事先定义好的EXCEL标准输出表中,按用户的要求输出。
PB5生成EXCEL格式文件的SCRIPT语句举例如下:
dw_1.SaveAs(″c:\zbfxxt\sj.xls″,excel!,true)
创建同一坐标内的多条曲线
string pp
long i,j
st_1.text=w_ytktt.ddlb_1.text+″年″+vv+″折线图″
delete from lzht ;
commit;
ni=mid(W_ytktt.ddlb_1.text,3,2)
for j=1 to 12
if j<10 then
ny=ni+″0″+string(j)
else
ny=ni+string(j)
end if
for i=1 to 5
if i=1 then
pp=″折线图1″
select a84 into :la from lsl_a where x1=:ny and ofn=:ytm;end if
if i=2 then
pp=″折线图2″
select a85 into :la from lsl_a where x1=:ny and ofn=:ytm;end if
if i=3 then
pp=″折线图3″
select a34 into :la from lsl_a where x1=:ny and ofn=:ytm;end if
if i=4 then
pp=″折线图4″
select a31 into :la from lsl_a where x1=:ny and ofn=:ytm;
end if
if i=5 then
pp=″折线图5″
select a30 into :la from lsl_a where x1=:ny and ofn=:ytm;end if
insert into lzht(yue,zdm,zdz) values(:j,:pp,:la) using sqlca;
next
next
commit;
dw_1.SetTransObject(sqlca)
dw_1.Reset()
dw_1.Retrieve()