基于数据库的信息管理系统,最核心的功能是将数据存储到数据库中,并可以对数据进行增加、修改、删除、查询等功能。其中查询功能更是用户经常使用的功能,一个可改变条件的灵活、快捷、准确的查询会给用户带来极大的方便,也给软件本身带来了更大的价值。
二、通用查询的设计
1.对象的添加
在VB6.0环境中,建立一个标准的EXE工程,在工程的部件中添加ADO、MSHFlexGrid两个控件,然后在窗体中添加两个MSHFlexGrid对象,分别改名为Grid1和Grid2,添加三个Command按钮Command1,做成控件数组,添加两个Command按钮,分别改名为Cmd_confirm、Cmd_cancel,最后添加四个Combo控件Combo1,做成控件数组。
2.各控件的功能
Grid1:查询条件输入区,初始值设为2行,5列。
Grid2:查询结果显示区,可根据查询结果,自动调整行列,并显示记录。
Command1(0): Caption属性为“增加行”,具有为Grid1增加行数的功能。
Command1(1): Caption属性为“删除行”,具有为Grid1删除行数的功能。
Command1(2): Caption属性为“清除条件”,具有清除查询条件的功能。
Cmd_confirm:根据Grid1中的查询条件,查询数据的功能。
Cmd_cancel:退出查询功能。
Combo1(0):用于提供连接条件“And”和“or”。
Combo1(1):提供查询的内容(表或视图中字段对用的汉字别名)。
Combo1(2):提供查询的关系条件(“=”、“>”等)。
Combo1(3):提供Combo1(4)对应的查询字段的值。
Combo1(4):与Combo1(1)同步,提供查询的内容(表或视图中的字段名)。
3.设计后的界面
通用查询界面如下图所示:
图 通用查询界面
三、代码实现
1.自定义的对象及变量
Option Explicit
Public cn As ADODB.Connection '数据库的连接对象
Public rs As ADODB.Recordset '数据库的记录集对象
Public strsumdemand As String '通用查询求和语句
Public strcondition As String '通用查询条件
'-------------------------需要编程者根据要查询的表或视图来改变的条件
Public constr As String '数据库连接字符串
Public strsql As String '传递查询条件(字段无汉字别名)
Public strtable As String '传递查询表名
Public strdemand As String '通用查询语句(字段具有汉字别名)
'-------------------------------------------------------
2.用户自定义过程
(1)完成对数据库连接对象cn的赋值,并打开,以备使用。
Public Sub opencn() '打开连接
Set cn = New ADODB.Connection
' constr字符串,用于编程者根据所使用的数据库不同(如Access、SQL Server),来修改成不同的连接字符串。本例中以cx.mdb为例。
constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "/cx.mdb;Persist Security Info=False"
cn.Open constr
End Sub
(2)完成对数据库连接对象cn关闭,及置空功能。
Public Sub closecn()
cn.Close
Set cn = Nothing
End Sub
(3)完成对数据库记录集对象rs的设置,并根据查询条件,对数据库进行查询,返回结果集。
Public Sub openrs(sqlstr As String)
Set rs = New ADODB.Recordset
With rs
.ActiveConnection = cn
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = adLockBatchOptimistic
.Source = sqlstr
.Open
Set .ActiveConnection = Nothing
End With
End Sub
(4)完成对数据库连接记录集对象rs关闭,及置空功能。
Public Sub closers()
rs.Close
Set rs = Nothing
End Sub
(5)根据查询结果,将符合条件的记录添加到Grid2中,并显示。
Public Sub fillgrid()
Dim j As Integer
Dim i As Integer
Dim m As Integer '记录集行值
Dim n As Integer '记录集列值
Dim rssum As ADODB.Recordset
Opencn '调用子过程Opencn,打开数据库连接
'调用子过程Openrs,并传参数—查询的内容
openrs strdemand & strcondition
closecn '调用子过程closecn,关闭数据库连接
Grid2.Clear '清空表格Grid2
Grid2.FormatString = ""
'判断记录集中是否有记录,无记录跳出程序段
If rs.RecordCount <= 0 Then Exit Sub
m = rs.RecordCount 'm变量用来记录记录集rs中的记录总数
n = rs.Fields.Count 'n变量用来记录记录集rs的字段的总数
rs.MoveFirst
'---设置Grid2的0至n-1列的对齐方式和文本内容
For i = 0 To n - 1
Grid2.FormatString = Grid2.FormatString & " |< " & rs.Fields(i).Name
Next
'-------------------------------------------------------
Grid2.Rows = m + 1 '设置Grid2的总行数
Grid2.Cols = n + 1 '设置Grid2的总列数
'---将查询到的记录添加到Grid2中
For i = 1 To m '------------------------------行循环
For j = 1 To n '=====================列循环
Grid2.TextMatrix(i, j) = rs.Fields(j - 1).Value & ""
If m <= 100 Then
If i Mod 2 = 0 Then
Grid2.Col = j
Grid2.Row = i
Grid2.CellBackColor = &HFEFBDE
End If
End If
Next j '=================================
rs.MoveNext
Next i '------------------------------------
'---------------向Grid2中添加查询到的记录
If strsumdemand <> "" Then
opencn
Grid2.Rows = Grid2.Rows + 1
Grid2.TextMatrix(Grid2.Rows - 1, 1) = "合计"
Set rssum = New ADODB.Recordset
rssum.Open strsumdemand & strcondition, cn, adOpenKeyset, adLockReadOnly
For j = 1 To n
For i = 0 To rssum.Fields.Count - 1
If Grid2.TextMatrix(0, j) = rssum.Fields(i).Name Then
Grid2.TextMatrix(Grid2.Rows - 1, j) = _
& rssum.Fields(i).Value & ""
End If
Next i
Next j
closecn
End If
Grid2.MergeCells = flexMergeRestrictColumns
Grid2.MergeCol(1) = True
Me.Caption = Mid(Me.Caption, 1, InStr(Me.Caption, "表")) & "(共有" & Grid2.Rows - 1 & "条记录)"
'-----------------------------------------------------------
End Sub
(6)根据参数com和rs,向combobox中添加值
Public Sub fillcom1(com As ComboBox, rs As ADODB.Recordset)'填充combobox
com.Clear
If rs.RecordCount <= 0 Then Exit Sub
rs.MoveFirst
Do Until rs.EOF
com.AddItem (rs.Fields(0).Value) & ""
rs.MoveNext
Loop
rs.MoveFirst
End Sub
3.窗体的加载事件
Private Sub Form_Load()
' 给strsql变量赋值,值为SELECT语句,参考格式如下,只有字段名,字段无别名,这是为了与界面用户操作的查询字段同步,给编程者提供的字段名称
strsql = "SELECT STUDENT_TBL.STUID, STUDENT_TBL.STUname, STUDENT_TBL.STUsorce, STUDENT_TBL.STUchive FROM STUDENT_TBL"
' 给strdemand变量赋值,值为SELECT语句,参考格式如下,给字段取别名是为了在选择条件的界面给用户提供汉字的参考
strdemand = "SELECT STUDENT_TBL.STUID as 学号, STUDENT_TBL.STUname as 姓名, STUDENT_TBL.STUsorce as 课程, STUDENT_TBL.STUchive as 成绩 FROM STUDENT_TBL"
' 给strtable变量赋值,值为要查询的表名或视图名
strtable = "STUDENT_TBL"
strsumdemand = ""
Dim i As Integer
' --------------给Grid1初始化,设置列宽、单元格对齐方式
Grid1.FormatString = " 逻辑符|^ 列 名 |^ 运算符 |^ 数据值 |"
Grid1.ColWidth(4) = 0
Grid1.ColWidth(3) = 2500
Grid1.ColWidth(2) = 1000
Grid1.ColWidth(1) = 1850
Grid1.ColWidth(0) = 1000
For i = 0 To 3
Grid1.Row = 0
Grid1.Col = i
Grid1.CellAlignment = 4
Next i
' -----------------------------------------------------
Opencn '调用子过程Opencn,打开数据库连接
openrs strdemand '调用子过程Openrs,并传参数—查询的内容
' --------------------向Combo1(1)中添加strdemand字符串中字段别名
For i = 0 To rs.Fields.Count - 1
Combo1(1).AddItem rs.Fields(i).Name
Next i
' --------------------向Combo1(4)中添加strsql字符串中字段名
openrs strsql
For i = 0 To rs.Fields.Count - 1
Combo1(4).AddItem rs.Fields(i).Name
Next i
closers
closecn
' ----------------------初始化Combo1(2)
With Combo1(2)
.AddItem " = "
.AddItem " > "
.AddItem " < "
.AddItem " >= "
.AddItem " <= "
.AddItem " <> "
.AddItem " like "
End With
' -----设置Combo1的0--3各元素与Grid1的0--3各列的宽度相同
Combo1(0).Width = 1000
Combo1(1).Width = 1850
Combo1(2).Width = 1000
Combo1(3).Width = 2500
End Sub
4.取消按钮的单击事件
Private Sub Cmd_cancel_Click()
Unload Me
End Sub
5.确定按钮的单击事件
Private Sub Cmd_confirm_Click()
Dim i As Integer
' -----根据Combo1(3)的特殊值,修改Grid1当前单元的文本
If Combo1(3).Visible = True Then
If Combo1(3).Text = "True" Then
Grid1.TextMatrix(Grid1.Row, 3) = "1"
ElseIf Combo1(3).Text = "Flase" Then
Grid1.TextMatrix(Grid1.Row, 3) = "0"
Else
Grid1.TextMatrix(Grid1.Row, 3) = Combo1(3).Text
End If
End If
strcondition = ""
' -----根据不同的关系运算,给strcondition变量赋值
If Grid1.Rows >= 2 And Grid1.TextMatrix(1, 1) <> "" Then
If Grid1.TextMatrix(1, 2) = " like " Then
strcondition = " where " & Grid1.TextMatrix(1, 4) & " like " & "'%" & Grid1.TextMatrix(1, 3) & "%'"
Else
strcondition = " where " & Grid1.TextMatrix(1, 4) & Grid1.TextMatrix(1, 2) & "'" & Grid1.TextMatrix(1, 3) & "'"
End If
For i = 2 To Grid1.Rows - 1
If Grid1.TextMatrix(i, 2) = " like " Then
strcondition = strcondition & Grid1.TextMatrix(i, 0) & Grid1.TextMatrix(i, 4) & " like " & "'%" & Grid1.TextMatrix(i, 3) & "%'"
Else
strcondition = strcondition & Grid1.TextMatrix(i, 0) & Grid1.TextMatrix(i, 4) & Grid1.TextMatrix(i, 2) & "'" & Grid1.TextMatrix(i, 3) & "'"
End If
Next i
End If
' -----调用过程Fillgrid,向Grid2中添加查询到的记录
Fillgrid
End Sub
6.Combo1的单击事件
Private Sub Combo1_Click(Index As Integer)
' ----控制Combo1(4)与Combo1(1)同步,并根据Combo1(1)中选的字段不同,向Combo1(3)中添加这一字段下的所有不重复的值
Dim tempsql As String
If Index = 1 Then
Combo1(4).ListIndex = Combo1(1).ListIndex
Grid1.TextMatrix(Grid1.Row, 4) = Combo1(4).Text
tempsql = "SELECT DISTINCT " & Combo1(4).Text & " from " & strtable
opencn
openrs tempsql
closecn
fillcom1 Combo1(3), rs
End If
Grid1.TextMatrix(Grid1.Row, Index) = Combo1(Index).Text
If Grid1.Text = "True" Then
Grid1.Text = "1"
ElseIf Grid1.Text = "False" Then
Grid1.Text = "0"
End If
End Sub
7.Command1的单击事件
Private Sub Command1_Click(Index As Integer)
Dim i As Integer
Select Case Index
Case 0 '清除条件
Grid1.Rows = 2
For i = 0 To 4
Grid1.TextMatrix(1, i) = ""
Next i
Case 1 '增加行
Grid1.Rows = Grid1.Rows + 1
Case 2 '删除行
If Grid1.Rows > 2 Then
Grid1.Rows = Grid1.Rows - 1
Else
For i = 0 To 4
Grid1.TextMatrix(1, i) = ""
Next i
End If
End Select
End Sub
8.Grid1的EnterCell事件,控制Combo1在Grid1中出现的位置
Private Sub Grid1_EnterCell()
Combo1(Grid1.Col).Visible = True
Combo1(Grid1.Col).Left = Grid1.Left + Grid1.CellLeft
Combo1(Grid1.Col).Top = Grid1.Top + Grid1.CellTop
Combo1(Grid1.Col).ZOrder 0
End Sub
9.Grid1的LeaveCell事件
实现将Combo1中的文本内容添加到Grid1相应的单元格中。
Private Sub Grid1_LeaveCell()
If Grid1.Row > 0 Then
Grid1.Text = Combo1(Grid1.Col).Text
If Grid1.Text = "True" Then
Grid1.Text = "1"
ElseIf Grid1.Text = "False" Then
Grid1.Text = "0"
End If
Combo1(Grid1.Col).Visible = False
End If
End Sub
四、通用查询功能的验证
为验证以上程序功能,建立一个实验数据库CX.mdb,在此数据库中添加一个表STUDENT_TBL,结构如表1所示:
表1 STUDENT_TBL表结构
字段名 | 字段数据类型 | 主键 | 说明 |
STUID | Varchar(12) | Yes | 学生编号 |
STUname | Varchar(50) |
| 学生姓名 |
STUsorce | Varchar(20) |
| 课程 |
STUchive | Varchar(50) |
| 成绩 |
表2 数据录入
学生编号 | 学生姓名 | 课程 | 成绩 |
200201050401 | 刘强 | VB | 80.5 |
200201050402 | 李飞 | VB | 95 |
200201050403 | 刘立 | VC++ | 65 |
constr字符串,用于编程者根据所使用的数据库不同(如Access、SQL Server),来修改成不同的连接字符串,本例中以cx.mdb为例:
constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "/cx.mdb;Persist Security Info=False"
strsql变量赋值,给编程者提供的字段名称:
strsql = "SELECT STUDENT_TBL.STUID, STUDENT_TBL.STUname, STUDENT_TBL.STUsorce, STUDENT_TBL.STUchive FROM STUDENT_TBL"
strdemand变量赋值,给用户提供汉字参考:
strdemand = "SELECT STUDENT_TBL.STUID as 学号, STUDENT_TBL.STUname as 姓名, STUDENT_TBL.STUsorce as 课程, STUDENT_TBL.STUchive as 成绩 FROM STUDENT_TBL"
strtable变量赋值,值为要查询的表名或视图名:
strtable = "STUDENT_TBL"
修改以上代码后,将工程及子文件保存,然后运行程序,就会得到想要的功能。
五、结语
综上所述,利用以上代码,只需程序员根据程序要访问的数据库不同,改变连接字符串变量constr,就可以访问SQL Server、Access等类型的数据库,再根据要访问的表或试图的结构,写成SELECT语句的形式,对strsql、strdemand、strtable三个变量赋值,即可完成复杂的自由查询功能。同时这个功能代码,不会影响项目中其它程序功能,可作为单独的功能附加到程序中,从而增强程序的健壮性。可以说利用以上代码实现自由查询功能,既为程序员减轻了编程的压力,同时又获得了用户对开发者的认可,这也正是本文作者的意图,让程序员的编程更轻松,让软件为用户提供更灵活而强大的功能!
参考文献:
[1] Microsoft Corporation著 微软[中国]有限公司 译.中文Visual Basic 6.0程序员指南 ,北京希望出版社1998.6.
[2] 马艳红郑建伟等开发 国电电力物资信息管理系统.大连益友电脑有限公司,2002.3.