一 、 前言
Visual Basic开发数据库系统中,报表打印是其中最重要也是最常用的功能之一。按照报表实现的方法可大体上分为3类:第1类是较原始的方法,直接控制打印机对象Printer进行画线和打印;第2类是使用控件,如Data Report、Crystal Report、Active Report等;第3类是将需要打印的报表保存成其他程序可以识别的格式或直接输入到其他程序中,利用其他程序的打印功能操作,典型代表就是通过Word和Excel打印报表。
二、方法简介
使用Printer对象编程进行打印,最大的问题是要经常进行坐标运算,需要考虑很多琐碎的问题,代码量大,打印的内容无法预览。优点是控制灵活,且打印效果比较好,在实际应用中,对于一些灵活度较高,功能较复杂的报表使用本方法是较理想的方法。本文的实例中主要介绍了此种方法的实现过程。
VB自带的Data Report与Printer比起来,编程强度小了很多,而且它以所见即所得的方式设计报表,比较直观,打印出来的报表比较美观,实现打印预览功能比较简单。它缺点是不够灵活,绑定内容只能是Recordset,且还有诸多限制。
Crystal Report是Seagate公司出品的报表打印控件,8.0以上的版式本的功能已经十分强大,控制灵活,堪称经典的报表解决方案。它的缺点体积比较强大,且是商用软件,价格比较昂贵。
Active Report是Data Dynamic公司出品的优秀打印控件。Active Report作为Data Report的增强型,控制灵活,功能完备,完全可以胜任日常报表打印工作。
借助VBA调用一些外部软件解决打印问题,其中Word和Excel是常用的“打印代理”。这种方法的好处是控制比较简单,打印功能强大。它的缺点是要求运行报表打印程序的计算机必须安装相应软件(如Word或Excel等)。
三、程序实现
1.新建一个标准工程,名称为【工程1】。在工程中创建一个窗体,名称为【Forml】
2.单击【工程】菜单下的【部件】选取项,在弹出的列表中选中【Microsoft FlexGrid Control6.0(sp3)】选项,然后单击【确定】按键,MSFlexGrid控件就添加到工具箱中了。
3.在【Forml】窗体中放置1个MSFlexGrid控件、8个TextBox控件、8个Label控件、5个CommandButton控件等。主要控件对象的属性如下表所示。
主要控件的属性列表
|
对 象 |
属 性 |
值 |
功 能 |
|
MSFlexGrid |
名称 |
MSFlexGrid1 |
输入入库信息 |
|
Text1 |
名称 |
Text1 |
|
Text2 |
名称 |
TxtWhm_1 |
输入单据号 |
|
Text3 |
名称 |
TxtWhm_2 |
显示品种数 |
|
Text4 |
名称 |
TxtWhm_3 |
显示合计数量 |
|
Text5 |
名称 |
TxtWhm_4 |
显示合计金额 |
|
Text6 |
名称 |
TxtWhm_6 |
输入供货商名称 |
|
Text7 |
名称 |
TxtWhm_7 |
输入日期 |
|
Text8 |
名称 |
TxtWhm_8 |
输入经手人 |
|
Command1 |
名称 |
CmdRegister |
登记命令 |
|
Caption |
登记 |
|
Command2 |
名称 |
CmdSave |
保存命令 |
|
Caption |
保存 |
|
Command3 |
名称 |
Cmdprint |
打印命令 |
|
Caption |
打印 |
|
Command4 |
名称 |
CmdCancel |
取消命令 |
|
Caption |
取消 |
|
Command5 |
名称 |
CmdEnd |
退出命令 |
|
Caption |
退出 |
4.添加程序代码
这里以药品入库单为例实现报表的打印、核心代码如下:
Private Sub CmdPrint_Click() ’编程实现票据连续分页打印
’参数定义,作用为确定打印坐标
Dim i, A As Integer
Dim v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 As Integer
v1 = 5
v2 = v1 + MSFlexGrid1.ColWidth(0) * 1.2 ’序号
v3 = v2 + MSFlexGrid1.ColWidth(1) * 1# ’药品代码
v4 = v3 + MSFlexGrid1.ColWidth(2) * 0.95 ’药品名称
v5 = v4 + MSFlexGrid1.ColWidth(3) * 0.9 ’规格
v6 = v5 + MSFlexGrid1.ColWidth(4) * 0.8 ’产地
v7 = v6 + MSFlexGrid1.ColWidth(5) * 0.9 ’批号
v8 = v7 + MSFlexGrid1.ColWidth(6) * 0.8 ’有效期
v9 = v8 + MSFlexGrid1.ColWidth(7) * 0.9 ’单位
v10 = v9 + MSFlexGrid1.ColWidth(8) * 1.4 ’数量
v11 = v10 + MSFlexGrid1.ColWidth(9) * 1.2 ’单价-----进货价
v12 = v11 + MSFlexGrid1.ColWidth(10) * 1.3 ’金额
v13 = 11500
Dim m As Integer ’总记录数
Dim N As Integer ’每页记录数
Dim ii As Integer ’总页数
Dim j As Integer ’页码数
Dim k As Integer ’每页起始记录控制
Dim TmpLowerPageMoney As Single ’每页合计金额
m = Val(TxtWhm_2.Text) ’(TxtWhm_2 入库品种数)----总记录数
N = 4 ’每页 4 条记录
If Int(m / N) - m / N = 0 Then
ii = m / N
Else
ii = Int(m / N) + 1
End If
Printer.Height = 750 + 300 + 450 * N + 900 + 1000 ’定义纸张高度----根据每页记录数
Printer.Width = 12000 ’定义纸张宽度
For j = 1 To ii ’外循环控制打印页数
TmpLowerPageMoney = 0# ’每页合计金额 ------ 新页开始清零
Printer.CurrentX = 4000
Printer.CurrentY = 200
Printer.FontSize = 16
Printer.Print "湘潭市维民贸易有限公司入库单 "
Printer.CurrentX = 9250 ’页码置于左上角
Printer.CurrentY = 200
Printer.FontSize = 10
Printer.Print "第 " + Trim(Str(j)) + " 页 共 " & Trim(Str(ii)) + " 页"
Printer.CurrentX = 200
Printer.CurrentY = 750
Printer.FontSize = 10
Printer.Print "供货单位:" & TxtWhm_6.Text
Printer.CurrentX = 5000
Printer.CurrentY = 750
Printer.FontSize = 10
’Printer.Print "(此入库单不做报销凭证)"
Printer.CurrentX = 8800
Printer.CurrentY = 750
Printer.FontSize = 10
Printer.Print "票号:" & "" & TxtWhm_1.Text
’列标题
’A -------- 表主体纵向高度
A = 1050
Printer.Line (v1, A)-(v13, A) ’画顶横线
If MSFlexGrid1.ColWidth(0) > 0 Then ’第1列
Printer.Line (v1, A)-(v1, A + 450) ’画左坚边线
Printer.CurrentX = 50
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "序号"
End If
If MSFlexGrid1.ColWidth(1) > 0 Then ’第2列
Printer.Line (v2, A)-(v2, A + 450)
Printer.CurrentX = v2 + 10
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "药品代码"
End If
If MSFlexGrid1.ColWidth(2) > 0 Then ’第3列
Printer.Line (v3, A)-(v3, A + 450)
Printer.CurrentX = v3 + 40
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "药品名称"
End If
If MSFlexGrid1.ColWidth(3) > 0 Then ’第4列
Printer.Line (v4, A)-(v4, A + 450)
Printer.CurrentX = v4 + 40
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "规格"
End If
If MSFlexGrid1.ColWidth(4) > 0 Then ’第5列
Printer.Line (v5, A)-(v5, A + 450)
Printer.CurrentX = v5 + 40
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "产地"
End If
If MSFlexGrid1.ColWidth(5) > 0 Then ’第6列
Printer.Line (v6, A)-(v6, A + 450)
Printer.CurrentX = v6 + 40
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "批号"
End If
If MSFlexGrid1.ColWidth(6) > 0 Then ’第7列
Printer.Line (v7, A)-(v7, A + 450)
Printer.CurrentX = v7 + 40
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "有效期"
End If
If MSFlexGrid1.ColWidth(7) > 0 Then ’第8列
Printer.Line (v8, A)-(v8, A + 450)
Printer.CurrentX = v8 + 20
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "单位"
End If
If MSFlexGrid1.ColWidth(8) > 0 Then ’第9列
Printer.Line (v9, A)-(v9, A + 450)
Printer.CurrentX = v9 + 30
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "数量"
End If
If MSFlexGrid1.ColWidth(9) > 0 Then ’第10列
Printer.Line (v10, A)-(v10, A + 450)
Printer.CurrentX = v10 + 80
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "单价" ’注意: 此处“单价”对应“进货价”
End If
If MSFlexGrid1.ColWidth(10) > 0 Then ’第11列
Printer.Line (v11, A)-(v11, A + 450)
Printer.CurrentX = v11 + 20
Printer.CurrentY = A + 100
Printer.FontSize = 10
Printer.Print "金额"
Printer.Line (v12 + 10, A)-(v12 + 10, A + 450) ’画右坚边线(封口)
End If
A = 1500 ’A -------- 表主体纵向高度
Printer.Line (v1, A)-(v13, A) ’画横线
If j = 1 Then ’k 每页起始记录控制
k = 1 ’k=0 表示第1行,k=1 表示第2行
Else
k = (j - 1) * N + 1
End If
For i = k To j * N ’内循环控制每页打印-------------分页打印
If MSFlexGrid1.ColWidth(0) > 0 Then ’第1列 序号
Printer.Line (v1, A)-(v1, A + 450) ’画左坚边线
Printer.CurrentX = 245
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 0) <> "" Then ’i=0 时为第1行,标题行
Printer.Print MSFlexGrid1.TextMatrix(i, 0)
End If
End If
If MSFlexGrid1.ColWidth(1) > 0 Then ’第2列 药品代码
Printer.Line (v2, A)-(v2, A + 450)
Printer.CurrentX = v2 + 10
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 1) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 1)
End If
End If
If MSFlexGrid1.ColWidth(2) > 0 Then ’第3列 药品名称
Printer.Line (v3, A)-(v3, A + 450)
Printer.CurrentX = v3 + 10
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 2) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 2)
End If
End If
If MSFlexGrid1.ColWidth(3) > 0 Then ’第4列 规格
Printer.Line (v4, A)-(v4, A + 450)
Printer.CurrentX = v4 + 20
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 3) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 3)
End If
End If
If MSFlexGrid1.ColWidth(4) > 0 Then ’第5列 产地
Printer.Line (v5, A)-(v5, A + 450)
Printer.CurrentX = v5 + 50
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 4) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 4)
End If
End If
If MSFlexGrid1.ColWidth(5) > 0 Then ’第6列 批号
Printer.Line (v6, A)-(v6, A + 450)
Printer.CurrentX = v6 + 30
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 5) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 5)
End If
End If
If MSFlexGrid1.ColWidth(6) > 0 Then ’第7列 有效期
Printer.Line (v7, A)-(v7, A + 450)
Printer.CurrentX = v7 + 60
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 6) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 6)
End If
End If
If MSFlexGrid1.ColWidth(7) > 0 Then ’第8列 单位
Printer.Line (v8, A)-(v8, A + 450)
Printer.CurrentX = v8 + 30
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 7) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 7)
End If
End If
If MSFlexGrid1.ColWidth(8) > 0 Then ’第9列 数量
Printer.Line (v9, A)-(v9, A + 450)
Printer.CurrentX = v9 + 60
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 8) <> "" Then
Printer.Print MSFlexGrid1.TextMatrix(i, 8)
End If
End If
If MSFlexGrid1.ColWidth(9) > 0 Then ’第10列 进货价
Printer.Line (v10, A)-(v10, A + 450)
Printer.CurrentX = v10 + 150
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 9) <> "" Then
Printer.Print Format(MSFlexGrid1.TextMatrix(i, 9), "0.00")
End If
End If
If MSFlexGrid1.ColWidth(10) > 0 Then ’第11列 金额
Printer.Line (v11, A)-(v11, A + 450)
Printer.CurrentX = v11 + 200
Printer.CurrentY = A + 100
Printer.FontSize = 10
If MSFlexGrid1.TextMatrix(i, 10) <> "" Then
Printer.Print Format(MSFlexGrid1.TextMatrix(i, 10), "0.00")
End If
TmpLowerPageMoney = TmpLowerPageMoney + Val(MSFlexGrid1.TextMatrix(i, 10)) ’每页合计金额
TxtPageLowerMoney = Round(TmpLowerPageMoney, 2)
Printer.Line (v12, A)-(v12, A + 450) ’画右坚边线(封口)
End If
Printer.Line (v1, A + 450)-(v13, A + 450) ’“本页合计金额大写”上边横线
A = A + 450 ’行距每次增加 450
Next i ’内循环结束
Printer.FontSize = 10
Printer.Line (v1, A + 450)-(v13, A + 450)
Printer.CurrentX = v1 + 300
Printer.CurrentY = A + 100
Printer.Print "本页合计金额大写 " & "" & Format(LabPageUpperMoney, "0.00") ’每页合计金额(大写)
Printer.Line (v3 + 550, A)-(v3 + 550, A + 450) ’“本页合计金额大写”右边竖线
Printer.FontSize = 10
Printer.CurrentX = v9 + 60 ’v1 + 7500
Printer.CurrentY = A + 100
Printer.Print "小写: " & Format(TxtPageLowerMoney, "0.00") & "元" ’每页合计金额(小写)
Printer.Line (v9, A)-(v9, A + 450) ’“小写:”右边竖线
Printer.Line (v1, A + 450)-(v13, A + 450) ’画横线
Printer.FontSize = 10
Printer.CurrentX = v1 + 20
Printer.CurrentY = A + 550
Printer.Print "备注"
Printer.Line (v2, A + 450)-(v2, A + 900) ’“备注”右边竖线
Printer.FontSize = 10
Printer.CurrentX = v9 + 60 ’v1 + 7500
Printer.CurrentY = A + 550
Printer.Print "本次开票总金额: " & "" & Format(TxtWhm_4, "0.00") & "元" ’总金额(小写)
Printer.Line (v9, A + 450)-(v9, A + 900) ’“本次开票总金额:”右边竖线
Printer.Line (v1, A + 900)-(v13, A + 900) ’画底边横线
Printer.FontSize = 10
Printer.CurrentX = v1 + 10
Printer.CurrentY = A + 1000
Printer.Print "开票人:" & "" & TxtWhm_8.Text
Printer.FontSize = 10
Printer.CurrentX = v1 + 2200
Printer.CurrentY = A + 1000
Printer.Print "收货人: 复核人: 送货人:"
Printer.NewPage ’新的一页
Printer.EndDoc ’换页
Next j ’外循环结束
Call MsgBox("正在打印......!", vbOKOnly + vbInformation, "提示...")
End Sub
5.程序运行结果
程序运行效果如图1所示,打印效果如图2所示。

图1 药品入库单窗体运行结果

图2 药品入库单报表打印结果
四、 结束语
Printer是Visual Basic提供的一个操作打印机进行基本打印操作的对象。通过它,可以实现强大的打印功能,可以自定义打印格式、打印页数、表格的粗细和字体的大小等。编码虽然稍微麻烦(需要进行多次坐标计算),但也是最灵活的报表打印方式之一。作者在利用此方法设计《医药进销存管理系统》中的入(出)库单时,取得了很好的较果,大家可以根据自己开发MIS系统中报表打印的实际要求,借鉴此设计思路,实现属于自己系统的报表打印。