VFP6.0作为优秀的桌面型数据库系统,提供了强大的报表、标签输出功能。但是在实际应用中,其提供的报表输出格式常常不符合要求,有时会碰到一些复杂格式的表格,有时要多报表同文档输出,用VFP6.0的报表设计功能难于实现。
在实际应用中笔者尝试编程实现用VFP6.0操纵Word灵活打印各式报表,取得了良好的效果,在此介绍这种方法。众所周知,MicroSoft 的Word是一个功能强大的字处理软件,它可以用自身带有的宏编辑器编写宏来实现绝大多数菜单功能,也可以用VBA编写程序完成很多任务。编程实现VFP6.0操纵Word灵活打印特殊格式的报表,是用VFP6.0编写嵌有类似于VBA宏的程序,执行Word的命令打印报表、报告。所以理论上,用这种方式可以实现任意格式报表的输出。
问题的关键在于: 一,正确地在VFP6.0中调用Word。对于在VFP6.0中调用Word(也可理解为客户/服务器的请求和应答关系),使用语句
loWord = etcominstance ("word.application")
调用后,Word就可视为VFP 的一个对象,为了使用其变量、方法、事件和过程,必须在程序开头时包含Word的一个头文件,语句为:#INCLUDE wdolb.h (Offices97中的Word) 或 #INCLUDE msolb09.h(Offices2000中的Word)。二,正确地使用word能执行的编排版式的语言。使用这种方式打印报表的主要目的是满足特殊的报表格式,而编排这些格式是依靠Word能运行的宏代码,这些宏代码在又要在VFP中被执行,而宏在Word中与在VFP中形式大体相近,但书写格式不尽相同。例如要插入一个两行两列的表格,Word中宏格式为:
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= 2,
而在VFP中应该为: .Activedocument.Tables.Add(.Selection.Range,2,2) ;再如输出一行文本“电脑编程” Word中宏格式为:Selection.TypeText Text:=" 电脑编程",而在VFP中应该为: Selection.TypeText(" 电脑编程")等。在后面的例程中可以看出这些差别。当不知道该如何实现某个特殊格式时,最便捷的做法是在Word中刻录该格式的Word宏,拷贝到VFP中做适当修改即可。三,正确处理VFP6.0宿主语句与Word宏语句的镶嵌关系。这种报表打印方式的优越之处,不光在于单份特殊格式的报表输出,而且在于多份在VFP意义上的报表的同文档打印,甚至用一些信息挖掘手段从几十、上百个数据表中提取信息,打印出一个大体完整的既有表格又有自由文字的报告,这些是很诱人的。所以,一般这样的报表打印程序除了满足格式上的要求外,通常还要实现一定的数据筛选,信息挖掘的功能,或者多表记录关联在同一报表输出,多报表的同文档输出等等,所以除了Word宏,程序中还有大量VFP自身的处理语句,有时两者是相互嵌套的,要注意两类语句排列顺序,有时顺序的错误回导致程序的错误。例如,对Word对象的控制语句要放在“WITH …….ENDWITH”中,这样,在使用VFP的循环语句、分支语句时一定要注意不要嵌套错误。编程中如果出现奇怪的错误,最好是检查一下语句的排列顺序。
下面举一个简单的例子,介绍如何在VFP6.0中调用Word、用其代码控制、以报表形式打印输出满足条件的记录。这种打印结果脱离了VFP6.0,可以保存为独立电子文档,也可做进一步的编辑。
该示例是假定在学生信息管理系统中,要打印满足学号为特定值的学生信息。
首先,新建一个目录WriteReport作为当前VFP6.0默认路径,在其中建一个数据库表文件Student,形式为Student(name(C,8),gender(C,2),borntime(D,8),photo(G,4),studentno(C,12),stime(D,8),dpartment(C,20),major(C,18),drom(C,20),dtelenumber(C,15),address(C,20),htelenumber(C,15),hobby(M,4)),其中设置字段studentno为该表主关键字,并录入几条记录;然后建立一个名为WriteReport 的过程(程序清单附后);最后建立一个如图1所示的
图1. 执行表单
表单调用WriteReport过程,其中“打印”按钮的代码为:
cStuNumb = ThisForm.List1.Value
IF EMPTY(cStuNumb)
MESSAGEBOX("请先用鼠标在列表框中单击一个学生的姓名!",0+64+0,"提示信息")
ELSE
Do WriteReport WITH cStuNumb
ENDIF
执行该过程即可在word 中打印出如图2所示的报表。
图2. 学生信息报表样式
WriteReport程序清单:
*PROCEDURE WriteReport Write Student Document from database table By Word!
PARAMET cStudentNumber
#INCLUDE wdolb.h
#DEFINE True .T.
#DEFINE False .F.
IF !USED('student') && Open the table
USE student IN 0 ORDER studentno
ENDIF
SELE student
IF PARA()=0 &&When there is no parameter been pasted,write the first student in the table
cStudentNumber = student.studentno
ENDIF
SEEK cStudentNumber
IF FOUND()
LOCAL loWord,loTable,lnRow,lnColumn
loWord=Getcominstance("word.application") &&Call Word application
loWord.Visible=.t.
cString = "学生信息报表"
WITH loWord
.Documents.Add("Normal",False)
.Selection.MoveDown(wdLine,100)
WITH .Selection && Information on the top of the report
.Font.Name = "宋体" && Format of the String
.Font.Size = 20
.ParagraphFormat.Alignment=wdAlignParagraphCenter
.TypeText(cString)
.TypeParagraph && Add a blank line
ENDWITH
.Selection.Sections(1).Footers(1).PageNumbers.Add(wdAlignPageNumberCenter,True)
.Selection.Font.Size =14
.Activedocument.Tables.Add(.Selection.Range,1,7)
loTable=.Activedocument.Tables(1)
WITH loTable
.Cell(1,1).Width=80
.Cell(1,2).Width=45
.Cell(1,3).Width=80
.Cell(1,4).Width=45
.Cell(1,5).Width=30
.Cell(1,6).Width=45
.Cell(1,7).Width=90
.Cell(1,1).Range.Insertafter("照片")
.Cell(1,2).Range.Insertafter("姓名")
.Cell(1,4).Range.Insertafter("性别")
.Cell(1,6).Range.Insertafter("学号")
.Cell(1,3).Range.Insertafter(name)
.Cell(1,5).Range.Insertafter(gender)
.Cell(1,7).Range.Insertafter(studentno)
ENDWITH
.Selection.MoveDown(wdLine,100)
.Activedocument.Tables.Add(.Selection.Range,2,5)
loTable = .Activedocument.Tables(1)
WITH loTable
FOR j=2 TO 3
.Cell(j,1).Width=80
.Cell(j,2).Width=70
.Cell(j,3).Width=100
.Cell(j,4).Width=70
.Cell(j,5).Width=95
ENDFOR
.Cell(2,2).Range.Insertafter("出生年月")
.Cell(2,3).Range.Insertafter(borntime)
.Cell(2,4).Range.Insertafter("入学时间")
.Cell(2,5).Range.Insertafter(stime)
.Cell(3,2).Range.Insertafter("所在院系")
.Cell(3,3).Range.Insertafter(department)
.Cell(3,4).Range.Insertafter("所学专业")
.Cell(3,5).Range.Insertafter(major)
ENDWITH
.Selection.SelectColumn && Select the three columns
.Selection.Cells.Merge && unite columns
.Selection.MoveDown(wdLine,100)
.Activedocument.Tables.Add(.Selection.Range,2,4)
loTable=.Activedocument.Tables(1)
WITH loTable
FOR j=4 TO 5
.Cell(j,1).Width=80
.Cell(j,2).Width=170
.Cell(j,3).Width=70
.Cell(j,4).Width=95
ENDFOR
.Cell(4,1).Range.Insertafter("学校住址")
.Cell(4,2).Range.Insertafter(drom)
.Cell(4,3).Range.Insertafter("寝室电话")
.Cell(4,4).Range.Insertafter(dtelenumber)
.Cell(5,1).Range.Insertafter("家庭住址")
.Cell(5,2).Range.Insertafter(address)
.Cell(5,3).Range.Insertafter("联系电话")
.Cell(5,4).Range.Insertafter(htelenumber)
ENDWITH
.Selection.MoveDown(wdLine,100)
.Activedocument.Tables.Add(.Selection.Range,1,2)
loTable = .Activedocument.Tables(1)
WITH lotable
.Cell(6,1).Width=80
.Cell(6,1).Height=60
.Cell(6,2).Width=335
.Cell(6,1).Range.Insertafter("个人特长")
.Cell(6,2).Range.Insertafter(hobby)
ENDWITH
.Selection.Sections(1).Footers(1).PageNumbers.Add(wdAlignPageNumberCenter,True) &&Insert Pagenumber
ENDWITH
ENDIF
RETURN
该程序在VFP6.0中调试通过。(注意:要求同机装有Offices的Word软件,程序才能正常运行)。
补充说明:本文主要探讨用VFP操纵Word打印报的方法,同时在程序实现上也有些技巧,希望在贵刊的数据库栏或者其它专栏中刊出,不胜感激!所有源程序存到名为“WriteReport”的文件夹中随文邮到,包含完整的项目、库、表单及程序,可打开直接运行检测。
|