VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - VB通用数据表格输出程序的设计
发表评论(0)作者:沙顺义, 平台:VB6.0+Win98, 阅读:11300, 日期:2001-04-20
VB通用数据表格输出程序的设计
淮北市社会保障局计算中心
沙顺义
---- 做为一种简捷、系统的 Windows应用程序开发工具,Visual Basic 5 具有强大的数据处理能力,提供了多种数据访问方法,可以方便地存取Microsoft SQL Server、Oracle、XBase等多种数据库,被广泛应用于建立各种信息管理系统。但是,VB缺乏足够的、符合中文习惯的数据表格输出功能。虽然使用Crystal Report控件及 Crystal Reports程序可以输出报表,但操作很麻烦,中文处理能力也不理想,特别是不能够用来制作不确定内容的表格。笔者在用VB开发淮北市医疗保险信息管理系统时,需要对任意的查询结果进行表格输出,为此,编制了一个通用的数据表格输出控件,能够根据查询的结果自动生成二维中文表格,并打印输出,在此介绍给大家,共同探讨。

一.VB 5中的结果集
---- VB 5提供的数据访问方法有数据询问对象(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 String
  Dim i As Integer
  getFmt = ""                
  注释:返回的结果串初始置空
  Select Case intType
    Case dbBoolean
      getFmt = getFmt & "\ \ \ \0;\ \ \ \1"
注释:Boolean 型值转换为0、1,
    Case dbByte
      getFmt = "@@@@"
    Case dbInteger
      getFmt = "@@@@@@"
    Case dbLong
      getFmt = "@@@@@@@@@@"
    Case dbCurrency
      getFmt = "@@@@@@@@@@"
    Case dbSingle
      getFmt = "@@@@@@@@@@"
    Case dbDouble
      getFmt = "@@@@@@@@@@"
    Case dbDate
      getFmt = "@@@@@@@@@@"
    Case dbBinary
      getFmt = "@@@@"
    Case dbText
      If logSize  >= 40 Then
  注释:限制一列最多打印40个半角字符
getFmt = "@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@"
      Else
        For i = 0 To CInt(logSize / 2) * 2 - 1
          getFmt = getFmt & "@"
        Next    注释:调整数值长度为偶数,
以适应汉字制表符
      End If
    Case dbLongBinary
      getFmt = "@@@@"
    Case dbMemo
      getFmt = "@@@@@@@@@@@@@@@@"
    Case dbGUID
      getFmt = "@@@@"
    Case dbBigInt
      getFmt = "@@@@@@@@@@"
    Case dbVarBinary
      getFmt = "@@@@"
    Case dbChar
      For i = 0 To CInt(logSize / 2) * 2 - 1
        getFmt = getFmt & "@"
      Next
    Case dbNumeric
      For i = 0 To CInt(logSize / 2) * 2 - 1
        getFmt = getFmt & "@"
      Next
    Case dbDecimal
       For i = 0 To CInt(logSize / 2) * 2 - 1
         getFmt = getFmt & "@"
       Next
    Case dbFloat
      getFmt = "@@@@@@@@@@"
    Case dbTime
      getFmt = "@@@@@@@@"
    Case dbTimeStamp
      getFmt = "@@@@@@@@@@"
  End Select
  End 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
  .MoveLast
  ReDim strDy(.RecordCount + 8)  
注释:需存放标题、表框等,所以加8
  ReDim Fmt(.Fields.Count)
  For i = 0 To .RecordCount + 7
    strDy(i) = ""        注释:初始置空
  Next
  For i = 0 To .Fields.Count - 1
Fmt(i) = getFmt(.Fields(i).Type, .Fields(i).Size)
注释:生成表格各列的格式字符串
    j = Len(.Fields(i).Name)
    If j  > Len(Fmt(i)) Then
      Fmt(i) = String$(Int((j / 2) + 0.5) * 2, "@")
注释:标题 (字段名) 字多则增大列宽
    End If
Next
    str = "┃"
    str0 = "┏"
    str1 = "┠"
str2 = "┗"    注释:设定表格为粗框细线,
可根据需要改变
  For i = 0 To .Fields.Count - 1
    For j = 1 To Len(Fmt(i)) / 2
      str0 = str0 & "━"
      str1 = str1 & "─"
      str2 = str2 & "━"
    Next
    If (i = .Fields.Count - 1) Then
      str = str & Format(.Fields(i).Name, Fmt(i)) & "┃"
    Else
      str = str & Format(.Fields(i).Name, Fmt(i)) & "│"
    End If
    If (i = .Fields.Count - 1) Then
      str0 = str0 & "┓"
      str1 = str1 & "┨"
      str2 = str2 & "┛"
    Else
      str0 = str0 & "┯"
      str1 = str1 & "┼"
      str2 = str2 & "┷"
    End If
  Next
  strDy(0) = "表格标题"
  注释:通过在标题前增加空格可使标题居中
  strDy(1) = ""
  strDy(2) = Format(Now, " 打印日期:
yyyy年 m月 d日")
  strDy(3) = str0
  strDy(4) = str
  strDy(5) = str1
  intDc = 6
  .MoveFirst
  Do While Not .EOF
   str = "┃"
   For i = 0 To .Fields.Count - 1
      If IsNull(.Fields(i).Value) Then    
注释:处理 Null 值
        If i = .Fields.Count - 1 Then
          str = str & Format(" ", Fmt(i)) & "┃"
        Else
          str = str & Format(" ", Fmt(i)) & "│"
        End If
      Else
        If i = .Fields.Count - 1 Then
          str = str & Format(Left$(.Fields(i).
Value, Len(Fmt(i))), Fmt(i)) & "┃"
        Else
          str = str & Format(Left$(.Fields(i).
Value, Len(Fmt(i))), Fmt(i)) & "│"
        End If
      End If
    Next
    strDy(intDc) = strDy(intDc) & str
    intDc = intDc + 1
    .MoveNext
  Loop
  strDy(intDc) = str2
  End With
End Sub

---- 在实际编程中还要排除二进制数据字段,全角与半角字符的匹配调整,处理数据中出现的换行符、回车符、制表符,等等,限于篇幅,这里不于介绍。
---- 2.rdoResultset对象

---- rdoResultset对象的表格自动生成方法与Recordset对象的方法相似,在处理过程中把Recordset对象的RecordCount属性用rdoResultset对象的RowCount属性替换,Fields集合用rdoColumns替换,Field对象用rdoColumn替换,其余相同。例如:

---- 引用Data控件MyData结果集中第三个字段的名称用:MyData.Recordset.Fields(3).Name。

---- 引用RDC控件MyRDC相应字段的名称用: MyRDC.Resultset.rdoColumns(3).Name。

三.表格的输出
---- 表格的输出包括二个部分,一是屏幕预览,二是打印机输出。屏幕预览是把存放在数组中的表格通过在PictureBox控件上调用 Print方法显示出来而实现的。打印输出是把同样的内容通过 Printer对象的 Print方法实现的。下面例示打印机输出的实现方法:
  Printer.Font.Name = "黑体"  
       注释:设置标题字体
  Printer.Font.Size = 18           
  注释:设置标题字体大小
  Printer.Print strDy(0)           
  注释:打印标题
  Printer.Print strDy(1)           
  注释:打印空行
  Printer.Font.Name = "楷体_GB2312"
注释:设置日期字体
  Printer.Font.Size = 16            
注释:设置日期字体大小
  Printer.Print strDy(2)            
注释:打印日期
  Printer.Font.Name = "宋体"     
    注释:设置表格字体
  Printer.Font.Size = 11         
    注释:设置表格字体大小
  Printer.Print strDy(3)         
    注释:以下打印表格内容
  Printer.Print strDy(4)
  For i = 6 To intDc
    If i <  intDc Then
      Printer.Print strDy(5)
      Printer.Print strDy(i)
    Else
      Printer.Print strDy(i)         注释:表尾
    End If
  Next
  Printer.EndDoc              
       注释:打印完成

---- 屏幕预览程序与打印机的输出相同,只要把 Printer对象换成PictureBox控件对象并使用相应的对象属性及方法,同时,在编程中还要处理分页、纸张、打印设置、字体、出错等等,限于篇幅,这里不一一介绍。在控件中实现了字体及其大小的设置、纸张的设置、自动分页、自动顺序号,任选列的汇总、选择打印、多份打印等功能,感兴趣的朋友可与本人联系。
---- 该控件在中文Windows 95、VB 5下运行通过。