摘 要:本文主要介绍了在使用Visual Foxpro 编写数据库应用程序时,如何根据实际需要随机选取字段生成自由报表。
关键词:VFP 数据库
一、存在的问题
用VFP报表生成器生成的报表,对于用户所需的某一数据库的任意字段组合报表,就显得不是那样运用自如。因为,一方面软件开发时,无法考虑到日后用户所需报表的所有格式。另一方面,由于所设计好的报表格式文件已编译成可执行文件,即使修改了.FRX和.FRT文件结构内容,也需在开发环境下重新编译,对用户来讲是无法实现的。例如职工档案库中有许多项目,需一份职工职称年龄表,进行报表上报,此类问题就比较难解决。
二、解决方案
1.自己编写一个简单的报表生成程序,可以根据随机选取的字段生成表头、表格线及打印项目,将报表每一行看做是一条记录,然后进行报表打印。
2.运用VFP与Excel 的交换数据及在VFP中全面控制Excel的操作(即自动服务器),就可以很好的解决这一问题。关于如何控制Excel,一方面可以通过Excel的帮助文件的VBA语法,另一方面也有相当多的文章关于控制Excel的语法。值得注意的是:1、为提高效率,所有有关计算、小计、合计最好在VFP中进行,并写在相应的记录内;2、由于是两个软件,如果在有大量数据逐一插入Excel单元格时,显得速度较慢,所以如果数据量较大,应直接用VFP的数据表导出为Excel格式,再由VFP在后台控制Excel打开,并指定的Excel格式文件进行修改文档标题、列的名称、网格线型,以及根据纸张大小计算各列宽和调整字体大小。
本文着重谈第一种方案的实现。
三、实现办法
首先需要创建两个表文件,一个是所要打印的数据表的结构文件,本例为DYBX.DBF;一个是已选择字段的表文件,本例为PRNTMP.DBF。
表结构如下:
表结构: DYBX.DBF
字段 字段名 类型 宽度 小数位
1 FIELD_NAME 字符型 10
2 FIELD_TYPE 字符型 1
3 FIELD_LEN 数值型 3
4 FIELD_DEC 数值型 3
表结构: PRNTMP.DBF
字段 字段名 类型 宽度
1 ZDM 字符型 10
2 ZDCD 数值型 3
3 ZDLX 字符型 1
表结构: dyb.DBF
字段 字段名 类型 宽度
1 dybx 字符型 180
然后构建如下表单,左侧列表框的数据源为DYBX.DBF,右侧GRID的数据源为PRNTMP.DBF,按钮“增加项目”的作用是将选择字段增加到PRNTMP中,“删除项目”是将右侧选择字段从PRNTMP中删除,“生成报表”是据PRNTMP内容生成用于打印输出的表,“打印报表”是用REPORT命令将生成表打印输出。
************
左侧列表框属性
recordsource=dybx
右侧grid属性
recordsource=prntmp
数据环境:DYB,DYBX,ZGB,PRNTMP, 其中DYB属性exclusive为.t.,ZGB为人员档案数据表。
“增加项目”click代码:
local m.i,m.n,m.mc,m.cd
m.i=0
sele dybx
m.n=recn()
m.mc=field_name
sele prntmp
sum all zdcd to i
if i>160
=messagebox("超出表长,重新选择",64)
else
sele prntmp
go top
loca for trim(zdm)==trim(m.mc)
if found()
=messagebox("已有此字段!",64)
else
m.cd=dybx.field_len
if dybx.field_type=='D' &&日期型长度为10
m.cd=10
endif
if len(trim(dybx.field_name))>m.cd &&名称大于字段长度
m.cd=len(trim(dybx.field_name))
endif
appe blan
repl zdm with dybx.field_name,zdcd with m.cd,zdlx with dybx.field_type
endif
endif
thisform.grid1.refresh()
“删除项目”click代码:
sele prntmp
dele
thisform.grid1.refresh()
* * * * * * * * * * * * * * * * *
*生成报表按钮的程序代码
* * * * * * * * * * * * * * * * *
proc scbb
local z(20),z2(20)
dime z(20),z2(20)
c1="┌" &&初始化变量
c2="┐"
c3="┬"
c4="─"
c5="├"
c6="┤"
c7="│"
c8="┴"
c9="┼"
c10="└"
c11="┘"
m.jls=30
i0=0
i1=1
sele dyb &&要打印的表
zap
sele prntmp &&已选中字段的表
go top
l1=c1+c4+c4+c3
l2=c7+'序号'+c7
l3=c7+' '+c7
l4=c5+c4+c4+c9
l5=c10+c4+c4+c8
do whil !eof() &&生成表头
i2=zdcd/2+mod(zdcd,2)
for j=1 to i2
l1=l1+c4
l3=l3+" "
l4=l4+c4
l5=l5+c4
endfor
l2=l2+padc(trim(zdm),i2*2)
z(i1)=trim(zdm)
z2(i1)=zdcd
skip
if !eof()
l1=l1+c3
l2=l2+c7
l3=l3+c7
l4=l4+c9
l5=l5+c8
i1=i1+1
endif
enddo
i0=i1
l1=l1+c2
l2=l2+c7
l3=l3+c7
l4=l4+c6
l5=l5+c11
sele dyb
appe blank
repl dybx with l1
appe blank
repl dybx with l2
appe blank
repl dybx with l4 &&生成表头结束
sele zgb &&打开职工库,既要打印的职工信息
go top
b1=c7
b2=''
k=1
j=1
x=1
mrec=recn()
do whil !eof() &&每条记录据类型生成一行打印字符
j=1
b1=c7+str(x,4)+c7
do whil j<=i0
sele zgb
go mrec
lszdm=trim(z(j)) &&字段名
lszdz=&lszdm &&相应值
DO CASE &&日期\数值字段变字符
CASE z3(j)=’D’ &&时间字段
b2=dtoc(LSZDZ)
CASE z3(j)=’N’ &&数值字段
b2=str(LSZDZ)
OTHE
b2=padl(&z(j),z2(j))
ENDCASE
b1=b1+b2+c7
j=j+1
enddo
sele dyb && 加入打印库
appe blan
repl dybx with b1
sele zgb
GO MREC
skip
MREC=RECN()
if !eof()
k=k+1
x=x+1
if k>m.jls &&换页处理
sele dyb
appe blan
repl dybx with l5
appe blan
appe blan
appe blank
repl dybx with l1
appe blank
repl dybx with l2
K=1
endif
sele dyb
appe blan
repl dybx with l4
SELE ZGB
GO MREC
else
sele dyb
appe blan
repl dybx with l5
EXIT
endif
enddo
retu
此程序用VFP6.0调试成功,并已在“干部职称管理系统”中运行至今。由于使用方便,客户反应良好。
|