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.
Related
I put together a sub that allows you to input the name of the file you want your sub to refer to instead of encoding a single file. However beyond the input box, I get the error "subscript out of range". I tried entering the file name with and without "" and file extension .xls
Sub tester()
Dim wbName As String
wbName = Application.InputBox("What is the workbook name?")
If Right(wbName, 4) <> ".xls" Then wbName = wbName + ".xls"
Set mainWB = Workbooks(wbName)
Dim copyThis As Range, pasteThis As Range
Set copyThis = mainWB.Worksheets(2).Columns("F")
Set pasteThis = Workbooks("VBA Workbook.xlsm").Worksheeets(1).Columns("A")
copyThis.Copy Destination:=pasteThis
End Sub
Whenever there is user intervention, you will have to use lot of error handling to avoid possible errors. I recommned using a Userform insetad. Instead of the making a user, type the workbook name, use a UserForm witm a ComboBox1 (As shown in the image below) populated with the names of all open workbooks so that user can choose the relevant workbook rather than typing the name
Code
Option Explicit
Private Sub UserForm_Initialize()
Dim wkb As Workbook
Me.Label1.Caption = "Please select the relevant workbook"
With Me.ComboBox1
'~~> Loop thorugh all open workbooks and add
'~~> their name to the Combobox
For Each wkb In Application.Workbooks
.AddItem wkb.Name
Next wkb
End With
End Sub
Private Sub CommandButton1_Click()
If ComboBox1.ListIndex = -1 Then
MsgBox "Please select a wotkbook name and try again"
Exit Sub
End If
Dim wb As Workbook
Set wb = Workbooks(ComboBox1.List(ComboBox1.ListIndex))
With wb
MsgBox .FullName
'~~> Do what you want
End With
End Sub
New to VBA here.
At work I am creating a macro that can compile and format data from a report we get monthly and the file name changes.
Since the name changes, instead of having to go into VBE and changing the name from there, is there a user form I might be able to create that allows me to type in the name of the workbook and it will be able to insert it into the script?
What I have so far:
Sub tester()
Dim wbName As String
wbName = Application.InputBox("What is the workbook name?")
If Right(wbName, 4) <> ".xls" Then wbName = wbName + ".xls"
Set mainWB = Workbooks(wbName)
Dim copyThis As Range, pasteThis As Range
Set copyThis = mainWB.Worksheets(2).Columns("F")
Set pasteThis = Workbooks("VBA Workbook.xlsm").Worksheeets(1).Columns("A")
copyThis.Copy Destination:=pasteThis
End Sub
The workbook name will change month to month.
Alternative solutions are welcomed
Thanks all
Assuming your macro is in Personal.xlsb, and you have the workbook you need to reference as the ActiveWorkbook, you can just do:
Dim mainWB as Workbook
Set mainWB = ActiveWorkbook
Then you'd just use mainWB as the reference, so:
mainWB.Worksheets("Sheet1").Range("A1")
Or if you want the user to input the WB name:
Dim wbName as String
wbName = Application.InputBox("What is the workbook name?")
If right(wbName, 4) <> ".xls" Then wbName = wbName + ".xls"
Set mainWB = Workbooks(wbName)
...
...And you'd probably want to add error handling in the InputBox() case, if the user types a name that isn't correct.
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
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
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