一、需求分析
在进行一个项目的设计之前,先要进行必要的需求分析。
现某图书馆需要管理其各种人员和图书信息,希望实现办公的信息化,通过建立一个图书管理系统来管理图书。其完成的功能如下:
(1) 可以实现图书的登记、借阅和赔偿的管理。
(2) 可以实现对图书的各种信息的查询,包括逐个浏览,以及对图书信息的增加、删除和编辑操作。另外,可以根据输入的信息来检索某个图书的信息。
(3) 可以实现对管理人员的投诉管理。
(4) 可以实现对值班人员的管理。
系统的功能模块图如图1所示。
本实例根据上面的设计规划出的实体有图书登记实体、图书借阅实体、图书赔偿实体、查询输出实体、值班管理实体、投诉管理实体。各个实体具体的描述E-R图如下。
图书登记实体E-R图如图2所示。
图书借阅实体E-R图如图3所示。

图1 系统的功能模块图

图2 图书登记实体E-R图

图3 图书借阅实体E-R图
图书赔偿实体E-R图如图4所示。

图4 图书赔偿实体E-R图
投诉管理实体E-R图如图5所示。

图5 投诉管理实体E-R图
值班管理实体E-R图如图6所示。

图6 值班管理实体E-R图
查询输出实体E-R图如图7所示。

图7 查询输出实体E-R图
二、结构设计
根据上面的需求分析,设计好数据库系统,然后开发应用程序可以考虑的窗体的系统,每一个窗体实现不同的功能,可以设计下面的几个模块。
● 图书管理模块:用来实现图书的登记、借阅、赔偿。
● 图书资料模块:用来实现图书的查询输出。
● 值班管理模块:用来实现管理人员的值班浏览。
● 投诉管理模块:用来实现对管理人员的投诉管理。
● 系统管理模块:用来实现用户的增加、删除和修改等操作。
三、数据库设计 这里的数据库采用Access,用ADO作为连接数据对象。
1、建立Access 数据库
启动Access,建立一个空的数据库book.mdb,如图8所示。
使用程序设计器建立系统需要的表格如下。
图书登记表,如图9所示。

图8 建立数据库book.mdb 图9 图书登记表
图书借阅表,如图10所示。图书赔偿表,如图11所示。

图10 图书借阅表 图11 图书赔偿表
图书资料表,如图12所示。系统管理表,如图13所示。

图12 图书资料表 图13 系统管理表
投诉管理表,如图14所示。

图14 投诉管理表
值班管理表,如图15所示。

图15 值班管理表
2、连接数据
在Visual Basic环境下,选择“工程”→“引用”命令,在随后出现的对话框中选择“Microsoft ActiveX Data Objects 2.0 Library”,然后单击“确定”按钮,如图16所示。

图16 引用ADO连接数据库
在程序设计的公共模块中,先定义ADO连接对象。语句如下:
Public conn As New ADODB.Connection ' 标记连接对象
然后在子程序中,用如下的语句即可打开数据库:
Dim connectionstring As String
connectionstring = "provider=Microsoft.Jet.oledb.4.0;" &_
"data source=book.mdb"
conn.Open connectionstring
3、设置ODBC
VB的ADO对象是通过ODBC来访问数据库,所以还要建立ODBC数据引擎接口。
打开控制面板中的“管理工具”→“数据源”(ODBC),出现如图17所示的对话框。

图17 ODBC对话框
单击“添加”按钮,出现“创建新数据源”对话框,如图18所示。

图18 “创建新数据源”对话框
选择Microsoft Access Driver(*.mdb),单击“完成”按钮,出现如图19所示对话框。

图19 设置连接数据源
在“数据源名”文本框中添加一个名字,单击“确定”按钮完成系统默认连接设置。然后在ODBC对话框中单击“确定”按钮完成ODBC设置。
界面设计 设计好的界面如图20所示。

图20 图书管理系统界面
这是一个多文档界面(MDI)应用程序,可以同时显示多个文档,每个文档显示在各自的窗体中。MDI 应用程序中常有包含子菜单的“窗体”选项,用于在窗体或文档之间进行切换。
菜单应用程序中,有5个菜单选项,每个选项对应着E-R图的一个子项目。
1、创建主窗体
首先创建一个工程,命名为图书管理系统,选择“工程”→“添加MDI窗体”命令,则在项目中添加了主窗体。该窗体的一些属性如表1所示。
表1 主窗体的属性
| 属 |
性值 |
| Caption |
图书管理系统 |
| Name |
Main |
| Menu |
Mainmenu1 |
| Windowstate |
Maxsize |
Windowstate的值为Maxsize,即程序启动之后自动最大化。
将“菜单”组件从“工具箱”拖到窗体上。创建一个 Text 属性设置为“文件”的顶级菜单项,且带有名为“关闭”的子菜单项。类似地创建一些菜单项,如表2所示。
表2 菜 单 项 表
| 菜 单 名 称 |
Text属性 |
功 能 描 述 |
| MenuItem1 |
图书管理 |
顶级菜单,包含子菜单 |
| MenuItem2 |
图书登记 |
调出图书登记窗体 |
| MenuItem3 |
图书借阅 |
调出图书借阅窗体 |
| MenuItem4 |
图书赔偿 |
调出图书赔偿窗体 |
| MenuItem5 |
图书资料 |
顶级菜单,包含子菜单 |
| MenuItem6 |
查询输出 |
调出查询输出窗体 |
| MenuItem7 |
值班管理 |
顶级菜单,没有子菜单 |
| MenuItem8 |
投诉管理 |
顶级菜单,没有子菜单 |
| MenuItem9 |
系统管理 |
顶级菜单,包含子菜单 |
| MenuItem10 |
增加用户 |
调出用户窗体 |
| MenuItem11 |
修改密码 |
调出密码窗体 |
| MenuItem12 |
退出 |
系统退出 |
主窗体如图21所示。

图21 主窗体
2、创建各子窗体
选择“工程”→“添加窗体”命令,添加子窗体。
在新建Visual Basic工程时自带的窗体中,将其属性MIDChild改成True,则这个窗体成为MID窗体的子窗体。
在这个项目中,要创建的子窗体如表3所示。
表3 所有子窗体
| 子 窗 体 名 |
Text |
| 图书登记 |
frmdengji |
| 图书借阅 |
frmjieyue |
| 图书赔偿 |
frmpeichang |
| 增加新用户 |
frmadduser |
| 查询输出 |
frmfind |
| 登录系统 |
frmlogin |
| 修改密码 |
frmchangepwd |
下面分别给出这些子窗体,以及它们所使用的控件。
(1) 图书登记子窗体如图22所示,其控件如表4所示。

图22 图书登记子窗体
表4 图书登记子窗体控件
| 控 件 类 别 |
控件Name |
控件Text |
| Label |
Label1 |
编号 |
| Label2 |
书名 |
| Label3 |
类型 |
| Label4 |
购买日期 |
| Label5 |
定价 |
| TextBox |
Text1 |
(空) |
| Text2 |
(空) |
| Text3 |
(空) |
| Text4 |
(空) |
| Text5 |
(空) |
| CommandButton |
Command1 |
增加记录 |
| Command2 |
删除记录 |
| Command3 |
下一条 |
| Command4 |
上一条 |
| Command5 |
第一条 |
| Command6 |
最后一条 |
| Command7 |
退出 |
| ADO |
DataAdodc1 |
(空) |
| DataGrid |
DataGrid1 |
(空) |
图书借阅和图书赔偿子窗体分别如图23和图24所示,因为它们的控件与图书登记子窗体的雷同,在此不作介绍。

图23 图书借阅子窗体

图24 图书赔偿子窗体
(2) 增加用户子窗体如图25所示,其控件如表5所示。

图25 增加用户子窗体
表5 增加用户子窗体控件
| 控 件 类 别 |
控件Name |
控件Text |
| Label |
Label1 |
输入用户名 |
| Label2 |
输入密码 |
| Label3 |
确认密码 |
| Label4 |
选择权限 |
| TextBox |
Text1 |
(空) |
| Text2 |
(空) |
| Text3 |
(空) |
| ComboBox |
Comb1 |
(空) |
| CommandButton |
Commandl |
确定 |
| Command2 |
取消 |
(3) 修改密码子窗体如图26所示。

图26 修改密码子窗体
(4) 库房管理子窗体如图27所示。

图27 库房管理子窗体
其控件如表6所示。
表6 库房管理子窗体控件
| 控 件 类 别 |
控件Name |
控件Text |
| TextBox |
Text1 |
(空) |
| ComboBox |
Combo1 |
|
| MSFlexGrid |
MSFlexGrid1 |
|
(5) 查询子窗体如图28所示,其控件如表7所示。

图28 查询子窗体
表7 查询子窗体控件
| 控 件 类 别 |
控件Name |
控件Text |
| OptionButton |
Option1 |
按编号查询 |
| |
Option2 |
按购买日期查询 |
| Label |
Label1 |
从 |
| Label2 |
到 |
| Label3 |
从 |
| Label4 |
年 |
| Label5 |
月 |
| Label6 |
日 |
| Label7 |
到 |
| Label8 |
年 |
| Label9 |
月 |
| Label10 |
日 |
| Combo(0) ComboBox |
Combo1 |
(空) |
| Combo(1) ComboBox |
Combo1 |
(空) |
| Comboy(0) ComboBox |
Comboy |
(空) |
| Comboy(1) ComboBox |
Comboy |
(空) |
| Combom(0) ComboBox |
Combom |
(空) |
| Combom(1) ComboBox |
Combom |
(空) |
| Combod(0) ComboBox |
Combod |
(空) |
| Combod(1) ComboBox |
Combod |
(空) |
| CommandButton |
Command1 |
查询 |
| Command2 |
取消 |
(6) 用户登录子窗体如图29所示。
(7) 值班管理子窗体如图30所示,其控件如表8所示。

图29 用户登录子窗体 图30 值班管理子窗体
(8) 投诉管理子窗体如图31所示,其控件如表9所示。

图31 投诉管理子窗体
建立公共模块 1、显示目录
建立公共模块可以提高代码的效率,同时使得修改和维护代码都很方便。
创建公共模块的步骤如下:
(1) 在菜单中选择“工程”→“添加模块”命令,则出现模块对话框,如图32所示。
(2) 选择模块图标后,单击“打开”按钮,则模块已经添加到项目中了。默认情况下名为Module1。

图32 模块对话框
(3) 在模块中定义整个项目的公共变量。
Public conn As New ADODB.Connection ' 标记连接对象
Public userID As String ' 标记当前用户ID
Public userpow As String ' 标记用户权限
Public find As Boolean ' 标记查询
Public sqlfind As String ' 查询语句
Public rs_data1 As New ADODB.Recordset
Public findok As Boolean
Public frmdata As Boolean
Public Const keyenter = 13 ' enter键的ASCII码
在主窗体添加完菜单之后,就要为各个子菜单创建事件处理程序。
主窗体代码
在本项目中,子菜单事件都是Click事件,这里先给出主窗体部分的代码。
下面是响应“增加用户”子菜单Click事件,调出增加用户窗体代码。
Private Sub adduser_Click()
frmadduser.Show
End Sub
下面是响应“查询输出”子菜单Click事件,调出查询输出窗体代码。
Private Sub chaxunshuchu_Click()
frmfind.Show
End Sub
下面是响应“退出”子菜单Click事件,调出退出窗体代码。
Private Sub exit_Click()
Unload Me
End Sub
下面是响应“图书登记”子菜单Click事件,调出图书登记窗体代码。
Private Sub checkin_Click()
frmdengji.Show
End Sub
下面是响应“修改密码”子菜单Click事件,调出修改密码窗体代码。
Private Sub changepwd_Click()
frmchangepwd.Show
End Sub
下面是响应“图书借阅”子菜单Click事件,调出图书借阅窗体代码。
Private Sub borrow_Click()
frmjieyue.Show
End Sub
下面是响应“图书赔偿”子菜单Click事件,调出图书赔偿窗体代码。
Private Sub tushupeichang_Click()
frmpeichang.Show 1
End Sub
下面是响应“值班管理”菜单Click事件,调出值班管理窗体代码。
Private Sub zhibanguanli_Click()
frmzhiban.Show 1
End Sub
下面是响应“投诉管理”子菜单Click事件,调出投诉管理窗体代码。
Private Sub tousuguanli_Click()
frmtousu.Show 1
End Sub
2、各子窗体的代码
在各个子窗体建立好后,就可以根据各个子窗体的功能给它们添加相应代码了。
(1) 图书登记子窗体代码
本窗体用来填写图书登记的信息,用ADO来连接数据库,是本窗体的重点。采用MDI的子程序,所以运行后,它出现在主程序的界面下,如图33所示。

图33 图书登记子窗体
按钮控件要求先填写基本信息,然后与数据库信息比较。
Private Sub Command1_Click()
On Error GoTo adderr
Text1.SetFocus
Adodc1.Recordset.AddNew
Exit Sub
adderr:
MsgBox Err.Description
End Sub
Private Sub Command2_Click()
On Error GoTo deleteerr
With Adodc1.Recordset
If Not .EOF And Not .BOF Then
If MsgBox("删除当前记录吗?", vbYesNo + vbQuestion) = vbYes Then
.Delete
.MoveNext
If .EOF Then .MoveLast
End If
End If
End With
Exit Sub
deleteerr:
MsgBox Err.Description
End Sub
Private Sub Command3_Click()
Adodc1.Recordset.MoveNext
If Adodc1.Recordset.EOF Then
MsgBox "这是最后一条记录", vbOKCancel + vbQuestion
Adodc1.Recordset.MoveLast
End If
End Sub
Private Sub Command4_Click()
Adodc1.Recordset.MovePrevious
If Adodc1.Recordset.BOF Then
MsgBox "这是第一条记录", vbOKCancel + vbQuestion
Adodc1.Recordset.MoveFirst
End If
End Sub
Private Sub Command5_Click()
If Adodc1.Recordset.EOF Then
MsgBox "记录空", vbOKCancel + vbQuestion
End
Else
Adodc1.Recordset.MoveFirst
Exit Sub
End Sub
Private Sub Command6_Click()
If Adodc1.Recordset.RecordCount = 0 Then
MsgBox "空记录", vbOKCancel + vbQuestion
End
Else
Adodc1.Recordset.MoveLast
End If
End Sub
Private Sub Command7_Click()
MDIForm1.Show
frmdengji.Hide
End Sub
图书借阅和图书赔偿子窗体运行后如图34和图35所示,因为它们的代码和图书登记子窗体的代码雷同,在此不做重复。

图34 图书借阅子窗体运行效果

图35 图书赔偿子窗体运行效果
(2) 增加用户子窗体代码
增加用户子窗体是用来增加用户的用户名、密码和权限的。其运行效果如图36所示。
单击“确定”按钮后,还要返回一个信息框,提示成功信息,如图37所示。

图36 增加用户子窗体运行效果 图37 成功信息框
窗体部分代码的思路是,收集输入的表中的字符串,然后与数据库中的系统的用户数据比较,如果不存在,则允许添加。
Private Sub Command1_Click()
Dim sql As String
Dim rs_add As New ADODB.Recordset
If Trim(Text1.Text) = "" Then
MsgBox "用户名不能为空", vbOKOnly + vbExclamation, ""
Exit Sub
Text1.SetFocus
Else
sql = "select * from 系统管理"
rs_add.Open sql, conn, adOpenKeyset, adLockPessimistic
While (rs_add.EOF = False)
If Trim(rs_add.Fields(0)) = Trim(Text1.Text) Then
MsgBox "已有这个用户", vbOKOnly + vbExclamation, ""
Text1.SetFocus
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Combo1.Text = ""
Exit Sub
Else
rs_add.MoveNext
End If
Wend
If Trim(Text2.Text) <> Trim(Text3.Text) Then
MsgBox "两次密码不一致", vbOKOnly + vbExclamation, ""
Text2.SetFocus
Text2.Text = ""
Text3.Text = ""
Exit Sub
ElseIf Trim(Combo1.Text) <> "system" And Trim(Combo1.Text) <> "guest" Then
MsgBox "请选择正确的用户权限", vbOKOnly + vbExclamation, ""
Combo1.SetFocus
Combo1.Text = ""
Exit Sub
Else
rs_add.AddNew
rs_add.Fields(0) = Text1.Text
rs_add.Fields(1) = Text2.Text
rs_add.Fields(2) = Combo1.Text
rs_add.Update
rs_add.Close
下面是返回成功信息对话框的代码:
MsgBox "添加用户成功", vbOKOnly + vbExclamation, ""
Unload Me
End If
End If
End Sub
(3) 修改密码子窗体代码
修改密码子窗体是用来修改用户密码的。其运行效果如图38所示。

图38 修改密码子窗体运行效果
在“确定”按钮的Click事件中添加如下代码:
Private Sub Command1_Click()
Dim rs_chang As New ADODB.Recordset
Dim sql As String
If Trim(Text1.Text) <> Trim(Text2.Text) Then
MsgBox "密码不一致!", vbOKOnly + vbExclamation, ""
Text1.SetFocus
Text1.Text = ""
Text2.Text = ""
Else
sql = "select * from 系统管理 where 用户名='" & userID & "'"
rs_chang.Open sql, conn, adOpenKeyset, adLockPessimistic
rs_chang.Fields(1) = Text1.Text
rs_chang.Update
rs_chang.Close
MsgBox "密码修改成功", vbOKOnly + vbExclamation, ""
Unload Me
End If
End Sub

在上述代码中,首先比较两个表中的数据是否一致,然后用rs_chang.Fields(1) = Text1.Text语句把代码输入到数据库中。最后,用MsgBox "密码修改成功", vbOKOnly + vbExclamation,""语句弹出一个信息框,告诉修改成功,如图39所示。
显示目录
(4) 库房管理子窗体代码
库房管理子窗体是用来管理图书资料的。其运行效果如图40所示。

图40 库房管理子窗体
实际上,设计库房管理子窗体的程序代码与增加用户子窗体的代码在思路上是完全相同的。就是在DataGrid的文本框中显示图书进出的清单,最后把填写的明细存储到数据库中。
检查代码如下:
Option Explicit
Dim rs_data2 As New ADODB.Recordset
Dim select_row As String
Dim showgrid2 As Boolean
Dim rs_custom As New ADODB.Recordset
Dim jinchu As String ' 进出库标志
Dim modify As Boolean ' 修改状态标志
Private Sub cmdexit_Click()
Unload Me
End Sub
Private Sub Form_Load()
On Error GoTo loaderror
Dim sql As String
sql = "select * from 图书资料"
rs_custom.CursorLocation = adUseClient
rs_custom.Open sql, conn, adOpenKeyset, adLockPessimistic
While Not rs_custom.EOF
Combo1.AddItem rs_custom.Fields(0)
rs_custom.MoveNext
Wend
findok = True
modify = False ' 非修改状态
showgrid2 = False
displaygrid1 ' 调用显示Datagrid1子程序
loaderror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
'显示msflexgrid1子程序
Public Sub displaygrid1()
Dim i As Integer
On Error GoTo displayerror
setgrid
setgridhead
MSFlexGrid1.Row = 0
If Not rs_data1.EOF Then
rs_data1.MoveFirst
Do While Not rs_data1.EOF
MSFlexGrid1.Row = MSFlexGrid1.Row + 1
MSFlexGrid1.Col = 0
If Not IsNull(rs_data1.Fields(0)) Then MSFlexGrid1.Text = rs_data1.Fields(0) Else
MSFlexGrid1.Text = ""
MSFlexGrid1.Col = 1
If Not IsNull(rs_data1.Fields(1)) Then MSFlexGrid1.Text = rs_data1.Fields(1) Else
MSFlexGrid1.Text = ""
MSFlexGrid1.Col = 2
If Not IsNull(rs_data1.Fields(2)) Then MSFlexGrid1.Text = rs_data1.Fields(2) Else
MSFlexGrid1.Text = ""
MSFlexGrid1.Col = 3
If Not IsNull(rs_data1.Fields(3)) Then MSFlexGrid1.Text = rs_data1.Fields(3) Else
MSFlexGrid1.Text = ""
MSFlexGrid1.Col = 4
If Not IsNull(rs_data1.Fields(4)) Then MSFlexGrid1.Text = rs_data1.Fields(4) Else
MSFlexGrid1.Text = ""
MSFlexGrid1.Col = 5
If Not IsNull(rs_data1.Fields(5)) Then MSFlexGrid1.Text = rs_data1.Fields(5) Else
MSFlexGrid1.Text = ""
rs_data1.MoveNext
Loop
End If
displayerror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
Public Sub setgrid()
Dim i As Integer
On Error GoTo seterror
With MSFlexGrid1
.ScrollBars = flexScrollBarBoth
.FixedCols = 0
.Rows = rs_data1.RecordCount + 1
.Cols = 6
.SelectionMode = flexSelectionByRow
For i = 0 To .Rows - 1
.RowHeight(i) = 315
Next
For i = 0 To .Cols - 1
.ColWidth(i) = 1300
Next i
End With
Exit Sub
seterror:
MsgBox Err.Description
End Sub
Public Sub setgridhead()
On Error GoTo setheaderror
MSFlexGrid1.Row = 0
MSFlexGrid1.Col = 0
MSFlexGrid1.Text = "编号"
MSFlexGrid1.Col = 1
MSFlexGrid1.Text = "购买日期"
MSFlexGrid1.Col = 2
MSFlexGrid1.Text = "书名"
MSFlexGrid1.Col = 3
MSFlexGrid1.Text = "类型"
MSFlexGrid1.Col = 4
MSFlexGrid1.Text = "定价"
MSFlexGrid1.Col = 5
MSFlexGrid1.Text = "备注"
Exit Sub
setheaderror:
MsgBox Err.Description
End Sub
Private Sub Form_Unload(Cancel As Integer)
findok = False
rs_data1.Close
rs_custom.Close
End Sub
Private Sub MSFlexGrid1_Click()
On Error GoTo griderror
Dim getrow As Long
getrow = MSFlexGrid1.Row
If MSFlexGrid1.Rows = 1 Then
MsgBox "无相关记录", vbOKOnly + vbExclamation, ""
Else
select_row = MSFlexGrid1.TextMatrix(getrow, 0)
End If
griderror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
Public Sub showdata()
With MSFlexGrid2
.Rows = rs_data2.RecordCount + 1
.Row = 0
If Not rs_data2.EOF Then
rs_data2.MoveFirst
Do While Not rs_data2.EOF
.Row = .Row + 1
.Col = 0
If Not IsNull(rs_data2.Fields(0)) Then .Text = rs_data2.Fields(0) Else .Text = ""
.Col = 1
If Not IsNull(rs_data2.Fields(1)) Then .Text = rs_data2.Fields(1) Else .Text = ""
.Col = 2
If Not IsNull(rs_data2.Fields(2)) Then .Text = rs_data2.Fields(2) Else .Text = ""
.Col = 3
If Not IsNull(rs_data2.Fields(3)) Then .Text = rs_data2.Fields(3) Else .Text = ""
.Col = 4
If Not IsNull(rs_data2.Fields(4)) And CDbl(rs_data2.Fields(4)) < 0 Then
.Text = -CDbl(rs_data2.Fields(4))
Else
.Text = rs_data2.Fields(4)
End If
.Col = 5
If Not IsNull(rs_data2.Fields(5)) Then .Text = rs_data2.Fields(5) Else .Text = ""
.Col = 6
If Not IsNull(rs_data2.Fields(6)) Then .Text = rs_data2.Fields(6) Else .Text = ""
.Col = 7
If Not IsNull(rs_data2.Fields(7)) And CDbl(rs_data2.Fields(4)) < 0 Then
.Text = -CDbl(rs_data2.Fields(7))
Else
.Text = rs_data2.Fields(7)
End If
.Col = 8
If Not IsNull(rs_data2.Fields(8)) Then .Text = rs_data2.Fields(8) Else .Text = ""
rs_data2.MoveNext
Loop
rs_data2.MoveLast
End If
End With
End Sub
(5) 查询子窗体代码
查询子窗体是用来查询库房中图书资料明细的。其运行效果如图41所示。

图41 查询子窗体运行效果
在列表框中给出编号或年月日后,“查询”按钮的Click事件将给出与数据库查找比较的结果。
Private Sub Command1_Click()
On Error GoTo cmderror
Dim find_date1 As String
Dim find_date2 As String
If Option1.Value = True Then
sqlfind = "select * from 图书资料 where 编号 between '" & _
Combo1(0).Text & "'" & " and " & "'" & Combo1(1).Text & "'"
End If
If Option2.Value = True Then
find_date1 = Format(CDate(Comboy(0).Text & "-" & _
Combom(0).Text & "-" & Combod(0).Text), "yyyy-mm-dd")
find_date2 = Format(CDate(Comboy(1).Text & "-" & _
Combom(1).Text & "-" & Combod(1).Text), "yyyy-mm-dd")
sqlfind = "select * from 图书资料 where 购买日期 between #" & _
find_date1 & "#" & " and" & " #" & find_date2 & "#"
End If
rs_data1.Open sqlfind, conn, adOpenKeyset, adLockPessimistic
frmdatamanage.displaygrid1
Unload Me
cmderror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
运行查询子窗体时,组合框中就已经从数据库中提取了货单号和年月日两个待查条件。
Dim i As Integer
Dim sql As String
If findok = True Then
rs_data1.Close
End If
sql = "select * from 图书资料 order by 编号 desc"
rs_find.CursorLocation = adUseClient
rs_find.Open sql, conn, adOpenKeyset, adLockPessimistic
If rs_find.EOF = False Then ' 添加编号
With rs_find
Do While Not .EOF
Combo1(0).AddItem .Fields(0)
Combo1(1).AddItem .Fields(0)
.MoveNext
Loop
End With
End If
For i = 2001 To 2005 ' 添加年
Comboy(0).AddItem i
Comboy(1).AddItem i
Next i
For i = 1 To 12 ' 添加月
Combom(0).AddItem i
Combom(1).AddItem i
Next i
For i = 1 To 31 ' 添加日
Combod(0).AddItem i
Combod(1).AddItem i
Next i
End Sub
查询完毕后,输出查询结果,如图42所示。

图42 查询结果
http://book.csdn.net 2006-31 16:26:00
显示目录
(6) 用户登录子窗体代码
运行的用户登录子窗体如图43所示。

图43 运行的用户登录子窗体
在本项目中,用户登录子窗体是运行的第一个界面,它的作用是检查用户名和密码是否正确。由于用户的资料是存放在数据库中,所以在启动该子窗体时,就已经连接了数据库。其代码如下:
Private Sub Form_Load()
Dim connectionstring As String
connectionstring = "provider=Microsoft.Jet.oledb.4.0;" & _
"data source=book.mdb"
conn.Open connectionstring
cnt = 0
End Sub
“确定”按钮的作用是检查输入的数据是否与数据库中的数据一致。
Private Sub Command1_Click()
Dim sql As String
Dim rs_login As New ADODB.Recordset
If Trim(txtuser.Text) = "" Then ' 判断输入的用户名是否为空
MsgBox "没有这个用户", vbOKOnly + vbExclamation, ""
txtuser.SetFocus
Else
sql = "select * from 系统管理 where 用户名='" & txtuser.Text & "'"
rs_login.Open sql, conn, adOpenKeyset, adLockPessimistic
If rs_login.EOF = True Then
MsgBox "没有这个用户", vbOKOnly + vbExclamation, ""
txtuser.SetFocus
Else ' 检验密码是否正确
用户名和密码通过后,要关闭本窗体并打开主窗体。
If Trim(rs_login.Fields(1)) = Trim(txtpwd.Text) Then
userID = txtuser.Text
userpow = rs_login.Fields(2)
rs_login.Close
Unload Me
MDIForm1.Show
Else
MsgBox "密码不正确", vbOKOnly + vbExclamation, ""
txtpwd.SetFocus
End If
End If
End If
' 只能输入3次
cnt = cnt + 1
If cnt = 3 Then
Unload Me
End If
Exit Sub
End Sub
(7) 值班管理子窗体代码
值班管理子窗体的作用是把值班人员的时间安排形成列表。运行的值班管理子窗体如图44所示。

图44 运行的值班管理子窗体
先定义连接数据库的变量:
Option Explicit
Dim rs_zhiban As New ADODB.Recordset
然后列出窗体部分的代码。
Private Sub cmdadd_Click()
On Error GoTo adderror
If cmdadd.Caption = "新增记录" Then ' 当此按钮的状态为为“增加记录”时
cmdadd.Caption = "确定" ' 按钮名称改“确定”
cmddel.Enabled = False
DataGrid1.AllowAddNew = True
DataGrid1.AllowUpdate = True ' 设定DataGrid可以增加记录
Else
If Not IsNull(DataGrid1.Bookmark) Then
If Not IsDate(Trim(DataGrid1.Columns("值班开始日期").CellText(DataGrid1.Bookmark))) Then
MsgBox "请按照格式yyyy-mm-dd输入值班开始日期", vbOKOnly + vbExclamation, ""
Exit Sub
End If
If Not IsDate(Trim(DataGrid1.Columns("值班开始时间").CellText(DataGrid1.Bookmark))) Then
MsgBox "请按照格式hh-mm输入值班开始时间", vbOKOnly + vbExclamation, ""
Exit Sub
End If
If Not IsDate(Trim(DataGrid1.Columns("值班截止日期").CellText(DataGrid1.Bookmark))) Then
MsgBox "请按照格式yyyy-mm-dd输入值班截止日期", vbOKOnly + vbExclamation, ""
Exit Sub
End If
If Not IsDate(Trim(DataGrid1.Columns("值班截止时间").CellText(DataGrid1.Bookmark))) Then
MsgBox "请按照格式hh-mm输入值班截止时间", vbOKOnly + vbExclamation, ""
Exit Sub
End If
If Trim(DataGrid1.Columns("值班人").CellText(DataGrid1.Bookmark)) = "" Then
MsgBox "值班人不能为空!", vbOKOnly + vbExclamation, ""
Exit Sub
End If
rs_zhiban.Update
MsgBox "添加信息成功!", vbOKOnly + vbExclamation, ""
DataGrid1.AllowAddNew = False
DataGrid1.AllowUpdate = False
Else
MsgBox "没有添加信息!", vbOKOnly + vbExclamation, ""
End If
cmdadd.Caption = "新增记录"
cmddel.Enabled = True
End If
adderror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
Private Sub cmdcancel_Click()
Unload Me
MDIForm1.Show
End Sub
Private Sub cmddel_Click()
Dim answer As String
On Error GoTo delerror
answer = MsgBox("确定要删除吗?", vbYesNo, "")
If answer = vbYes Then
DataGrid1.AllowDelete = True
rs_zhiban.Delete
rs_zhiban.Update
DataGrid1.Refresh
MsgBox "成功删除!", vbOKOnly + vbExclamation, ""
DataGrid1.AllowDelete = False
Else
Exit Sub
End If
delerror:
If Err.Number <> 0 Then
MsgBox Err.Description
End If
End Sub
Private Sub Form_Load()
Dim sql As String
On Error GoTo loaderror
sql = "select * from 值班管理"
rs_zhiban.CursorLocation = adUseClient
rs_zhiban.Open sql, conn, adOpenKeyset, adLockPessimistic ' 打开数据库
' 设定DataGrid控件属性
DataGrid1.AllowAddNew = False ' 不可增加
DataGrid1.AllowDelete = False ' 不可删除
DataGrid1.AllowUpdate = False
Set DataGrid1.DataSource = rs_zhiban
Exit Sub
loaderror:
MsgBox Err.Description
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set DataGrid1.DataSource = Nothing
rs_zhiban.Close
End Sub
(8) 投诉管理子窗体代码
投诉管理子窗体是为了对人员进行更好的管理而设置的,可以向其添加投诉的对象、时间和内容等。投诉管理运行后的子窗体如图45所示。

图45 运行的投诉管理子窗体
以下为窗体的代码:
Private Sub Command1_Click()
On Error GoTo adderr
Text1.SetFocus
Adodc1.Recordset.AddNew
Exit Sub
adderr:
MsgBox Err.Description
End Sub
Private Sub Command2_Click()
On Error GoTo deleteerr
With Adodc1.Recordset
If Not .EOF And Not .BOF Then
If MsgBox("删除当前记录吗?", vbYesNo + vbQuestion) = vbYes Then
.Delete
.MoveNext
If .EOF Then .MoveLast
End If
End If
End With
Exit Sub
deleteerr:
MsgBox Err.Description
End Sub
Private Sub Command3_Click()
Adodc1.Recordset.MovePrevious
If Adodc1.Recordset.BOF Then
MsgBox "这是第一条记录", vbOKCancel + vbQuestion
Adodc1.Recordset.MoveFirst
End If
End Sub
Private Sub Command4_Click()
Adodc1.Recordset.MoveNext
If Adodc1.Recordset.EOF Then
MsgBox "这是最后一条记录", vbOKCancel + vbQuestion
Adodc1.Recordset.MoveLast
End If
End Sub
Private Sub Command5_Click()
If Adodc1.Recordset.EOF Then
MsgBox "记录空", vbOKCancel + vbQuestion
End
Else
Adodc1.Recordset.MoveFirst
End If
Exit Sub
End Sub
Private Sub Command6_Click()
If Adodc1.Recordset.RecordCount = 0 Then
MsgBox "空记录", vbOKCancel + vbQuestion
End
Else
Adodc1.Recordset.MoveLast
End If
End Sub
Private Sub Command7_Click()
MDIForm1.Show
frmtousu.Hide
End Sub
到这里,各个窗体的界面和代码都介绍完了。发布后可以作为一个实际的项目应用。
查看本文来源