4

Ive a scenario to do some changes in a workbook in another workbook path. But the question is I need to check whether the workbook already open or not. If not I need to get that opened instance to a workbook variable.

Here is the code Im using for checking whether workbook open or not and then the code for opening

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

So if file open I need to get that workbook in to that wb variable.

Community
  • 1
  • 1
Sandeep Thomas
  • 4,303
  • 14
  • 61
  • 132

4 Answers4

3

Ive got a solution

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

Here is in the loop its traversing through all workbook and if its there take that reference..

Sandeep Thomas
  • 4,303
  • 14
  • 61
  • 132
  • This traverses only the workbooks in the same Excel Instance. Take a look at my updated answer. – Vityata Mar 12 '18 at 12:41
  • nice one @SandeepThomas – Tarek.Eladly Mar 12 '18 at 12:43
  • @SandeepThomas - do you know what is an Excel Instance? – Vityata Mar 12 '18 at 12:43
  • Sorry am only a newbie with VBA.. coming from C# – Sandeep Thomas Mar 12 '18 at 12:45
  • @SandeepThomas - take a look at my answer, I have added screenshots. Your code will work only in case that the workbooks are in the same instance. Thus, they would be members of the same collection. If the instances are different, it will not work. – Vityata Mar 12 '18 at 12:50
  • @Vityata It seems to be fine in our case. Means its trying to open.. first its checks the file is already open, if open it loops through all the workbooks and if there is a match finds in path (fullname), it takes that instance of workbook from the loop itself.. Fortuanetely the solution clears the challenge I faced.. – Sandeep Thomas Mar 12 '18 at 12:52
  • @SandeepThomas - it is your project and your code, if you like it - stay with it :). If it was my project, I would not use it this way, because the `Workbooks` collection loops only the files from the same instance, thus you would miss a workbook, opened in another instance. – Vityata Mar 12 '18 at 12:57
  • @Vityata Sorry, friend. it was a very urgent requirement for a demo so I am sticking with it.. Am sure it could not be a great solution, but since it worked for the situation I was proceeding with that plan – Sandeep Thomas Mar 12 '18 at 13:09
  • @SandeepThomas - it is ok, no offence or anything :) – Vityata Mar 12 '18 at 13:23
  • 1
    `If fo = False Then` can also be written as `IF NOT fo THEN`. It's a matter of taste, but with variable names such as `WorkbookIsOpen` I find `IF NOT WorkbookIsOpen THEN` easier to read. – Darren Bartrup-Cook Mar 12 '18 at 13:44
1

To reference a workbook to the workbook collection it should be opened -

The Workbook object is a member of the Workbooks collection. The Workbooks collection contains all the Workbook objects currently open in Microsoft Excel.

MSDN Wrokbook Object

Thus, if your workbook is in the same Excel instance, then try like this:

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

If it is not in the same instance, then GetObject should work:

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

GetObject MSDN


This is how 3 workbooks in the same instance look like:

enter image description here

This is how 2 workbooks look like in 2 different instances:

enter image description here

Pros and Cons for using multiple instances (Source answers.microsoft.com):

Pros

  • If you have 32-bit Excel, each instance can use up to 3 GB memory. If you have a powerful computer, very heavy files, and 32-bit Excel, each instance of Excel can use 3 GB. So with e.g. 2 instances of Excel.exe, you could say that the total memory Excel could use triples. (Please note that this is not needed with 64-bit Excel as it is not limited by 3 GB memory per instance)

  • If you want to have a separate Undo chain, so that each Undo only undos in the currently active workbook, then separate instances will indeed achieve this.

Cons

  • If you want to have a common Undo chain shared by all open files, then using multiple instances will not achieve this.

  • If you want to be able to e.g. press Ctrl+F6 to jump between your open files quickly, then using multiple instances will not achieve this.

  • Paste Special will not work between instances. See this for more info.

  • Making workbook links between 2 files in separate running instances cannot be made by clicking, and will not update in real-time.


The code looks ok, simply use the Set keyword:

If fo = False Then set wb = Workbooks.Open(filename:=cf)
Vityata
  • 42,633
  • 8
  • 55
  • 100
  • Sorry my actual question is if fo is true? In that situation I need to get that opened instance into worksheet variable – Sandeep Thomas Mar 12 '18 at 12:17
  • Ok.. The issue with if open then close it and reopen is, just imagine if the VBA app already did some changes to that workbook, we cant just close it.. So its great to get that opened instance – Sandeep Thomas Mar 12 '18 at 12:29
  • @SandeepThomas - take a look here - https://stackoverflow.com/questions/2971473/can-vba-reach-across-instances-of-excel , there are some working solutions to get the opened instances. – Vityata Mar 12 '18 at 12:35
  • @SandeepThomas - or use `GetObject` – Vityata Mar 12 '18 at 12:38
  • Hi I did a solution there which worked fine fortunately.. Shared the answer – Sandeep Thomas Mar 12 '18 at 12:41
  • @SandeepThomas - the solution is quite dangerous - it will not work, if the instance of the opened workbook is not the same. – Vityata Mar 12 '18 at 12:42
  • We are checking full path.. So it will be same isnt it? We are not just checking the filename without path.. – Sandeep Thomas Mar 12 '18 at 12:44
  • The code you have provided works only, if the files are in the same Excel Instance. Then they are in the same `Workbooks` collection. If the files are in separate Excel Instances (which is quite often the case), then they would not be in the same `Workbooks` collection. Thus it is way not the same. – Vityata Mar 12 '18 at 12:46
  • Since the workbook is open from another workbook, both will be in same instance.. isnt it? So does that make any problem for the situation... – Sandeep Thomas Mar 12 '18 at 12:47
  • OK.. if so it works fine for different instances too.. The way I tried seems to be working fine.. – Sandeep Thomas Mar 12 '18 at 12:51
1

I hope this help

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)
Tarek.Eladly
  • 730
  • 12
  • 24
  • Sorry.. I guess you misunderstood the issue.. What we need is the reference of the opened instance of that workbook into a Workbook object – Sandeep Thomas Mar 12 '18 at 12:35
1

Here is a quick function that will open the workbook if it's not already open:

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
Tragamor
  • 3,594
  • 3
  • 15
  • 32