【问题标题】:VBA: How to address the correct workbook when giving a worksheet as an argument to a function?VBA:将工作表作为函数的参数时如何处理正确的工作簿?
【发布时间】:2017-11-22 19:30:46
【问题描述】:

我有一个关于 VBA 中工作簿的正确地址的问题,我对此很陌生。

这是我到目前为止所做的:
我写了一个子程序,除其他外,它创建了一个代号为“table10”的工作表。

然后我定义了一个函数来操作所述工作表的内容:这个函数

Text_To_Numbers(worksheet as worksheet)

需要一个工作表参数。我使用以下行从另一个子调用该函数:

Call Text_To_Numbers(table10)

现在,这是我的问题:
当唯一打开的工作簿是我想用我的函数操作的工作簿时,上述工作完美无缺。但是,当我有多个打开的工作簿时,该函数会尝试操作不同的工作簿,从而导致错误。

我很确定一定有一种方法可以指定要使用的工作簿,但我找不到它。话虽如此,还有一个复杂的问题:我要操作的工作簿的名称是机器生成的,所以它总是有不同的名称。这意味着不能一次又一次地使用对同一文件名的显式引用。

谁能帮我解决这个问题?

【问题讨论】:

  • ThisWorkbook 用于运行宏的工作簿,例如ThisWorkbook.table10ThisWorkbook.Worksheets("Table10"),或将Application.Workbooks("WorkBookName.xlsm").Worksheets("Table10") 用于任何其他工作簿。
  • 另外,您可以声明一个工作簿变量Dim wb as Workbook,然后使用它:Set wb = Workbooks.Open("Somepath\Somefile.xlsx") 打开一个,然后wb.Worksheets(1) 引用该工作簿中的第一个工作表。
  • 除非您设置了对其他工作簿项目的引用,否则table10 将始终使用代码引用工作簿中的工作表(如果它是代号)。

标签: vba excel


【解决方案1】:

您需要在 VBA 中完全限定对象,以避免出现这样的情况,即父对象是模糊的。

在您的情况下,您希望工作表连接到其父工作簿,因此请确保指定它来自给定工作簿!

您不能通过 CodeName 直接引用其他工作簿中的工作表,只能对 ThisWorkbook 对象(包含 VBA 代码的工作簿)执行此操作。请参阅问题Fully reference a worksheet by codename 以获取有关如何从另一个工作簿通过其代号获取工作表的详细信息。我已经在答案中包含了该函数以及如何在这种情况下使用它。

您通过以下方式之一创建了工作表 table10

  • ActiveWorkbook
  • 本工作簿
  • WB(一些工作簿对象)

因此,您无需名称即可使用该工作簿对象访问它!


使用ThisWorkbook.table10 应该与table10 给出相同的行为,但这里有两个更简洁的调用函数的示例。

' A neater way to call the function:
Text_To_Numbers worksheet:=ThisWorkbook.table10
' You could also call it simply using
Text_To_Numbers ThisWorkbook.table10


如果您的工作表不在ThisWorkbook

' Get sheet (from the workbook object you are using, WB) and pass to your Text_To_Numbers 
Text_To_Numbers GetSheetWithCodename("table10", WB)

Function GetSheetWithCodename(ByVal worksheetCodename As String, Optional wb As Workbook) As Worksheet
    Dim iSheet As Long
    If wb Is Nothing Then Set wb = ThisWorkbook ' mimics the default behaviour
    For iSheet = 1 To wb.Worksheets.Count
        If wb.Worksheets(iSheet).CodeName = worksheetCodename Then
            Set GetSheetWithCodename = wb.Worksheets(iSheet)
            Exit Function
        End If
    Next iSheet
End Function

【讨论】:

    【解决方案2】:

    尝试将工作簿和工作表分配给一个变量,然后当您需要在其中做一些工作时以这种方式调用它:

    Dim WB As Workbook
    
    Dim WS As Worksheet
    
    'If you want to open the workbook before doing work
    Set WB = Workbooks.Open("/Workbook path name goes here”)
    
    Set WS = WB.Worksheets("Table‌​10")
    

    那么你只需要在你的函数中传递一个对 WS 变量的调用,就可以在指定的工作表中执行操作。

    编辑:

    抱歉,当我第一次阅读您的问题时,没有意识到您正在尝试在项目编辑器中引用索引名称。代号可以从外部工作簿中引用,下面的示例展示了如何选择工作簿和工作表代号以执行从一个工作簿复制/粘贴到另一个工作簿:

    Sub UseCodeNameFromOutsideProject()
    Dim WS As Worksheet
    With Workbooks("MyWorkbook.xlsb")
        Set WS = _
            .Worksheets(CStr(.VBProject.VBComponents("Sheet1").Properties(7)))
            WS.Range("A1").Copy
            Selection.Copy
            WS.Range("B1").PasteSpecial
    End With
    End Sub
    

    感谢Enderland 的创意。

    【讨论】:

    • @data_beta 我几乎不建议你阅读VBA Best Practices: Avoid using SELECT or ACTIVATE
    • 嗯,我觉得您的整个答案可以替换为评论“请参阅 this answer 以获取从另一个工作簿按代号访问工作表的稍微笨拙的方法”。但是,是的,现在这是一个稍微多一点的主题答案!
    • 您确定Dim WS As Worksheet in WB 有效吗?以前从未见过in WB 的语法。至少在 MS Excel 2016 中这是行不通的。
    • @Wolfie 即使引用的链接是针对 Visual Studio 6 而不是 VBA ;) 我也很确定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 2021-11-26
    相关资源
    最近更新 更多