excel多级联动代码

'源数据按钮代码

'指向以下宏

Option Explicit
Dim Tree '目录树存储每个菜单

Sub main()    '根据数据表初始化弹出菜单
    Dim mybar As Object, arr, i&, j&, key$, myb, pkey$
    Dim N_col As Long '数据区宽度
    On Error Resume Next
    Set Tree = CreateObject("Scripting.Dictionary")    '目录树存储每个菜单
    Application.CommandBars("myCell").Delete    '重设菜单前删除原菜单
    Set mybar = Application.CommandBars.Add(Name:="myCell", position:=msoBarPopup)    '创建弹出式菜单
    Tree.Add "myCell", mybar
    arr = Range("源数据!a1").CurrentRegion.Value    '定位数据区,源数据放入数组arr
    '遍历行,单独写第一列先,避免在后面循环是判断第一个空值key
    N_col = UBound(arr, 2)
    ReDim Preserve arr(1 To UBound(arr, 1), 1 To N_col + 1)    '数组加空列做标识用
    For j = 2 To UBound(arr, 1)
        'xNode.key = arr(j, 1): xNode.text = arr(j, 1): xNode.parentKey = ""
        If Not Tree.exists(arr(j, 1)) Then
            If arr(j, 2) = "" Then    '第二列为空则直接写命令按钮
                AddControlButton "myCell", arr(j, 1), arr(j, 1), j, N_col
            Else    '有下级菜单则添加弹出节点
                AddControlPopup "myCell", arr(j, 1), arr(j, 1)
            End If
        End If
    Next
    '遍历第二列以后的以第一列为基准key
    'Exit Sub
    For i = 2 To UBound(arr)    '遍历数据源行
        key = arr(i, 1)    '关键字从第一列开始
        For j = 2 To N_col  '遍历2-N列
            If arr(i, j) <> "" Then    '空格跳过
                pkey = key    '父节点关键字
                key = key & "\" & arr(i, j) '本级关键字
                If arr(i, j + 1) = "" Then  '下一列为空则直接写命令按钮
                    AddControlButton pkey, key, arr(i, j), i, N_col
                Else    '有下级菜单则添加弹出节点
                    If Not Tree.exists(key) Then    '第一次菜单出现
                        AddControlPopup pkey, key, arr(i, j)
                    End If
                End If
            End If
        Next
    Next
    Set mybar = Nothing
End Sub
'添加菜单命令
Private Sub AddControlButton(ByVal pkey$, ByVal key$, ByVal caption$, ByVal i&, ByVal n&)
    Dim myb
    Set myb = Tree(pkey).Controls.Add(Type:=msoControlButton)
    With myb    '菜单加入触发按钮
        .caption = caption    '菜单按钮名称为x
        .OnAction = "'WriteToRng " & i & "," & n & "'" '最后一级选择触发事件,完成输入
        'Debug.Print "'WriteToRng " & i & "," & n & "'"
    End With
    Tree.Add key, myb
End Sub
'添加弹出菜单节点
Private Sub AddControlPopup(ByVal pkey$, ByVal key$, ByVal caption$)
    Dim myb
    Set myb = Tree(pkey).Controls.Add(Type:=msoControlPopup)
    myb.caption = caption    '菜单按钮名称
    Tree.Add key, myb '加入字典以供下级菜单索引节点用
End Sub
Public Sub WriteToRng(i, N_col)
    ActiveCell.EntireRow.Range("A1").Resize(1, N_col) = Sheets("源数据").Range("A" & i).Resize(1, N_col).Value
End Sub

 

Sub 代码执行时间()
  Dim tim1 As Date, tim2 As Date: tim1 = Timer

'---这中间请放置您要测试执行时间的代码---

   main
  tim2 = Timer
  MsgBox Format(tim2 - tim1, "程序执行时间为:0.00秒"), 64, "时间统计"
End Sub


Public Sub SubPopBar(keys() As Variant)
'根据参数数组返回子菜单,并复制到单独的弹出菜单
    Dim intI As Integer, subB
    Dim mybar As CommandBar
    Set subB = CommandBars("myCell")
    On Error Resume Next
    For intI = 0 To UBound(keys) '获得参数列表的子菜单
        If keys(intI) <> "" Then
            Set subB = subB.Controls(keys(intI))
            '上层是命令项
            If subB.Type = 1 Then Application.CommandBars("myCell").ShowPopup: Exit Sub
        Else
            Application.CommandBars("myCell").ShowPopup '如果前面几列输入的数据为空则直接弹出顶级菜单
            Exit Sub
        End If
    Next intI
    On Error Resume Next
    Application.CommandBars("myCellx").Delete '重设菜单前删除原菜单
    Set mybar = Application.CommandBars.Add(Name:="myCellx", position:=msoBarPopup) '创建弹出式菜单
    For intI = 1 To subB.Controls.Count
        subB.Controls(intI).Copy Bar:=mybar '从顶级菜单中摘出需要的子菜单
    Next
    'Set subB = Nothing
    'Set mybar = Nothing
    Application.CommandBars("myCellx").ShowPopup
End Sub

 

 

'--------------------------------------分割线-------------------------------------

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim a(), i '根据选择项摘取需要的子菜单
On Error Resume Next
If Target.Count = 1 And Target.Row > 1 Then
If Target.Column = 1 Then '若在第一级则直接使用全部菜单
With Application.CommandBars("myCell")
.ShowPopup
End With
ElseIf Target.Column <= Sheets("源数据").UsedRange.Columns.Count Then
ReDim a(0 To Target.Column - 2)
For i = 1 To Target.Column - 1
If Cells(Target.Row, i) <> "" Then
a(i - 1) = Cells(Target.Row, i)
Else
i = Target.Column
End If
Next
Call SubPopBar(a) '若在第N级则弹出N级子菜单
End If
End If
End Sub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值