【问题标题】:Detect whether Excel workbook is already open [closed]检测 Excel 工作簿是否已打开 [关闭]
【发布时间】:2019-05-27 16:46:04
【问题描述】:

在 VBA 中,我以编程方式打开了一个名为“myWork.XL”的 MS Excel 文件。

现在我想要一个可以告诉我它的状态的代码——它是否打开。 IE。 IsWorkBookOpened("myWork.XL) 之类的东西?

【问题讨论】:

    标签: excel vba


    【解决方案1】:

    试试这个:

    Option Explicit
    
    Sub Sample()
        Dim Ret
    
        Ret = IsWorkBookOpen("C:\myWork.xlsx")
    
        If Ret = True Then
            MsgBox "File is open"
        Else
            MsgBox "File is Closed"
        End If
    End Sub
    
    Function IsWorkBookOpen(FileName As String)
        Dim ff As Long, ErrNo As Long
    
        On Error Resume Next
        ff = FreeFile()
        Open FileName For Input Lock Read As #ff
        Close ff
        ErrNo = Err
        On Error GoTo 0
    
        Select Case ErrNo
        Case 0:    IsWorkBookOpen = False
        Case 70:   IsWorkBookOpen = True
        Case Else: Error ErrNo
        End Select
    End Function
    

    【讨论】:

    • +1 我曾经使用这种方法检查其他用户可以访问的 newtwork 驱动器上的文件。我认为代码最初发布在 msft 网站上。
    • 当恕我直言有更好的选择时,我个人会觉得使用原始文件 IO 尝试在打开的 Excel 工作簿上读取文件感到非常不舒服:但也许它有效?
    • @Charles Williams:是的,它可能很原始,但它仍然是一个没有缺点的好代码。至少我所知道的没有。 :) 试试看,也许你会喜欢?
    • 我确信它可以工作,但您认为更简单、更适合 Excel 的代码的缺点是什么? (使用 Workbooks.Open 打开工作簿并检查 Workbook.Readonly)
    • @CharlesWilliams 公平点。虽然在我的情况下,当我尝试类似的事情时,实际上 打开 托管在海外服务器上的大型模型的时间开销约为 2-3 分钟。当它以只读方式打开时,它给出了一个“grrr”时刻,而上面的 Sid 函数给出了立即响应。 FWIW Bob Phillips 在vbaexpress 列出了一个类似的功能,这是一个更高级的版本,等待本书在Chip Pearson 的其他地方关闭
    【解决方案2】:

    对于我的应用程序,我通常希望使用工作簿,而不仅仅是确定它是否打开。对于这种情况,我更喜欢跳过布尔函数,只返回工作簿。

    Sub test()
    
        Dim wb As Workbook
    
        Set wb = GetWorkbook("C:\Users\dick\Dropbox\Excel\Hoops.xls")
    
        If Not wb Is Nothing Then
            Debug.Print wb.Name
        End If
    
    End Sub
    
    Public Function GetWorkbook(ByVal sFullName As String) As Workbook
    
        Dim sFile As String
        Dim wbReturn As Workbook
    
        sFile = Dir(sFullName)
    
        On Error Resume Next
            Set wbReturn = Workbooks(sFile)
    
            If wbReturn Is Nothing Then
                Set wbReturn = Workbooks.Open(sFullName)
            End If
        On Error GoTo 0
    
        Set GetWorkbook = wbReturn
    
    End Function
    

    【讨论】:

    • 我同意这通常是想要的:如果你想检查这本书是否已经在另一个 Excel 实例中打开,你可以检查它是否以只读方式打开
    • 这给我Workbooks(sFile) 上的越界错误
    • 您不能在代码中包含On Error Resume Next,或者您在 VBE 的工具 - 选项下设置了对所有错误的中断。
    • 这个版本对我来说效果更好,上面的版本似乎没有检测到以只读方式打开的工作簿......
    • 我曾经使用过它,但是这些天我在 Excel 2017 中遇到了很多自动化错误,因为在运行宏之前已关闭相关工作簿.解决方案是放弃On Error Resume Next(因为wbReturn 不是 Nothing,但包含错误)并编写真正的错误处理。见:pastebin.com/u1LLgPa1
    【解决方案3】:

    如果打开,它将位于 Workbooks 集合中:

    Function BookOpen(strBookName As String) As Boolean
        Dim oBk As Workbook
        On Error Resume Next
        Set oBk = Workbooks(strBookName)
        On Error GoTo 0
        If oBk Is Nothing Then
            BookOpen = False
        Else
            BookOpen = True
        End If
    End Function
    
    Sub testbook()
        Dim strBookName As String
        strBookName = "myWork.xls"
        If BookOpen(strBookName) Then
            MsgBox strBookName & " is open", vbOKOnly + vbInformation
        Else
            MsgBox strBookName & " is NOT open", vbOKOnly + vbExclamation
        End If
    End Sub
    

    【讨论】:

    • Charles,这个方法我已经想到了。这种方法的主要缺点是,如果工作簿在不同的 Excel 实例中打开,那么您将始终将值设为 false :) 另一种方法是添加代码以循环遍历所有 Excel 实例,然后使用您的代码。最终我意识到我正在编写更多代码,因此我使用了另一种方法。席德
    • 如果你想检查这本书是否在另一个 Excel 实例中打开(可能是因为你无法保存或编辑它)为什么不在打开它后检查它是否只读(如果oBk.Readonly ...)
    【解决方案4】:

    我会选择这个:

    Public Function FileInUse(sFileName) As Boolean
        On Error Resume Next
        Open sFileName For Binary Access Read Lock Read As #1
        Close #1
        FileInUse = IIf(Err.Number > 0, True, False)
        On Error GoTo 0
    End Function
    

    作为 sFileName,您必须提供文件的直接路径,例如:

    Sub Test_Sub()
        myFilePath = "C:\Users\UserName\Desktop\example.xlsx"
        If FileInUse(myFilePath) Then
            MsgBox "File is Opened"
        Else
            MsgBox "File is Closed"
        End If
    End Sub
    

    【讨论】:

      【解决方案5】:

      如果您想在不创建另一个 Excel 实例的情况下进行检查怎么​​办?

      例如,我有一个 Word 宏(重复运行),它需要从 Excel 电子表格中提取数据。如果电子表格已在现有 Excel 实例中打开,我不希望创建新实例。

      我在这里找到了一个很好的答案: http://www.dbforums.com/microsoft-access/1022678-how-check-wether-excel-workbook-already-open-not-search-value.html

      感谢 MikeTheBike 和 kirankarnati

      Function WorkbookOpen(strWorkBookName As String) As Boolean
          'Returns TRUE if the workbook is open
          Dim oXL As Excel.Application
          Dim oBk As Workbook
      
          On Error Resume Next
          Set oXL = GetObject(, "Excel.Application")
          If Err.Number <> 0 Then
              'Excel is NOT open, so the workbook cannot be open
              Err.Clear
              WorkbookOpen = False
          Else
              'Excel is open, check if workbook is open
              Set oBk = oXL.Workbooks(strWorkBookName)
              If oBk Is Nothing Then
                  WorkbookOpen = False
              Else
                  WorkbookOpen = True
                  Set oBk = Nothing
              End If
          End If
          Set oXL = Nothing
      End Function
      
      Sub testWorkbookOpen()
          Dim strBookName As String
          strBookName = "myWork.xls"
          If WorkbookOpen(strBookName) Then
              msgbox strBookName & " is open", vbOKOnly + vbInformation
          Else
              msgbox strBookName & " is NOT open", vbOKOnly + vbExclamation
          End If
      End Sub
      

      【讨论】:

        【解决方案6】:

        这个比较容易理解:

        Dim location As String
        Dim wbk As Workbook
        
        location = "c:\excel.xls"
        
        Set wbk = Workbooks.Open(location)
        
        'Check to see if file is already open
        If wbk.ReadOnly Then
          ActiveWorkbook.Close
            MsgBox "Cannot update the excelsheet, someone currently using file. Please try again later."
            Exit Sub
        End If
        

        【讨论】:

        • 又短又甜:)
        【解决方案7】:

        查看此功能

        '********************************************************************************************************************************************************************************
        'Function Name                     : IsWorkBookOpen(ByVal OWB As String)
        'Function Description             : Function to check whether specified workbook is open
        'Data Parameters                  : OWB:- Specify name or path to the workbook. eg: "Book1.xlsx" or "C:\Users\Kannan.S\Desktop\Book1.xlsm"
        
        '********************************************************************************************************************************************************************************
        Function IsWorkBookOpen(ByVal OWB As String) As Boolean
            IsWorkBookOpen = False
            Dim WB As Excel.Workbook
            Dim WBName As String
            Dim WBPath As String
            Err.Clear
            On Error Resume Next
            OWBArray = Split(OWB, Application.PathSeparator)
            Set WB = Application.Workbooks(OWBArray(UBound(OWBArray)))
            WBName = OWBArray(UBound(OWBArray))
            WBPath = WB.Path & Application.PathSeparator & WBName
            If Not WB Is Nothing Then
                If UBound(OWBArray) > 0 Then
                    If LCase(WBPath) = LCase(OWB) Then IsWorkBookOpen = True
                Else
                    IsWorkBookOpen = True
                End If
            End If
            Err.Clear
        End Function
        

        【讨论】:

        • 这将捕获工作簿是否在本地计算机上的当前实例中打开 - 它不会捕获工作簿是在另一个本地实例中打开还是由其他用户在其他地方打开。
        • 我认为WB.Path &amp; "\" &amp; WBNameWB.FullName
        • 我还要在退出函数之前添加 Set WB = Nothing
        • 现在只使用文件名...
        • 如何在sub中调用和使用这个函数?我的意思是这个函数的输入是字符串
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-31
        相关资源
        最近更新 更多