学习资源:《Excel VBA从入门到进阶》第60集 by兰色幻想
本节讲Treeview控件。
TreeView控件是以树形结构显示数据的控件。利用TreeView控件,可以设计出树形结构图,便于用户选择不同的项目。
首先需要把treeview控件添加到工具箱,依旧在工具箱,右键附加控件,找到Microsoft TreeView Control,确定,就可以在工具箱找到它了。
一、数据导入
treeview是由节点构成的,第一个节点叫顶级节点,其余的是子节点。
例:把以下公司结构表做成Treeview。
可以看到已经把各级别标记为不同颜色,代码也是递进有层次感的,可以单从员工的代码看出他所属的公司和部门。下面以一个结构图展示节点分布:
代码思路讲解:
- treeview控件添加节点的ADD方法:
Treeview1.Nodes.Add(上一级节点的索引值,是否为子节点,节点的索引值,节点上显示的文字,图标的索引号,选取节点时的图标)
TreeView1.Nodes.Add(relative, relationship, key, text, image)
注意:
① 节点对象: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 nodeTreeView1.ImageList = ImageList1 '从imagelist控件中提取图片
Set Nodx = TreeView1.Nodes.Add(, , "总公司", "总公司人事结构", 1) '总公司是顶级节点的索引值,For x = 2 To Range("B65536").End(xlUp).RowC1 = 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 IfNextEnd Sub
运行演示:
二、数据读取
有数据导入,就有数据读取。如何让程序识别到我们点击了哪个节点呢?
还是接上例,想达到如下效果:
从图中可以看到,每点击一个节点,旁边的文本框都会显示它的信息。
代码思路讲解:
- 表示选取的节点
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 nodeSet 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 ThenTextBox1 = 截取名称(MyItem.Parent.Text) ' MyItem.Parent.Text上一级节点的显示文本TextBox2 = 截取名称(MyItem.Text)TextBox3.Value = ""TextBox4 = Replace(MyItem.Key, "A", "")
ElseIf Len(MyItem.Key) = 7 ThenTextBox1 = 截取名称(MyItem.Parent.Parent.Text)TextBox2 = 截取名称(MyItem.Parent.Text)TextBox3 = 截取名称(MyItem.Text)TextBox4 = Replace(MyItem.Key, "A", "")End IfEnd Sub