ET疑难千寻千解丛书之EXCEL2010编程与实践 罗刚君 章兰新 黄朝阳 编著
疑难36
如何引用数据表创建多级下拉菜单 数据有效性可以实现下拉菜单,但只能一级。那么可以实现二级菜单吗?例如利用图所示的数据 产生如图所示的二级菜单,当单击单元格时,产生二级菜单;选择第二级菜单时可以在单元格分别产生部门和姓名,即同时输入一级和二级菜单的字符。
è解决方案
数据有效性功能无法修改,但可以通过自定义二级菜单的方式来处理。ShowPopup方法可以将二级菜单显示在活动单元格处,从而打造出类似于数据有效性下拉列表的二级菜单。最后利用ActionControl属性获取用户所单击的菜单字符,并导入到单元格中。 简单而言,就是利用工作簿事件SheetSelectionChange,在选择指定的单元格时利用CommandBars.Add创建一级和二级菜单,而当用户选择菜单时,将菜单的文字标题导入到单元格中。 í操作方法 步骤1
按【Alt+F11】组合键打开VBE窗口。 步骤2
选择菜单“插入”→“模块”,并输入以下代码:
- Sub 选项() '用于指定哪个区域可以产生二级菜单
- Dim i As String, adds As String, sht As Worksheet
- '确认是否存在“数据”工作表
- On Error Resume Next
- Set sht = Sheets("数据")
- If err.Number <> 0 Then MsgBox "请建立一个名为“数据”的工作表,用于存放菜单
- 所需要的数据", , "确认数据表": GoTo err
- err.Clear
- On Error GoTo err
- '如果选择的是单元格,那么将选区地址赋予变量adds,否则将“B:B”赋予变量
- If TypeName(Selection) = "Range" Then adds = Selection.Address(0, 0) Else
- adds = "B:B"
- i = Application.InputBox("你想控制哪一个区域" & vbCrLf & "如果想关闭本功能,
- 单击取消按钮即可。", "请选择区域", adds, , , , , 8).Address(0, 0)
- SaveSetting "MyApp", "only", "only", i '将用户选择的单元格地址存入注册表
- Exit Sub '退出程序
- err:
- SaveSetting "MyApp", "only", "only", "" '在注册表中写入一个空字符
- End Sub
- 以上过程用于让用户指定在哪个区域产生二级菜单,可以利用【Ctrl】键多选。而用户选择的区域地址将会存储在注册表中。
- 步骤3 如果VBE编辑器左边没有对象浏览器,那么选择菜单“视图”→“对象浏览器”调出对象浏览器窗口。然后双击“ThisWorkbook”进入代码窗口,并输入以下工作簿级别事件过程代码:
- Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
- If GetSetting("MyApp", "only", "only", "") = "" Then Exit Sub
- '如果注册表中没有值则退出
- If Target.Count > 1 Then Exit Sub '如果选择区域则退出
- On Error Resume Next
- Dim sht As Worksheet
- Set sht = Sheets("数据") '将数据表赋予变量sht
- If err <> 0 Then err.Clear: Exit Sub
- '如果有错误(即没有“数据”工作表)那么退出
- If sht.Range("a1") = "" Then MsgBox "请在数据表中输入数据,必须从A1开始,数
- 据区不要留空", vbOKOnly, "提示": Exit Sub
- Dim a As Range
- '判断注册表中记录的单元格与活动单元格是否重叠
- Set a = Intersect(Range(GetSetting("MyApp", "only", "only", "")),
- ActiveCell)
- If a Is Nothing Then Exit Sub '如果不在指定区域则退出
- Dim i, j, addss As String
- With Application.CommandBars.Add("临时菜单", msoBarPopup, , 1)
- '创建一个快捷菜单
- With .Controls.Add(Type:=msoControlButton) '添加一个子菜单
- .Caption = "请选择" '指定显示标题
- .FaceId = 136 '指定图标
- End With
- For i = 1 To sht.Cells(1, Columns.Count).End(xlToLeft).Column
- '创建一级菜单
- If WorksheetFunction.CountA(sht.Rows(2)) = 0 Then
- '如果第二行为空则只创建一级菜单
- With .Controls.Add(Type:=msoControlButton) '开始创建一级菜单
- .Caption = sht.Cells(1, i).Text '菜单显示的标题
- .Style = msoButtonIconAndCaption '同时显示文本和图标
- .FaceId = 70 + i '指定图文件
- .OnAction = "输入" '指定菜单对应的宏名
- End With
- Else '第二行非空则创建二级菜单
- With .Controls.Add(msoControlPopup, 1, , , 1) '开如创建二级菜单
- .BeginGroup = True '全部产生一条横线分隔开
- .Caption = sht.Cells(1, i).Text '指定二级菜单标题
- For j = 2 To sht.Cells(Rows.Count, i).End(xlUp).Row
- If sht.Cells(j, i) = "" Then GoTo AA '如果为空则不创建子菜单
- Set oCtrl = .Controls.Add(Type:=msoControlButton) '创建子菜单
- With oCtrl '对子菜单指定标题、宏名和图标
- .Caption = sht.Cells(j, i)
- .OnAction = "输入"
- .FaceId = 69 + j
- End With
- AA:
- Next
- End With
- End If
- Next
- .ShowPopup '显示工具栏
- End With
- Application.CommandBars("临时菜单").Delete '删除工具栏
- End Sub
复制代码 |