当前位置:文档之家› VB通用数据表格输出程序的设计.

VB通用数据表格输出程序的设计.

VB通用数据表格输出程序的设计做为一种简捷、系统的Windows应用程序开发工具,Visual Basic具有强大的数据处理能力,提供了多种数据访问方法,可以方便地存取Microsoft SQL Server、Oracle、XBase等多种数据库,被广泛应用于建立各种信息管理系统。

但是,VB缺乏足够的、符合中文习惯的数据表格输出功能。

虽然使用Crystal Report控件及Crystal Reports程序可以输出报表,但操作很麻烦,中文处理能力也不理想,特别是不能够用来制作不确定内容的表格。

笔者在用VB开发淮北市医疗保险信息管理系统时,需要对任意的查询结果进行表格输出,为此,编制了一个通用的数据表格输出控件,能够根据查询的结果自动生成二维中文表格,并打印输出,在此介绍给大家,共同探讨。

一.VB中的结果集VB提供的数据访问方法有数据询问对象(DAO)、Data控件、远程数据对象(RDO)、RemoteData控件(RDC)、ODBC API、VB SQL等,其中ODBC API比较复杂,开发、调试和支持非常困难;VB SQL是针对Microsoft SQL Server的,这两种方法使用的比较少,这里不做讨论。

比较常用的方法是DAO、Data控件、RDO、RDC,其中DAO和Data控件使用的结果集(又叫纪录集) 包含在Recordset 对象中,RDO和RDC使用的结果集包含在rdoResultset对象中。

通用表格输出的实现方法就是根据任意的Recordset对象或rdoResultset对象自动生成表格并输出。

二.表格的自动生成1. Recordset对象下面以Data控件为例,介绍Recordset对象的表格自动生成方法。

假设有Data控件名称为MyData,首先说明相关的内容及用法:(1) Data控件的结果集包含在它的Recordset对象中,引用方法为: MyData.Recordset。

(2) Recordset 对象的RecordCount属性为结果集的行数,它决定了表格的长度,该属性引用方法为: MyData.Recordset.RecordCount。

(3) Recordset 对象包含一个Fields集合,通过Fields集合的Count属性可以得到结果集中字段的个数,用做表格的列数,该属性引用方法为: MyData.Recordset.Fields.Count。

(4) Fields集合包括结果集合全部Field对象,这些Field对象引用方法为:MyData.Recordset.Fields(i),其中i是该Field对象在中的位置序号,从0开始计数。

(5) Field 对象的Name属性是该字段的名称,用做表格对应列的名称,引用方法为:MyData.Recordset.Fields(i).Name。

(6) Field 对象的Size属性是该字段数据的最大尺寸,引用方法为:MyData.Recordset.Fields(i).Size。

(7) Field 对象的Type属性是该字段数据的类型,引用方法为:MyData.Recordset.Fields(i).Type。

用Field 对象的Size和Type属性可以计算出表格对应列的宽度。

(8) Field 对象的Value属性是该字段的值,这是表格对应列的内容,引用方法为:MyData.Recordset.Fields(i).Value。

以上引用在VB中都可有多种引用方法,这里使用的是比较明了的一种,便于说明问题。

注意:表格的自动生成可分为两个步骤。

第一步,根据结果集中各字段的Size和Type属性,生成表格各对应列的宽度,用Format函数使用的格式字符串表示。

下面的Function getFmt()用来生成表格各列的格式字符串,调用时把Field 对象的Type和Size属性值分别赋给形式参数intType和logSize。

Private Function getFmt(intType As Integer, logSize As Long) As StringDim i As IntegergetFmt = ""'返回的结果串初始置空Select Case intTypeCase dbBooleangetFmt = getFmt & "\ \ \ \0;\ \ \ \1"'Boolean 型值转换为0、1,Case dbBytegetFmt = "@@@@"Case dbIntegergetFmt = "@@@@@@"Case dbLonggetFmt = "@@@@@@@@@@"Case dbCurrencygetFmt = "@@@@@@@@@@"Case dbSinglegetFmt = "@@@@@@@@@@"Case dbDoublegetFmt = "@@@@@@@@@@"Case dbDategetFmt = "@@@@@@@@@@"Case dbBinarygetFmt = "@@@@"Case dbTextIf logSize >= 40 Then'限制一列最多打印40个半角字符getFmt = "@@@@@@@@@@@@@@@@@@@@@@@ _@@@@@@@@@@@@@@@@@"ElseFor i = 0 To CInt(logSize / 2) * 2 - 1getFmt = getFmt & "@"Next '调整数值长度为偶数,以适应汉字制表符End IfCase dbLongBinarygetFmt = "@@@@"Case dbMemogetFmt = "@@@@@@@@@@@@@@@@"Case dbGUIDgetFmt = "@@@@"Case dbBigIntgetFmt = "@@@@@@@@@@"Case dbVarBinarygetFmt = "@@@@"Case dbCharFor i = 0 To CInt(logSize / 2) * 2 - 1getFmt = getFmt & "@"NextCase dbNumericFor i = 0 To CInt(logSize / 2) * 2 - 1getFmt = getFmt & "@"NextCase dbDecimalFor i = 0 To CInt(logSize / 2) * 2 - 1getFmt = getFmt & "@"NextCase dbFloatgetFmt = "@@@@@@@@@@"Case dbTimegetFmt = "@@@@@@@@"Case dbTimeStampgetFmt = "@@@@@@@@@@"End SelectEnd Function第二步,取结果集的内容并根据各列的格式字符串生成表格,生成的表格存放在字符串数组strDy()中,下面用Sub Dy()例示这一步骤。

Dim strDy() As String'存放格式化后的表格内容Dim Fmt() As String'存放表格各列的格式字符串'以上二个数组变量的元素个数根据结果集的行数和列数在程序中设定Dim str,str0,str1,str2 As String'临时使用的串变量Dim i,j As Integer'临时使用的整型变量Dim intDc As Integer '存放表格行数,实际上即是strDy()的元素个数Private Sub Dy()With MyData.Recordset.MoveLastReDim strDy(.RecordCount + 8)'需存放标题、表框等,所以加8ReDim Fmt(.Fields.Count)For i = 0 To .RecordCount + 7strDy(i) = "" '初始置空NextFor i = 0 To .Fields.Count - 1Fmt(i) = getFmt(.Fields(i).Type, .Fields(i).Size)'生成表格各列的格式字符串j = Len(.Fields(i).Name)If j > Len(Fmt(i)) ThenFmt(i) = String$(Int((j / 2) + 0.5) * 2, "@")'标题(字段名) 字多则增大列宽End IfNextstr = "┃"str0 = "┏"str1 = "┠"str2 = "┗" '设定表格为粗框细线,可根据需要改变For i = 0 To .Fields.Count - 1For j = 1 To Len(Fmt(i)) / 2str0 = str0 & "━"str1 = str1 & "─"str2 = str2 & "━"NextIf (i = .Fields.Count - 1) Thenstr = str & Format(.Fields(i).Name, Fmt(i)) & "┃"Elsestr = str & Format(.Fields(i).Name, Fmt(i)) & "│"End IfIf (i = .Fields.Count - 1) Thenstr0 = str0 & "┓"str1 = str1 & "┨"str2 = str2 & "┛"Elsestr0 = str0 & "┯"str1 = str1 & "┼"str2 = str2 & "┷"End IfNextstrDy(0) = "表格标题"'通过在标题前增加空格可使标题居中strDy(1) = ""strDy(2) = Format(Now, " 打印日期:yyyy年m月d日")strDy(3) = str0strDy(4) = strstrDy(5) = str1intDc = 6.MoveFirstDo While Not .EOFstr = "┃"For i = 0 To .Fields.Count - 1If IsNull(.Fields(i).Value) Then'处理Null 值If i = .Fields.Count - 1 Thenstr = str & Format(" ", Fmt(i)) & "┃"Elsestr = str & Format(" ", Fmt(i)) & "│"End IfElseIf i = .Fields.Count - 1 Thenstr = str & Format(Left$(.Fields(i).Value, Len(Fmt(i))), Fmt(i)) & "┃"Elsestr = str & Format(Left$(.Fields(i).Value, Len(Fmt(i))), Fmt(i)) & "│"End IfEnd IfNextstrDy(intDc) = strDy(intDc) & strintDc = intDc + 1.MoveNextLoopstrDy(intDc) = str2End WithEnd Sub在实际编程中还要排除二进制数据字段,全角与半角字符的匹配调整,处理数据中出现的换行符、回车符、制表符,等等,限于篇幅,这里不于介绍。

相关主题