VBA中ListView应用1(显示数据)
使用VBA做用户窗体的时候,ListView是经常需要用的一个控件。
做一个用多个ListView进行联动显示数据的小窗口
本文主要涉及:
- VBA 编写窗体程序
- MySQL 存放数据
- ListView 显示数据
本章需要完成的效果如下:
- 在ListView1中显示合同和项目的资料,每个合同对应一个项目
- 在ListView2中显示型号的资料,每个合同对应多个型号
- 在ListView3中显示负责人的资料,每个合同对应多个负责人
- 当在ListView1中使用鼠标左键或者上下移动的时候,在下方的文本框,ListView2和ListView3中的数据会跟着对应的合同编号进行变化
前期准备:
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表示列内容居中显示
For Each D In Dic_合同.keys
.ColumnHeaders.Add , , D, Dic_合同(D), 2 '最后一个2表示列内容居中显示
.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表示列内容居中显示
.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表示列内容居中显示
.View = lvwReport '报表视图
.HideSelection = False '当控件失去焦点时选择文本加亮显示
.FullRowSelect = True '选择整行
.Gridlines = True '显示网格线
.LabelEdit = lvwManual '不允许编辑第一列
End With
End Sub
因为有很多地方需要用到4个表的标题,所以将其定义成全局变量,然后在窗体出现时初始化内容,后续可以随时调用。
在初始化字典的时候,每个表的主键不需要添加进去。
在初始化ListView列的时候,就可以直接循环字典添加
5、编写
提取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)
For Each D In Dic_合同.keys
x = x + 1
Me.Controls(D) = .SubItems(x)
End With
End Sub
6、编写
获取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)
For Each D In Dic_合同.keys
x = x + 1
.SubItems(x) = rst.Fields(D)
rst.MoveNext
End With
conn.Close: Set conn = Nothing: Set rst = Nothing
End Sub
Dim data As New MySQL
链接类模块
conn.Open data.模拟数据
调用类模块中的代码,直接打开MySQL数据库
将查询到的rst子集使用循环写入ListView1中
ListView1的数据来自合同和项目表,在VBA中SQL语句看不太清晰,可以先使用Navicat将SQL语句写出来,然后在复制到VBA中
7、编写
获取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)
rst.MoveNext
End With
conn.Close: Set conn = Nothing: Set rst = Nothing
End Sub
8、编写
获取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)
rst.MoveNext
End With
conn.Close: Set conn = Nothing: Set rst = Nothing
End Sub
写完3个获取ListView数据过程后,发现ListView2和ListView3很相似,只有4处标红的地方不同,那么可以写成带有参数的过程来精简代码。
9、设置
ListView1单击事件
Private Sub ListView1_Click()
'ListView1单击事件
ListView2.ListItems.Clear
ListView3.ListItems.Clear
Call 提取ListView1数据
'调用过程
获取数据 "型号", ListView2, "型号编号", Dic_型号 'ListView2
获取数据 "业绩", ListView3, "负责人编号", Dic_业绩 'ListView3