VB+Access設計圖書管理系統
一、需求分析
在進行一個項目的設計之前,先要進行必要的需求分析。
現某圖書館需要管理其各種人員和圖書信息,希望實現辦公的信息化,通過建立一個圖書管理系統來管理圖書。其完成的功能如下:
(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 主窗體的屬性
Windowstate的值為Maxsize,即程序啟動之后自動最大化。
將“菜單”組件從“工具箱”拖到窗體上。創建一個 Text 屬性設置為“文件”的頂級菜單項,且帶有名為“關閉”的子菜單項。類似地創建一些菜單項,如表2所示。
表2 菜 單 項 表
主窗體如圖21所示。

圖21 主窗體
2、創建各子窗體
選擇“工程”→“添加窗體”命令,添加子窗體。
在新建Visual Basic工程時自帶的窗體中,將其屬性MIDChild改成True,則這個窗體成為MID窗體的子窗體。
在這個項目中,要創建的子窗體如表3所示。
表3 所有子窗體
下面分別給出這些子窗體,以及它們所使用的控件。
(1) 圖書登記子窗體如圖22所示,其控件如表4所示。

圖22 圖書登記子窗體
表4 圖書登記子窗體控件
圖書借閱和圖書賠償子窗體分別如圖23和圖24所示,因為它們的控件與圖書登記子窗體的雷同,在此不作介紹。

圖23 圖書借閱子窗體

圖24 圖書賠償子窗體
(2) 增加用戶子窗體如圖25所示,其控件如表5所示。

圖25 增加用戶子窗體
表5 增加用戶子窗體控件
(3) 修改密碼子窗體如圖26所示。

圖26 修改密碼子窗體
(4) 庫房管理子窗體如圖27所示。

圖27 庫房管理子窗體
其控件如表6所示。
表6 庫房管理子窗體控件
(5) 查詢子窗體如圖28所示,其控件如表7所示。

圖28 查詢子窗體
表7 查詢子窗體控件
(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
到這里,各個窗體的界面和代碼都介紹完了。發布后可以作為一個實際的項目應用。
在進行一個項目的設計之前,先要進行必要的需求分析。
現某圖書館需要管理其各種人員和圖書信息,希望實現辦公的信息化,通過建立一個圖書管理系統來管理圖書。其完成的功能如下:
(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
到這里,各個窗體的界面和代碼都介紹完了。發布后可以作為一個實際的項目應用。