VBA学习笔记60-1: Treeview控件

VBA学习笔记60-1: Treeview控件

学习资源:《Excel VBA从入门到进阶》第60集 by兰色幻想


本节讲Treeview控件。

*来自评论区的温馨提示:treeview也有32位和64位的兼容问题,如果无法使用,要先检查下office是多少位的。


TreeView控件是以树形结构显示数据的控件。利用TreeView控件,可以设计出树形结构图,便于用户选择不同的项目。

总公司人事结构是一级节点,公司一、公司二、公司三是二级节点,部门是三级节点,人员是四级节点

首先需要把treeview控件添加到工具箱,依旧在工具箱,右键附加控件,找到Microsoft TreeView Control,确定,就可以在工具箱找到它了。


一、数据导入

treeview是由节点构成的,第一个节点叫顶级节点,其余的是子节点。

例:把以下公司结构表做成Treeview。

可以看到已经把各级别标记为不同颜色,代码也是递进有层次感的,可以单从员工的代码看出他所属的公司和部门。下面以一个结构图展示节点分布:

代码思路讲解:

  1. treeview控件添加节点的ADD方法:
Treeview1.Nodes.Add(上一级节点的索引值,是否为子节点,节点的索引值,节点上显示的文字,图标的索引号,选取节点时的图标)
TreeView1.Nodes.Add(relative, relationship, key, text, image, selectedimage)

注意:

① 节点对象:Nodes

② 如果一级节点的索引值和创建节点的位置为空的话,则表示创建是的顶级节点。

③ 节点的索引值不能是纯数字。

④ 子节点的表示:tvwChild。

⑤ 节点的图片索引,选填。

⑥ 选取节点时显示的图片索引,选填。


套到例子里,写创建顶级节点的语句:

Set Nodx = TreeView1.Nodes.Add(, , "总公司", "总公司人事结构", 1) 

①上一级节点的索引值:因为是顶级节点,所以没有上一级节点的索引值,略过不填

②是否为子节点:顶级节点不是子节点,略过不填(不填内容也要写逗号啊)

③节点的索引值:设置为"总公司"

④节点上显示的文字:"总公司人事结构"

⑤选取节点时的图标:1(上节内容imagelist,因为有图标,所以记得也要在窗体插入imagelist控件)。

**假设不设置选取节点时的图标,代码可写为:

Set Nodx = TreeView1.Nodes.Add(, , "总公司", "总公司人事结构") 

最后的逗号可不写,因为这项参数是可选的。


写创建子节点(公司一)的语句:

Set Nodx = TreeView1.Nodes.Add("总公司", tvwChild, "A" & C2, C1 & "(" & C2 & ")", 2)

①上一级节点的索引值:“总公司”。

②是否为子节点:是,所以填tvwChild。

③节点的索引值:因为不能是纯数字,为方便记忆,把表格中的代码赋值给C2,写成 "A" & C2。以公司一为例,那么它的索引值就是“A1”。

④节点上显示的文字:C1 & "(" & C2 & ")",把表格中的级别赋值给C1。以公司一为例,那么它将会显示为“公司一(1)”。

⑤选取节点时的图标:2(imagelist控件的序号2图片)。


2. 代码逻辑

①要显示图标,所以先要配置好lmagelist控件。

②循环语句,循环获取级别和代码。

③判断语句,根据代码判断并生成对应级别的节点。


完整代码:

Private Sub UserForm_Initialize()

Dim Nodx As node

TreeView1.ImageList = ImageList1 '从imagelist控件中提取图片
Set Nodx = TreeView1.Nodes.Add(, , "总公司", "总公司人事结构", 1) '总公司是顶级节点的索引值,

For x = 2 To Range("B65536").End(xlUp).Row

    C1 = Cells(x, 1)
    C2 = Cells(x, 2)
    
    If Len(C2) = 1 Then '如果代码长度为1,说明是顶级节点下的二级节点
    
        Set Nodx = TreeView1.Nodes.Add("总公司", tvwChild, "A" & C2, C1 & "(" & C2 & ")", 2)
    
    ElseIf Len(C2) = 3 Then '如果代码长度为3,说明是三级节点
    
        Set Nodx = TreeView1.Nodes.Add("A" & Left(C2, 1), tvwChild, "A" & C2, C1 & "(" & C2 & ")", 3)
    
    ElseIf Len(Cells(x, 2)) = 6 Then '如果代码长度为6,说明是四级节点
    
        Set Nodx = TreeView1.Nodes.Add("A" & Left(C2, 3), tvwChild, "A" & C2, C1 & "(" & C2 & ")", 4)
    
    End If

Next

End Sub

运行演示:


二、数据读取

有数据导入,就有数据读取。如何让程序识别到我们点击了哪个节点呢?

还是接上例,想达到如下效果:

从图中可以看到,每点击一个节点,旁边的文本框都会显示它的信息。

代码思路讲解:

  1. 表示选取的节点
SelectedItem 正在选取的节点
SelectedItem.Key 正在选取节点的索引值

2. 节点包含的信息,第一个信息是它的索引值,刚刚除了顶级节点的索引值特别设置为“总公司”,其他索引值都是“A代码”,代码长度不一。第二个信息是它显示出来的内容text,除了顶级节点特别设置为“总公司人事结构”,其他都是“级别名(代码)”。

所以我们需要根据代码长度判断,它所在的级别,使用判断语句。

①如果代码长度为2,表明它是二级节点,公司名称就是节点的text(注意去除后面的“(代码)”,部门和姓名没有,代码是去除首字母的索引值。

②如果代码长度为4,表明它是三级节点,公司名称是它的上一节点的text,部门是当前节点的text,姓名没有,代码是去除首字母的索引值。

上一节点 Nodes.Parent

②如果代码长度为7,表明它是四级节点,公司名称是它的上上一节点的text,部门是上一节点的text,姓名当前节点的text,代码是去除首字母的索引值。

上上一节点 Nodes.Parent.Parent

3. 去除Text后面的“(代码)“内容,因为比较重复,写一个VBA自定义函数。代码和级别的长度不一,所以不能直接用Left,需要再加一个函数组合用,用字符查找函数InStr查找”(“的位置,用instr,算出left的截止位置。

Function 截取名称(AAA)
   截取名称 = Left(AAA, InStr(1, AAA, "(") - 1)
End Function


完整代码:

Private Sub TreeView1_Click()
Dim MyItem As node

Set MyItem = TreeView1.SelectedItem 'SelectedItem正在选取的节点

If Len(MyItem.Key) = 2 Then 'SelectedItem.Key 正在选取节点的索引值
    TextBox1 = 截取名称(MyItem.Text) '如果是顶级节点,公司名称等于节点的显示内容(去掉代码)
    TextBox2.Value = ""
    TextBox3.Value = ""
    TextBox4 = Replace(MyItem.Key, "A", "") '替换掉A后的代码
ElseIf Len(MyItem.Key) = 4 Then
    TextBox1 = 截取名称(MyItem.Parent.Text) ' MyItem.Parent.Text上一级节点的显示文本
    TextBox2 = 截取名称(MyItem.Text)
    TextBox3.Value = ""
    TextBox4 = Replace(MyItem.Key, "A", "")
ElseIf Len(MyItem.Key) = 7 Then
    TextBox1 = 截取名称(MyItem.Parent.Parent.Text)
    TextBox2 = 截取名称(MyItem.Parent.Text)
    TextBox3 = 截取名称(MyItem.Text)
    TextBox4 = Replace(MyItem.Key, "A", "")
 End If

End Sub

编辑于 2021-07-29 15:52