1

I copied some UDF function code that serves my purpose from this guide which supposedly has worked for others. I didn't really alter the code much, but for transparency here is the exact code I have in my workbook as a module:

Function IsExtWorkBookOpen(Name As String) As Boolean
    Dim xWb As Workbook
    On Error Resume Next
    Set xWb = Application.Workbooks.Item(Name)
    IsExtWorkBookOpen = (Not xWb Is Nothing)
End Function

Now when I enter the function in a cell of the workbook, the function appears as an option in the dropdown list. I pressed tab to autofill the full name of the UDF, to ensure the function name is correctly typed. I then called the function several times in different cells with different filenames/paths as strings, such as:

=IsExtWorkBookOpen("C:\Computer\Fake\filepath\name\CORRECTLY SPELLED FULL FILENAME.xlsm")
=IsExtWorkBookOpen("C:\Computer\Fake\filepath\name\[CORRECTLY SPELLED FULL FILENAME].xlsm")
=IsExtWorkBookOpen("[CORRECTLY SPELLED FULL FILENAME]")

tried with or without the brackets around the filename. And ofc I've redacted the filepath/name here, its an actual filepath and filename in my code. Note that the filepath in my code directs to a drive that is a network directory, not a local directory in the PC's hardware.

Also tried adding the following as a second parameter: Optional VolatileParameter As Variant and calling , NOW() as the second parameter to see if it has something to do with the UDF needing to be volatile. To my dismay, nothing seems to work, as the resulting value in the cells is always #NAME.

It gets weird though, because I tested my code in the VBA editor by inserting a procedure, calling the UDF in the procedure, placing breakpoints in the UDF and running the procedure. Here's the code for that:

Public Sub Test1()
    Dim x
    x = IsExtWorkBookOpen("EXTERNAL WORKBOOK.xlsm")
    MsgBox (x)
End Sub

The procedure runs perfectly, and returns a FALSE value. Can't notice anything off in the registries during breakpoints. Although I did notice it seems to return FALSE even if the external workbook I am checking is actually open... so thats probably a bigger problem than trying to figure out why the function won't work when entered into a cell.

Even weirder, is the very first time I entered the function into a cell, it did return and display FALSE! but only the very first time, ever since just #NAME.

I tried crawling the web for similar programming bugs and the closest I found was this forum thread. It seems that maybe, as with this user's UDF, mine is not even executing because excel doesn't know how to execute it from the start?

Finally, I noticed the following comment by 'Joe' on the first webpage, from where I copied the code, which stated:

Just want to make sure everyone is aware, the "IsWorkBookOpen" function will only be able to tell if a workbook is open in the current instance of Excel. If you have multiple instances open you would need to run it on each instance to be sure the workbook is (not) open, using this code alone.

Reading this comment, is this code doomed to work for my purpose from the beginning? I still doubt this because the #NAME error happens even when I tried calling the UDF with the correctly spelled filename of the current workbook (not the external one)(the workbook within which the VBA module is) which leads me to believe the bug is elsewhere in the code functionality.

If so though, can anyone give me a hint as to what code is needed to successfully perform my function that checks if another workbook is open in the same local PC/desktop?

niton
  • 8,771
  • 21
  • 32
  • 52
  • 2
    That UDF works fine for me, though note that `Application.Workbooks.Item()` wants the workbook name and not the full path, so `=IsExtWorkBookOpen("tempo3.xlsb")` returns TRUE but `=IsExtWorkBookOpen("C:\Temp\tempo3.xlsb")` gives FALSE – Tim Williams Aug 18 '22 at 20:03

2 Answers2

1

That UDF works fine for me, though note that Application.Workbooks.Item() wants the workbook name and not the full path, so

=IsExtWorkBookOpen("tempo3.xlsb") 

returns TRUE but

=IsExtWorkBookOpen("C:\Temp\tempo3.xlsb") 

gives FALSE.

Note you can take a different approach using GetObject if you want to find out if a workbook is open in the same instance or a different instance of Excel (note here you'd pass in the full path):

Function IsExtWorkBookOpen2(Name As String) As Boolean
    Dim xWb As Object
    On Error Resume Next
    Set xWb = GetObject(Name)
    If Not xWb Is Nothing Then Debug.Print xWb.Name
    IsExtWorkBookOpen2 = (Not xWb Is Nothing)
End Function
Tim Williams
  • 154,628
  • 8
  • 97
  • 125
0

I suggest you to rewrite that function as follow:

Option Explicit



Function IsWorkbookOpenByName(name As String) As Boolean

Dim wb As Workbook
For Each wb In Application.Workbooks ' Loop through all open workbooks
    If wb.Name = name Then ' If a workbook is found with specified name (name + extension)...
        IsWorkbookOpenByName = True ' ... return true...
        Exit For ' ... and exit loop.
    End If
Next

End Function



Function IsWorkbookOpenByFullName(fullName As String) As Boolean
    
    Dim wb As Workbook
    For Each wb In Application.Workbooks ' Loop through all open workbooks
        If wb.FullName = fullName Then ' If a workbook is found with specified fullName (path + name + extension)...
            IsWorkbookOpenByFullName = True ' ... return true...
            Exit For ' ... and exit loop.
        End If
    Next
    
End Function

The code above is tested and working.

If you want to combine these functions in only one, simply change the If statement into If wb.Name = name or wb.FullName = name in the first function:

Option Explicit



Function IsWorkbookOpen(name As String) As Boolean

Dim wb As Workbook
For Each wb In Application.Workbooks ' Loop through all open workbooks
    If wb.Name = name or wb.FullName = name Then ' If a workbook is found with specified name or fullname...
        IsWorkbookOpen = True ' ... return true...
        Exit For ' ... and exit loop.
    End If
Next

End Function

With this last function you can pass the name or the fullname (name + path + extension).

Note 1: I highly recommend you using Option Explicit for all your VBA code. This preprocessor command forces the VBA interpreter (remember that VBA is not really compiled) to require all variable declarations. This prevent typos and will save you hours of debugging in search of a missing char in some variable name. Also, it will make your code more reliable and it's a healthy habit.

Note 2: When possible, avoid the On Error Resume Next statement because it can be harmful. That statement "authorizes" the code execution to continue even if errors occurs, so you could get unexpected result from your code and it could be difficult to debug if it's a complex function.

I say this because VBA was my first programming language, and unfortunately no one told me about these aspects. I learned that changing bad habits is more difficult than learning good practices on time :)

IFrank
  • 419
  • 1
  • 5
  • 12
  • 1
    Thanks for your input, I have no qualms with reprogramming it to work this way. I copied your code (the third iteration, with both 'IF wb.Name = name or wb.FullName = name Then'. It returns FALSE in the cell when entered and the external referenced workbook is closed, but unfortunately it also returns FALSE when the external referenced workbook is open. Could it be because the external referenced workbook is not on my local drive but on a network drive? – Agustin Ferreira Aug 18 '22 at 21:04
  • @AgustinFerreira I tried with files on a shared network drive, the code still works. Can you try others UDF? I think there's something not related with your specific function... Just a question to be sure: after opening the "other" workbook, do you re-enter the function in the cell? If no, that's why is not working - Excel UDFs are not automatically re-triggered by default. – IFrank Aug 20 '22 at 08:51