如何在一个Excel工作簿中从另一个工作簿调用特定工作表的宏?

8

我想调用另一个工作簿中特定工作表的Excel宏。Microsoft文档和网络搜索提供的语法只允许按工作簿访问宏,无法使用特定工作表的宏。该语法为:

Application.Run ("testworkbook.xls!macroname")

我需要做的是在其中引用一个工作表,类似于以下内容:

我需要做的是在其中引用一个工作表,类似于:

Application.Run ("testworkbook.xls!Sheet1.macroname")

我尝试了这个和许多其他变化,包括在其中使用单引号或双引号,但我始终收到消息说找不到宏。
编辑:通过所有线索和大量测试,我找到了答案。您可以访问特定于工作表的子程序,但必须使用规范名称,如“Sheet1”,不能使用实际的工作表名称。显然,其他工作簿无法访问该信息。
因此,上面的格式有效,只要您不尝试使用工作表名称(并且您可能需要将工作簿名称用单引号引起来(通过将CHR(39)连接到任一端)。

@Lance Roberts:下面的回答是否解答了您的问题? - Todd Main
@Otaku,是的,尽管我最终只使用了规范的工作表名称。但我喜欢你提供的所有信息,所以我会接受你的答案(我已经点赞了)。 - Lance Roberts
好的,我不确定非英语用户界面是否具有相同的规范表名称 - 如果这是您需要处理的内容 - 但对于这些目的来说,这是快速简单的。感谢接受/点赞。 - Todd Main
@Otaku,是的,我有点滥用“规范”的词语,可能有更好的术语,只是我这么想而已。 - Lance Roberts
4个回答

12

我知道你已经想通了,也许是经过了很多挣扎和喝咖啡,但我想要:

  • 给你更多关于为什么这样的细节
  • 提供一种您可以使用的方式 获取您工作表的名称。

首先,您想要的工作表名称并不是代码模块名称。因此,在VBE中,您看到代码模块的名称为“Sheet1”,但它可能具有不同的属性 Name,例如“MySheet1”(或可能相同)。

要通过名称获取它,您需要做一些循环,更改安全设置等。如果这是您想要的(由于安全设置问题,这在较小的环境中效果很好),则以下是一个示例:

  1. 更改安全设置以信任对VBA项目的编程访问。在Excel 2007中,转到“球形”|“Excel选项”|“信任中心”|“信任中心设置”|“宏设置”,然后启用“信任访问VBA项目模型”
  2. 创建一个带有一个工作表的工作簿。将其命名为“MySheet1”。打开VBE(Alt + F11)并在“ Sheet1(MySheet1)”中创建一个子例程,将其命名为TimesTen 并在代码中只是输入Debug.Print 10 * 10。像这样:

    Sub TimesTen()
        Debug.Print 10 * 10
    End Sub
    
  3. 将文件保存为宏启用的文档,并将其命名为“MacroXSLX.xlsm”,并保持打开。

  4. 打开一个新的Excel文档,转到其VBE,并在任何位置创建一个名为Test的子程序。在该代码主体中放入以下内容: 。

  5. Sub test()
    Dim SheetName As String
    SheetName = "MySheet1"
    Dim wb As Workbook
    Set wb = Workbooks("MacroXSLX.xlsm")
    For Each VBComp In wb.VBProject.VBComponents
        If VBComp.Properties.Item("Name").Value = SheetName Then
            Application.Run (wb.Name & "!" & VBComp.Name & ".TimesTen")
        End If
    Next
    End Sub
    
  6. 按下 F5 运行 test,在立即窗口中应该看到 100

可以看到 #4 中的代码正在循环遍历所有组件(模块、类等),寻找具有值为 MySheet1Name 属性的一个。一旦找到它,就可以获取该组件的名称,本例中为 Sheet1,然后使用它来构造字符串,在 MacroXSLX.xlsm 中运行该工作表的宏。代码可以进一步清理,以便在找到所需项时退出 For 语句等。

如上所述,唯一的真正缺点是安全设置和确保对 VBAProject 有程序化访问权 - 在一到十台计算机上很好,但如果必须始终正确设置更多计算机,则可能会很麻烦。


终于找到了一个解释,经过了两个小时的抓狂和喝咖啡。非常感谢! - Andrejs Gasilovs

1
您可以使用这个:

Run "'" & MySheet.Parent.name & "'!" & MySheet.CodeName & ".macroName"

1

你能否调整你的宏以接受一个工作表名称作为参数?这样当你在原始工作簿的工作表中调用它时,你可以直接使用MyMacro(me.name)进行调用。然后当你从其他工作簿中调用它时,你可以使用application.run("testworkbook.xls!MyMacro","sheetname")进行调用,其中"sheetname"是你的参数。

我不确定是否还有其他方法可以实现。


有多个具有相同按钮的工作表,并且它们都有相同的单击事件(因此每个工作表一个)。如果我无法做到这一点,我的计划是直接调用由这些宏调用的子例程(并将工作表名称作为参数插入其中)。我只是希望不必深入了解就能完成工作。 - Lance Roberts
仔细查看后,我意识到下游参数就是工作表本身,而你无法使用Run方法传递对象。 - Lance Roberts

1

VBA 项目是否有密码保护?此外,子程序是私有子程序吗?如果是,那么我认为宏将无法找到。


密码保护是仅限用户界面,因此不应阻止代码。子程序为公共。 - Lance Roberts
UserInterfaceOnly 只影响代码是否在受保护的工作表或工作簿上运行。VBA 项目受密码保护是不同的。但如果它是公共子程序,这不应该影响任何事情。如果 VBA 项目受保护,则无法从另一个模块调用私有子程序。 - guitarthrower

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接