How to reference an opened not active workbook? - excel

I want to reference from code in an active workbook to another workbook,
I don't want to type path like that workbooks("path") , this reference should be flexible, is there something like array of already opened workbooks ?

You can assign an open workbook to a variable without providing the full path. You can then use the set object variable to perform any actions you wish.
Sub set_wb()
Dim wb As Workbook
Set wb = Workbooks("test_wb.xlsb")
wb.Activate
End Sub
You can also iterate through each open workbook using for each
Sub wb_names()
Dim wb As Workbook
For Each wb In Workbooks
Debug.Print wb.Name
Next wb
End Sub
Similarly, you can use for to iterate through each workbook using their index (the index is dependant on which order workbooks were opened).
Sub wb_index()
Dim i As Byte
For i = 1 To Workbooks.Count
Debug.Print Workbooks(i).Name
Next i
End Sub
Hope this helps.

See this answer.
To reference an already open workbook, you can use
Workbooks("book_name.xlsx")
You can also iterate through the collection
Dim i As Integer
For i = 1 To Workbooks.Count
MsgBox Workbooks(i).Name
Next i

Related

Workbook.name property does not return the name of an excel file

I use the code below to write the names of the workbooks open in Microsoft Excel in an array, but it does not return the name of a freshly open excel file that was generated from SQL Server using template file (.xltm), knowing that the user account is a domain user. So, is it because of template or the domain user account? and how can I solve this problem and get the name of such file?
For Each AWB In Application.Workbooks
If AWB.Name <> ThisWorkbook.Name Then
WB_Array(i) = AWB.Name
i = i + 1
End If
Next AWB
Thanks
Extending the great answer in the link that Tim Williams gave in the comments, if the issue is that the other workbook is open in a different instance of Excel, you won't be able to find it by just looking in Application.Workbooks. You will need to get all the open Excel.Application Objects and then check each of their Application.Workbooks collections.
Credit to Florent B. for their code. Add their code to your project. Then use the following function to collect each workbook into a Dictionary. I have included an example of how to use that function to collect all the workbook names into an array.
Sub Example()
Dim AllWorkbooks As Object
Set AllWorkbooks = GetAllWorkbooks
'AllWorkbooks.Keys() is now an array containing the names of all open workbooks
'AllWorkbooks.Items() is now an array of all open workbook objects
End Sub
Function GetAllWorkbooks() As Object
Dim xlWorkbooks As Object
Set xlWorkbooks = CreateObject("Scripting.Dictionary")
Dim xl As Application
For Each xl In GetExcelInstances()
Dim WB As Workbook
For Each WB In xl.Workbooks
If Not xlWorkbooks.Exists(WB.Name) Then xlWorkbooks.Add WB.Name, WB
Next
Next
Set GetAllWorkbooks = xlWorkbooks
End Function
Open Workbooks to Array
Option Explicit
Sub ListWorkbookNames()
Dim wbCount As Long: wbCount = Workbooks.Count
If wbCount = 1 Then
MsgBox "Only the workbook containing this code is open.", vbExclamation
Exit Sub
End If
Dim WorkbookNames() As String: ReDim WorkbookNames(1 To wbCount - 1)
Dim wb As Workbook
Dim n As Long
For Each wb In Workbooks
If Not wb Is ThisWorkbook Then
n = n + 1
WorkbookNames(n) = wb.Name
End If
Next wb
MsgBox "Found the following open workbooks:" & vbLf _
& Join(WorkbookNames, vbLf), vbInformation
End Sub

Copy & Paste column between workbooks with * file [duplicate]

Is there a way to specify a workbook for a sheet without having the full name?
For example, If the workbook name is MyWorbook2015 and the 2015 may change to 2016 in the future, I need to to recognize the workbook based on MyWorkbook, and ignore the 2015. Something similar to this:
With Workbooks("MyWorkbook2015").Sheets("My_Sheet_Name_That_Does_Not_Change")
'do something
End With
In the code sample above, I need it to recognize the work book regardless of the date? Is this possible? If it is, how would I go about doing that?
Yes you can use the LIKE Operator with a wildcard "*". Here is an example. I am assuming that the workbook is open.
Sub Sample()
Dim wb As Workbook
Dim wbName As String
'~~> "MyWorkbook2015"
wbName = "MyWorkbook"
For Each wb In Application.Workbooks
If wb.Name Like wbName & "*" Then
Debug.Print wb.Name
With wb.Sheets("My_Sheet_Name_That_Does_Not_Change")
'~~> Do something
End With
End If
Next wb
End Sub
EDIT
Here is a way where you can use it as a function
Dim wbName As String
Sub Sample()
'~~> "MyWorkbook2015"
wbName = "MyWorkbook"
If Not GetWB Is Nothing Then
Debug.Print GetWB.Name
With GetWB.Sheets("My_Sheet_Name_That_Does_Not_Change")
'~~> Do something
End With
Else
MsgBox "No workbook with that name found"
End If
End Sub
Function GetWB() As Workbook
Dim wb As Workbook
For Each wb In Application.Workbooks
If wb.Name Like wbName & "*" Then
Set GetWB = wb
Exit Function
End If
Next wb
End Function
A slightly more reliable alternative to doing a partial match on Workbook.Name is to do an equivalency match on WorkBook.CodeName. The default CodeName for a Workbook is "ThisWorkbook", but you can change that by selecting the "ThisWorkbook" code page in the Project Explorer window and then open the Properties Window (Key: F4) and change the Name property for the code page.
Then following the example that Siddharth has shown but redefining then "GetWB" function like this:
Function GetWB() As Excel.Workbook
Const wbCodeName As String = "MySecretWorkbookName" ' change to the CodeName you choose
Dim wb As Workbook
For Each wb In Application.Workbooks
If wb.CodeName = wbCodeName Then
Set FindWorkbook = wb
Exit For
End If
Next wb
End Function
Note that changing the CodeName allows you to use the new CodeName in places where you would have used "ThisWorkbook", but you can still use "ThisWorkbook" as well.

How to get Workbook Name after opening the workbook using workbooks.open?

Workbooks.Open "C:\abc.xlsx"
Workbooks("abc").Worksheets("Sheet1").Range("A1:B7").Clear
In the above code I am opening the workbook using Workbooks.Open in first line. In the second line I am accessing the opened workbook using the workbook name.
How can I access the opened workbook without the filename in second line?
(I want to create a function and I don't want to pass both the file paths and filenames separately)
You need to use references and reference the workbook and the sheet for example:
Option Explicit
Sub OpenWorkbook()
Dim wb As Workbook, ws As Worksheet
Set wb = Workbooks.Open("C:\abc.xlsx", UpdateLinks:=False, ReadOnly:=True)
Set ws = wb.Sheets("Sheet1")
ws.Range("A1:B7").ClearContents
End Sub
Note that the parameters on the openworkbook such as Updatelinksand ReadOnly can be modified to True or Falseas you need to.
Create an object of type Excel.Workbook and open the workbook into that.
Like so
Dim w as Excel.Workbook
set w= Workbooks.Open ("C:\abc.xlsx")
and then you can say
w.worksheets.add.....
etc
You can shorten your code:
Option Explicit
Sub OpenWb()
Dim ws As Worksheet
Set ws = Workbooks.Open("C:\abc.xlsx").Worksheets("Sheet1")
With ws '<- Use With Statement to avoid sheet repetition
.Range("A1:B7").ClearContents
End With
End Sub
You can try this
Option Explicit
Sub TEST()
Dim WB As Workbook
Set WB = Workbooks.Open(Filename:="C:\abc.xlsx")
For Each WB In Workbooks
If WB.Name = "abc.xlsx" Then
WB.Worksheets(Sheet1).Range("A1:B7").ClearContents
Exit Sub
End If
Next
End Sub

VBA - Opening a workbook and remembering it for other macros

I'd like to create a macro that will:
Open a browser window to select a saved workbook (let's call it WB1)
In the same macro assign WB1 some form of reference that will allow it to be referenced by other macros
I can achieve step 1 via the following code:
Sub Add_New_Survey()
Dim pathString As String
Dim resultWorkbook As Workbook
Dim found As Boolean
pathString = Application.GetOpenFilename(fileFilter:="All Files (* . xl*) , *.xl* ")
' check if it's already opened
For Each wb In Workbooks
If InStr(pathString, wb.Name) > 0 Then
Set resultWorkbook = wb
found = True
Exit For
End If
Next wb
If Not found Then
Set resultWorkbook = Workbooks.Open(pathString)
End If
End Sub
This will open the workbook. I then need to perform a number of data preparation activities on WB1 which I would like to automate. Is there a way to reference WB1 as I open it from the browser so the following macros know to look on WB1 specifically?
Many thanks
Welcome to SO. Your object resultWorkbook is linked to Workbooks.Open(pathString), so as long as you dont unlink it with Set resultWorkbook = Nothing, you can reference that workbook always on any sub, (but declare the variable as Public first in the module, outside of all subs).
To declare a Variable as Public, please read:
How do I declare a global variable in VBA?

Switch to other workbook

I am trying to build a code which would switch to the immediate other open workbook and copy data from there.
I can use workbook(1) and workbook(2) ,but problem is this index changes by sequence of opening workbooks.
So I want to put if function in it ,but doesnt work. Below is the code.
If ActiveWorkbook = Workbooks(1) Then
Workbooks(2).Activate
Else
Workbooks(1).Activate
End If
but it gives error 438 ,object doesn't support property or method.
Can you help me debug this?
Try the code below, the last section of the Copy >> Paste is just an example how you copy Range("A1:E10") from "Sheet1" in DestWB to ThisWB "Sheet1" (without using Activate or Select) - you should be able to modify it quite easily.
Code
Option Explicit
Sub CopyThisWorkBOok()
Dim ThisWB As Workbook
Dim DestWB As Workbook
Dim wb As Workbook
Dim i As Long
i = Application.Workbooks.Count
If i <> 2 Then ' check if number of open workbooks is 2
MsgBox "You need to have 2 open workbooks, currently there are " & i & " open workbooks", vbCritical
Exit Sub
Else
For Each wb In Application.Workbooks ' loop through all open workbooks
If wb.Name <> ThisWorkbook.Name Then
Set DestWB = wb
Else
Set ThisWB = ThisWorkbook
End If
Next wb
End If
' from here you start the part where you copy >> paste, there is no need to `Activate` or `Select` anything
DestWB.Worksheets("Sheet1").Range("A1:E10").Copy Destination:=ThisWB.Worksheets("Sheet1").Range("A2")
End Sub
You can use names of target objects, for example:
Workbooks("MyBook.xls").Worksheets("Sheet1").Activate
Depending on what you are trying to do, the description is not very clear, you can use a variation of this code. You can define the workbook that contains the VBA as "ThisWorkBook" and go from there.
Dim source_worksheet As Worksheet
Set source_worksheet = ThisWorkbook.Worksheets("Sheet2")
Dim target_worksheet As Worksheet
Set target_worksheet = ActiveWorkbook.Worksheets("Sheet1")
'Defines what sheet you are copying
source_worksheet.Copy After:=target_worksheet

Resources