使用VBA做用戶窗體的時候,ListView是經常需要用的一個控制項。
做一個用多個ListView進行聯動顯示數據的小窗口
本文主要涉及:
本章需要完成的效果如下:
1、在資料庫中準備4張數據表
2、配置好VBA鏈接MySQL的設置,具體方法請參考之前寫的一篇文章
3、在VBA插入用戶窗體,模塊,類模塊,並在工具箱中先勾選出ListView控制項
1、在類模塊中寫入鏈接MySQL語句
Driver 你的ODBC版本 Server MySQL所在的IP地址 Port 埠號 DB 訪問的資料庫名稱 Uid 訪問的用戶名 Pwd 訪問的密碼 Property Get 模擬數據() 模擬數據 = "Driver={MySQL ODBC 8.0 Unicode Driver};" & _ "Server= ;Port=3308;DB=模擬數據;" & _ "Uid= ;Pwd= ;OPTION=3;" End Property
2、在模塊中寫入幾個全局變數,
3、設計用戶窗體樣式,這裡需要注意,TextBox的名稱修改成和前面Lable的內容一致,並且也要與資料庫中項目和合同表的欄位名相同(統一的格式,便於循環)
項目
合同
4、雙擊窗體,開始編寫代碼,在用戶窗體出現的時候我們需要初始化一些信息,使用UserForm_Initialize事件
Private Sub UserForm_Initialize() 初始化合Dic_項目字典,Key是標題名稱,Item是列寬 Set Dic_項目 = CreateObject("Scripting.Dictionary") With Dic_項目 .Add "項目名稱", 100 .Add "項目所在省份", 60 .Add "項目所在城市", 60 .Add "項目所在區域", 80 End With
初始化合Dic_合同字典,Key是標題名稱,Item是列寬 Set Dic_合同 = CreateObject("Scripting.Dictionary") With Dic_合同 .Add "項目編號", 60 .Add "評審日期", 120 .Add "合同評審人", 55 .Add "賣方公司", 100 .Add "銷售方式", 45 .Add "付款方式", 45 End With
初始化合Dic_型號字典,Key是標題名稱,Item是列寬 Set Dic_型號 = CreateObject("Scripting.Dictionary") With Dic_型號 .Add "項目編號", 60 .Add "合同編號", 45 .Add "產品名稱", 100 .Add "產品子分類", 60 .Add "產品分類", 60 .Add "產品銷售額", 55 End With
初始化合Dic_業績字典,Key是標題名稱,Item是列寬 Set Dic_業績 = CreateObject("Scripting.Dictionary") With Dic_業績 .Add "項目編號", 60 .Add "合同編號", 45 .Add "銷售部門", 45 .Add "辦事處", 80 .Add "項目負責人", 55 End With
初始化ListView1 With ListView1 .ColumnHeaders.Add , , "合同編號", 45 For Each D In Dic_項目.keys .ColumnHeaders.Add , , D, Dic_項目(D), 2 最後一個2表示列內容居中顯示 Next For Each D In Dic_合同.keys .ColumnHeaders.Add , , D, Dic_合同(D), 2 最後一個2表示列內容居中顯示 Next .View = lvwReport 報表視圖 .HideSelection = False 當控制項失去焦點時選擇文本加亮顯示 .FullRowSelect = True 選擇整行 .Gridlines = True 顯示網格線 .LabelEdit = lvwManual 不允許編輯第一列 End With 獲取ListView1數據
初始化ListView2 With ListView2 .ColumnHeaders.Add , , "型號編號", 45 For Each D In Dic_型號.keys .ColumnHeaders.Add , , D, Dic_型號(D), 2 最後一個2表示列內容居中顯示 Next .View = lvwReport 報表視圖 .HideSelection = False 當控制項失去焦點時選擇文本加亮顯示 .FullRowSelect = True 選擇整行 .Gridlines = True 顯示網格線 .LabelEdit = lvwManual 不允許編輯第一列 End With
初始化ListView3 With ListView3 .ColumnHeaders.Add , , "負責人編號", 55 For Each D In Dic_業績.keys .ColumnHeaders.Add , , D, Dic_業績(D), 2 最後一個2表示列內容居中顯示 Next .View = lvwReport 報表視圖 .HideSelection = False 當控制項失去焦點時選擇文本加亮顯示 .FullRowSelect = True 選擇整行 .Gridlines = True 顯示網格線 .LabelEdit = lvwManual 不允許編輯第一列 End With End Sub
因為有很多地方需要用到4個表的標題,所以將其定義成全局變數,然後在窗體出現時初始化內容,後續可以隨時調用。
在初始化字典的時候,每個表的主鍵不需要添加進去。
在初始化ListView列的時候,就可以直接循環字典添加
5、編寫提取ListView1數據過程
提取ListView1數據
Sub 提取ListView1數據() 當選中ListView1某一行時,將選中的行內容顯示在文本框 With ListView1.SelectedItem Me.Controls("合同編號") = .Text x = 0 For Each D In Dic_項目.keys x = x + 1 Me.Controls(D) = .SubItems(x) Next For Each D In Dic_合同.keys x = x + 1 Me.Controls(D) = .SubItems(x) Next End With End Sub
6、編寫獲取ListView1數據過程
獲取ListView1數據
Sub 獲取ListView1數據() 從資料庫獲取ListView1的數據 Dim conn As New ADODB.Connection Dim rst As New ADODB.Recordset Dim data As New MySQL Dim sql$ conn.Open data.模擬數據 sql = "SELECT 合同.*,項目.項目名稱,項目.項目所在省份,項目.項目所在城市,項目.項目所在區域 " sql = sql & "FROM 合同 LEFT JOIN 項目 ON 合同.項目編號 = 項目.項目編號" rst.Open sql, conn 將rst子集循環到ListView1 Do While Not rst.EOF With ListView1.ListItems.Add .Text = rst.Fields("合同編號") x = 0 此處的循環順序要和初始化的時候一致,先項目,在合同 For Each D In Dic_項目.keys x = x + 1 .SubItems(x) = rst.Fields(D) Next For Each D In Dic_合同.keys x = x + 1 .SubItems(x) = rst.Fields(D) Next rst.MoveNext End With Loop conn.Close: Set conn = Nothing: Set rst = Nothing End Sub
Dim data As New MySQL 鏈接類模塊
Dim data As New MySQL
conn.Open data.模擬數據 調用類模塊中的代碼,直接打開MySQL資料庫
conn.Open data.模擬數據
將查詢到的rst子集使用循環寫入ListView1中
ListView1的數據來自合同和項目表,在VBA中SQL語句看不太清晰,可以先使用Navicat將SQL語句寫出來,然後在複製到VBA中
7、編寫獲取ListView2數據過程
獲取ListView2數據
Sub 獲取ListView2數據() 當選中ListView1某一行時,從資料庫獲取ListView2的數據 Dim conn As New ADODB.Connection Dim rst As New ADODB.Recordset Dim data As New MySQL conn.Open data.模擬數據 rst.Open "SELECT * FROM 型號 WHERE 合同編號 = " & ListView1.SelectedItem.Text & "", conn Do While Not rst.EOF With ListView2.ListItems.Add .Text = rst.Fields("型號編號") x = 0 On Error Resume Next For Each D In Dic_型號.keys x = x + 1 .SubItems(x) = rst.Fields(D) Next rst.MoveNext End With Loop conn.Close: Set conn = Nothing: Set rst = Nothing End Sub
8、編寫獲取ListView3數據過程
獲取ListView3數據
Sub 獲取ListView3數據() 當選中ListView1某一行時,從資料庫獲取ListView3的數據 Dim conn As New ADODB.Connection Dim rst As New ADODB.Recordset Dim data As New MySQL conn.Open data.模擬數據 rst.Open "SELECT * FROM 業績 WHERE 合同編號 = " & ListView1.SelectedItem.Text & "", conn Do While Not rst.EOF With ListView3.ListItems.Add .Text = rst.Fields("負責人編號") x = 0 On Error Resume Next For Each D In Dic_業績.keys x = x + 1 .SubItems(x) = rst.Fields(D) Next rst.MoveNext End With Loop conn.Close: Set conn = Nothing: Set rst = Nothing End Sub
寫完3個獲取ListView數據過程後,發現ListView2和ListView3很相似,只有4處標紅的地方不同,那麼可以寫成帶有參數的過程來精簡代碼。
9、設置ListView1單擊事件
ListView1單擊事件
Private Sub ListView1_Click() ListView1單擊事件 ListView2.ListItems.Clear ListView3.ListItems.Clear Call 提取ListView1數據 調用過程 獲取數據 "型號", ListView2, "型號編號", Dic_型號 ListView2 獲取數據 "業績", ListView3, "負責人編號", Dic_業績 ListView3 End Sub
10、設置ListView1按鍵事件
ListView1按鍵事件
Private Sub ListView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer) ListView1按鍵事件 38和40表示方向鍵上和下 If KeyCode = 38 Or KeyCode = 40 Then ListView1_Click End If End Sub
加一個判斷,當用戶按方向鍵上下的時候,執行單擊事件的效果
至此編寫完所有代碼,一個簡易的窗體顯示系統完成。總共173行代碼,還是比較少的了
在實際運用中可能表的欄位比較多,那麼只需要在初始化字典的時候添加進去就OK,
要注意的就是MySQL數據中的欄位名,字典,還有用戶窗體中的TextBox名稱要一致,不然循環會出錯。
後續在這個系統上添加對資料庫進行增刪改的功能,未完待續......