【问题标题】:Excel VBA Selecting Original WorkbookExcel VBA选择原始工作簿
【发布时间】:2019-01-29 01:25:12
【问题描述】:

我正在编写一个 Excel VBA 脚本,该脚本要求我将原始 excel 工作簿中的不同细节有序地复制并粘贴到 5 个新的 excel 工作簿中。另外,我将宏添加到加载项中,以便可以将其添加到另一台计算机中。我唯一的问题是我无法引用原始工作簿,因为:

1) 原始工作簿的文件名将始终更改,因此我无法根据其名称提取工作簿/将工作簿名称分配给变量。

2) Excel VBA 具有 ActiveWorkbook/ThisWorkbook 属性,但它没有 ActiveWorkbook 属性将始终更改,具体取决于当前处于活动状态的工作簿。话虽如此,ActiveWorkbook 对我不起作用,因为创建新工作簿将覆盖原始工作簿。 ThisWorkbook 属性对我不起作用,因为 VBA 代码将存储在加载项中,但我想将新文件保存在原始工作簿的位置(这是当我使用 ThisWorkbook.Path 来标识位置时)。

有谁知道我是否可以让 Excel VBA 读取原始文件的位置并将该值锁定到一个变量中,这样当我需要再次引用它时,我总是可以再次调用它?

以下是我拥有的示例代码。任何帮助将不胜感激。谢谢!

Option Explicit

Sub new()

    Dim createWb As Workbook
    Dim Originalwks As Worksheet
    Dim createWbName As String

    Set Originalwks = ActiveWorkbook.ActiveSheet

    createWbName = Left(ActiveWorkbook.Name, Len(ActiveWorkbook.Name) - 4)
    Set createWb = Workbooks.Add
    createWb.SaveAs Filename:=ThisWorkbook.Path & Application.PathSeparator & createWbName
    createWb.Sheets("Sheet1").Name = createWbName

    Originalwks.UsedRange.Copy
    createWb.Worksheets(createWbName).Range("A1").PasteSpecial xlValues

    'I will still be adding new workbooks by copying values from the original workbook. 
    'But how do I pull out the original workbook again? 

    createWb.Close SaveChanges:=True

End Sub

【问题讨论】:

  • 如果OriginalwksActiveWorkbook 中的Activesheet,那么你不能只做Dim OriginalWb as WorkbookSet OriginalWb = ActiveWorkbook 吗?
  • 这意味着如果我在我的新工作簿上,ActiveWorkbook 将更改为新工作簿。如何调用 VBA 重新拉出原来的工作簿?
  • 你会有一个变量OriginalWb - 引用它。尽管ActiveWorkbook 会发生变化,但该变量将始终引用同一个工作簿——第一个处于活动状态的工作簿。 OriginalWks 的工作方式相同 - 即使 ActiveSheet 发生变化,您也可以引用第一个活动工作表。
  • ThisWorkbook 始终指的是运行 VBA 代码的工作簿。如果那是 Excel 加载项,则 ThisWorkbook 是该 Excel 加载项的隐藏工作簿。
  • 就我个人而言,我尽量避免使用 ActiveWorkbook,因为它可能会在意想不到的时候发生变化。 Excel 中有几个函数可以动态创建新的工作簿,这些工作簿成为 ActiveWorkbook,使用 ActiveWorkbook 可能会混淆您真正使用的是哪个工作簿。使用变量来保存您正在访问的工作簿,以便您知道自己拥有正确的工作簿。

标签: vba excel


【解决方案1】:

您对如何使用ActiveWorkbookThisWorkbook 对象感到困惑。最好的方法是始终控制您在流程中处理的所有元素,在这种情况下,您有一个作为原始工作簿的工作簿,并且您希望稍后在例程中使用它的数据和路径。无论您是从加载项还是从原始工作簿本身,甚至从另一个工作簿运行您的例程,都没有关系。您的原始工作簿有一个路径,您可以在代码中动态或硬编码定义它。所以这里有一些你可以使用的选项:

如果原始工作簿已打开且处于活动状态,则执行此操作以始终引用它并检索其路径:

Dim WB_Orig As Workbook
Set WB_Orig = ActiveWorkbook

如果 activeworkbook 发生变化,它不会导致问题。此外,无论从加载项还是原始工作簿本身运行代码,activewokbook 都将是那个(您在屏幕上看到的那个),如果您从加载项运行它ThisWorkbook 将引用添加-in 工作簿,而不是您原来的工作簿。

如果您从加载项运行代码,我会尝试找到原始工作簿并像这样打开它并同时将其设置为对象:

Set WB_Orig = Application.Workbooks.Open("filename") 'filename is the path to your original workbook

此外,工作簿可能已打开,因此最好在尝试打开之前检查所有打开的工作簿名称。您可以遍历打开的工作簿并检查它们的名称,如果有匹配项,只需将其分配为 WB_Orig

Function GetOriginalWorkbook(sFilename As String)
    Dim WB As Workbook
    For Each WB In Application.Workbooks
        If WB.Name = sFilename Then
            Set GetOriginalWorkbook = WB
            Exit For
        End If
    Next
End Function

在您的 sub 中使用上述功能,您可以轻松做到:

Set WB_Orig = GetOriginalWorkbook("Book1") 'you need to change Book1 with the name of your origianl workbook.

如果原始工作簿已打开,那么您将其作为已分配给WB_Orig 的对象,否则它将为Nothing,您应该打开它:

Set WB_Orig = GetOriginalWorkbook("Book1")

if WB_Orig is Nothing then
     Set WB_Orig = Application.Workbooks.Open("filename")
end if

另一个技巧是在尝试打开原始工作簿之前将on error 设置为resume next,然后将其设置回goto 0。这样,如果原来的工作簿没有打开,Excel会打开它,如果它打开了,应该会抛出一个错误,但是由于你告诉excel忽略它,它会继续执行代码,你应该没问题。使用on error resume next 很棘手,作为一种好的做法,您应该始终尝试预见和控制错误,而不是忽略它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    相关资源
    最近更新 更多