【问题标题】:How to make cells into Command Buttons with VBA and Excel如何使用 VBA 和 Excel 将单元格制作成命令按钮
【发布时间】:2019-06-05 22:44:55
【问题描述】:

如何在不插入按钮、形状或其他 active-X 对象的情况下将电子表格单元格转换为按钮并执行 VBA 代码?

【问题讨论】:

  • @TimWilliams - 有趣的想法!参考包括解决翻转等问题的答案以及点击。使用翻转效果,正如最初在那里和其他地方提出的那样,为形状弹出窗口添加实用程序(作为帮助/评论)......以及其他答案/问题,以发现当不再悬停在单元格上时如何关闭弹出窗口。我还注意到,现在作为 UDF 执行的 vba/代码无法直接跟踪,因此这可能会给新手带来问题(您的链接中也建议了解决方法)

标签: excel vba button named-ranges


【解决方案1】:

使用@TimWilliams 的建议和引用的 URL,基于那里的读数,我提供了一些演示代码,这些代码在 Excel 2010 中适用于我:IfError 在早期版本中可能不起作用,我想知道它是否表现得很好在以后的版本中有所不同。

注意:此代码不能像使用普通 VBA 一样调试。这是因为它是在“电子表格端”执行的,作为用户定义的函数。

将公式放入单元格(此处为 A2):

  1. =IFERROR(HYPERLINK("#MyUDF()","CellText"),"Junk")
  2. “CellText”将显示在单元格 A2 中。
  3. "#...." 指向 UDF。结合代码中的Set 语句,它强制执行“单击”,并且仅在单击时执行一次,而不是在悬停和移动跨单元格时执行的可重复事件
  4. =IFERROR(HYPERLINK(...),...) 是#name 或其他错误的解决方法。在仅使用=HYPERLINK(....) 时可以看到。

将此代码放在模块中(维度和 UDF):

Dim j as integer

Function MyUDF() ' this is a user-defined-function
    'NOTE: can't be traced when executed, 
        'so this creates debugging issues
Set MyUDF = Selection
Range("a1") = j
j = j + 1
End Function

点击 A2 中的 URL 将增加 A1 中显示的值 - 每点击一次。

观察悬停效果:

  1. 注释掉“Set Statement”
  2. 删除 UDF 引用周围的引号和井号。该单元格现在将显示“asdf”而不是“Test”。
  3. 在 URL 上滚动,单元格 A1 将随着您移动/悬停而增加。

要让整个单元格执行 UDF(以及递增值),请为单元格打开自动换行。

请注意,当您在单元格中四处移动时,通过悬停,代码会经常执行。对我来说,如果我在单元格中停止移动,代码不会执行。

【讨论】:

    【解决方案2】:

    “将按钮放入单元格”的替代方法

    使用工作表事件选择要执行代码的单元格:Worksheet_SelectionChange

    将代码放在特定工作表的模块中,而不是 WorkBook 模块中。根据需要对单元格进行颜色/边框/文本;任何计算机或屏幕上的一个单元格就是一个单元格。当用户单击短标签/描述时,我使用它来引用加载到 userForm 中的帮助,从帮助工作表中查找。这适用于作为按钮的合并单元格。使用单元格/按钮可以避免 IT 对 Active-X 对象的投诉。

    需要考虑的事情,示例代码如下:

    1. Target.Address 返回绝对地址,使用“$”字符
    2. 在您的代码中使用Select Case,即使您只有一个单元格/按钮。这简化了稍后添加单元格/按钮的路径
    3. 考虑在电子表格中使用命名范围,并在代码中引用它们。这样,VBA 就不会关心您是否移动单元格/按钮
    4. 如果您已合并单元格并为其创建了命名范围,请记住电子表格中的命名范围仅指向左上角的单元格
      • 但是,合并区域的Target.Address 返回整个范围,而不仅仅是一个单元格。如果您的Select Case 指的是Target 左上角单元格的地址,则可以避免此问题。
      • 使用Target.Cells(1,1).Address
    5. 合并单元格的错误选择:不要使用MergeArea.AddressMergeArea 不适用于合并单元格[仅适用于单个单元格];它返回单元格所在的合并范围。

    *示例代码*

    'How to Make Cells into Buttons that execute code
    ' place code in the specific Worksheet module of interest
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
       ' in this example, I create named ranges on the spreadsheet '
                ' [complicated names, here, so you can read what's what]:
          ' one cell:  "Button_OneCellNameRange"
          ' one set of merged cells:  "Button_MergedCellNameRange"
             ' [the reference is the top-left cell, only]
    
       ' a VBA created cell/button location [not very useful for later sheet edits]
          Dim myVBACellButton As Range
          Set myVBACellButton = Range("B2")
    
             Debug.Print "Target Address: " & Target.Address
                   'merged cells will return a range: eg "$A$1:$D$3"
    
             Debug.Print "Target.Cells(1,1).Address: " & Target.Cells(1, 1).Address
                   'merged cells will return the top left cell, which would match
                      ' a named reference to a merged cell
    
       Select Case Target.Cells(1, 1).Address
            'if you have merged cells, you must use the ".cells(1,1).address"
            ' and not just Target.Address
    
          Case Is = "$A$1"
             MsgBox "Hello from: Click on A1"
             ' [execute a procedure/subroutine call, or more code, here...]
    
          Case Is = myVBACellButton.Address
             MsgBox "Hello from: Click on B2, a VBA referenced cell/button"
                ' "myCellButton" defined as range in VBA
    
          'using a range named on the spreadsheet itself ...
             ' named ranges allow one to move the cell/button freely,
             ' without VBA worries
          Case Range("Button_OneCellNameRange").Address
             MsgBox "Hello From: Button Click on Button_OneCellNameRange"
    
          Case Range("Button_MergedCellNamedRange").Address
             'note that the address for merged cells is ONE CELL, the top left
             MsgBox _
                "Hello from: Button_MergedCellNamedRange.Address: " _
                      & Range("Button_MergedCellNamedRange").Address _
    
          Case Else ' normally you wouldn't be using this, for buttons
             MsgBox "NOT BUTTONS"
    
       End Select
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 2014-01-18
      • 1970-01-01
      • 2022-08-11
      • 2012-03-23
      相关资源
      最近更新 更多