打开工作簿,如果还没有打开,则打开;如果已经打开,则获取该引用。

4

我有一个场景需要在另一个工作簿路径中进行一些更改。但问题是我需要检查工作簿是否已经打开。如果没有,我需要将其打开并保存到一个工作簿变量中。

这里是我用于检查工作簿是否已经打开以及打开的代码:

Function IsFileOpen(fileFullName As String)
    Dim FileNumber As Integer
    Dim errorNum As Integer

    On Error Resume Next
    FileNumber = FreeFile()   ' Assign a free file number.
    ' Attempt to open the file and lock it.
    Open fileFullName For Input Lock Read As #FileNumber
    Close FileNumber       ' Close the file.
    errorNum = Err         ' Assign the Error Number which occured
    On Error GoTo 0        ' Turn error checking on.
    ' Now Check and see which error occurred and based
    ' on that you can decide whether file is already
    ' open
    Select Case errorNum
        ' No error occurred so ErroNum is Zero (0)
        ' File is NOT already open by another user.
        Case 0
         IsFileOpen = False

        ' Error number for "Permission Denied." is 70
        ' File is already opened by another user.
        Case 70
            IsFileOpen = True

        ' For any other Error occurred
        Case Else
            Error errorNum
    End Select

End Function
Public Function getConsolidatedDataFile() As Workbook
    Dim p As String
    p = ActiveWorkbook.Path
    Dim cf As String
    cf = printf("{0}\ConsolidatedData.xlsx", p)
    Dim wb As Workbook
    Dim fo As Boolean
    fo = IsFileOpen(cf)
    If fo = False Then wb = Workbooks.Open(filename:=cf)
    ''I need to get the code for this place of fo is true
    getConsolidatedDataFile wb

End Function

所以,如果文件已打开,我需要将工作簿放入wb变量中。

1
你需要保留所有打开的工作簿及其路径的引用,然后比较路径,如果之前已经打开过,则激活它使用 Application.ActiveWorkbook = TheWorkBook - Tarek.Eladly
如果您需要示例,请告诉我。 - Tarek.Eladly
@Tarek.Eladly 当然我想要一个..唯一的问题是当已经打开时如何获取打开的工作簿实例。 - Sandeep Thomas
什么是 printf? 它是自定义函数吗? 您的代码能编译吗? - Vityata
1
@Vityata 是的,那是我的自定义函数,类似于C#或VB.NET中的String.format函数。 - Sandeep Thomas
@SandeepThomas,我已经做出了这个例子。 - Tarek.Eladly
4个回答

3
我有一个解决方案。
If fo = False Then
    Set wb = Workbooks.Open(filename:=cf)
Else
    Dim w As Workbook
    For Each w In Workbooks
        If w.FullName = cf Then
            Set wb = w
        End If
    Next
End If

这里是在循环中遍历所有工作簿,如果有它就取该引用。


这只遍历同一 Excel 实例中的工作簿。请看我的更新答案。 - Vityata
不错,@SandeepThomas。 - Tarek.Eladly
@SandeepThomas - 你知道什么是Excel实例吗? - Vityata
抱歉,我只是一个VBA的新手..之前从C#转过来的。 - Sandeep Thomas
1
如果fo = False,则可以写成IF NOT fo THEN。这只是一种口味问题,但对于变量名如WorkbookIsOpen,我发现IF NOT WorkbookIsOpen THEN更容易阅读。 - Darren Bartrup-Cook
显示剩余5条评论

1
我希望这可以帮助到您。
Dim dict As Dictionary

Function OpenFile(fileFullName As String) As Workbook


If (dict.Exists(fileFullName)) Then

OpenFile = dict.Item(fileFullName)

End If

dict.Add "fileFullName", Workbooks.Open(Filename:=fileFullName)

OpenFile = dict.Item(fileFullName)

End Function

Application.ActiveWorkbook = OpenFile(fileFullName)

抱歉..我想你误解了问题..我们需要的是将打开的工作簿实例的引用传递给一个工作簿对象。 - Sandeep Thomas

1
这里有一个快速函数,如果工作簿尚未打开,它将打开它:
Function GetWorkBook(ByVal sFullName As String, Optional ReadOnly As Boolean) As Workbook
    Dim sFile As String: sFile = Dir(sFullName)
    On Error Resume Next
        Set GetWorkBook = Workbooks(sFile)
        If GetWorkBook Is Nothing Then Set GetWorkBook = Workbooks.Open(sFullName, ReadOnly:=ReadOnly)
    On Error GoTo 0
End Function

1

要将工作簿引用到工作簿集合中,它应该被打开 -

Workbook对象是Workbooks集合的成员。 Workbooks集合包含当前在Microsoft Excel中打开的所有Workbook对象。

MSDN Workbook Object

因此,如果您的工作簿在同一Excel实例中,则可以尝试以下操作:

Public Sub TestMe()        
    Dim wb As Workbook
    Set wb = Workbooks("12.xlsx")    
End Sub

如果不在同一实例中,那么GetObject应该可以工作:

Public Sub TestMe()        
    Dim wb As Workbook
    Set wb = GetObject("C:\path\12.xlsx")    
    Debug.Print wb.Worksheets(1).Name
End Sub

获取 MSDN 对象


这是同一实例中三个工作簿的外观:

enter image description here

这是两个不同实例中的两个工作簿的样子:

enter image description here

使用多个实例的利弊(源answers.microsoft.com):

优点

  • 如果您使用32位Excel,则每个实例最多可以使用3 GB内存。如果您有一台性能强大的计算机、非常重的文件和32位Excel,则每个Excel实例都可以使用3 GB。因此,例如使用2个Excel.exe实例,您可以说Excel可以使用的总内存增加了三倍。(请注意,64位Excel不受每个实例3 GB内存限制,因此不需要这样做)

  • 如果您想要一个单独的撤消链,以便每个撤消仅在当前活动的工作簿中进行,则单独的实例确实可以实现此目的。

缺点

  • 如果您想要拥有所有打开文件共享的公共撤销链,则使用多个实例将无法实现此目标。

  • 如果您想要能够快速在打开的文件之间跳转,例如按Ctrl+F6,则使用多个实例将无法实现此目标。

  • 粘贴特殊功能在实例之间不起作用。请参阅此处以获取更多信息。

  • 在两个运行实例之间创建工作簿链接不能通过单击完成,并且不会实时更新。


代码看起来没问题,只需使用Set关键字:

If fo = False Then set wb = Workbooks.Open(filename:=cf)

抱歉,我的实际问题是如果fo为真?在这种情况下,我需要将该打开的实例存储到工作表变量中。 - Sandeep Thomas
好的。如果打开了文件,然后关闭并重新打开它的问题在于,想象一下如果VBA应用程序已经对该工作簿进行了一些更改,我们不能只是关闭它。因此,最好获取已打开的实例。 - Sandeep Thomas
我们正在检查完整路径...所以它应该是相同的,不是吗?我们不仅仅是检查没有路径的文件名... - Sandeep Thomas
提供的代码仅在文件位于同一 Excel 实例中才能工作。此时它们会在相同的“工作簿”集合中。如果文件位于不同的 Excel 实例中(这种情况非常普遍),则它们不会在同一“工作簿”集合中。因此,二者是不同的。 - Vityata
既然工作簿是从另一个工作簿打开的,那么两者将在同一实例中。这对于情况是否会造成任何问题呢? - Sandeep Thomas
显示剩余5条评论

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