I have files I download on a daily basis but the name of the file changes every day.
Ex: Day 1 file name: miss123_1 Day 2: miss349_1
Is there any way to have the macro look for open files where the active workbooks title contains certain characters rather than having the macro look for that exact file? My current workaround is to constantly change the workbook title to fit that days name but there must be a way to make it dynamic.
My idea that does not work:
Windows(Contains("miss","_1",".xlsx")).Activate
Reference an Open Workbook by Partial Name
You need to loop through the Workbooks collection and compare each workbook name to a string pattern.
You can use the Like operator for the comparison.
The RefWorkbookTEST procedure illustrates how to utilize the RefWorkbook function.
Option Explicit
Sub RefWorkbookTEST()
Dim wb As Workbook: Set wb = RefWorkbook("miss*_1*.xlsx")
If wb Is Nothing Then
MsgBox "Workbook not found.", vbExclamation
Else
MsgBox "Referenced workbook '" & wb.Name & "'.", vbInformation
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: References an open workbook whose lower-case name matches
' a given lower-case string pattern.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefWorkbook(ByVal LowerCaseNamePattern As String) As Workbook
Dim wb As Workbook
For Each wb In Workbooks
If LCase(wb.Name) Like LowerCaseNamePattern Then
Set RefWorkbook = wb
Exit Function
End If
Next wb
End Function
Related
I want to create a macro where it will copy some data from one workbook (whose name stays always same - "SameNameWorkbook") and pastes that data in another open workbook whose name is changing everyday (because its name is a date). For example today my workbook which I want to paste the data in is called "11.06.2021".
What I did is I created a =today() formula in the J2 cell in the active workbook (different from the other 2 and named "CurrentWorkbook") and created a variable in VBA for the workbook with changing name:
`Second_workbook = Range("J2").Value`
When I want to have always a reference to the second workbook I wrote this:
`Windows("Second_workbook.xlsx").Activate`
`Range.("A1").Select`
`ActiveSheet.Paste`
Since Second_workbook is a variable linked to the =today() formula which is 11.06.2021 I thought that will put the date before .xlsx. However, this shows an error so my logic is wrong. Since I am more fond of Excel formulas I thought that this logic will work like the indirect function but obviously it doesn't.
So the end result which I want to have is following:
`Windows("11.06.2021.xlsx").Activate`
Tomorrow, then I want to have the following:
`Windows(12.06.2021.xlsx").Activate`
... and so on without me manually changing the name workbook in the macro everyday while I keep all 3 workbooks open of course.
Could you please help me with this issue? I would really appreciate your help.
Date Formatting
You have to format your date:
Format(Date, "dd.mm.yyyy") & ".xlsx"
Format(Range("J2").Value, "dd.mm.yyyy") & ".xlsx"
Date is the equivalent of Excel's TODAY in VBA.
Here's a common scenario (adjust the worksheet names and the ranges):
Option Explicit
Sub CopyToToday()
Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
' Attempt to create a reference to the Destination Workbook.
Dim dName As String: dName = Format(Date, "dd.mm.yyyy") & ".xlsx"
On Error Resume Next
Dim dwb As Workbook: Set dwb = Workbooks(dName)
On Error GoTo 0
If dwb Is Nothing Then
MsgBox "Could not create a reference to today's workbook.", _
vbCritical, "Workbook not open"
Exit Sub
End If
' Copy a range from Source Worksheet to Destination Worksheet.
swb.Worksheets("Sheet1").Range("A1:F10").Copy
dwb.Worksheets("Sheet1").Range("A1").PasteSpecial
Application.CutCopyMode = False
'dwb.Save
End Sub
"Second_workbook.xlsx" is a string and will be interpreted as a string, ignoring any variables with the same name.
Variables are written out without quotes, and strings of text have the quotes. Everything within quotes (green text) is taken as a string of text. To combine strings and variables we use the & operand like so:
"string" & variable & "string"
So what you are looking for should be:
Windows(Second_workbook & ".xlsx").Activate
You might want to save the workbook as a variable object instead, to refer to it easier:
Dim wb As Workbook
Set wb = Workbooks(Range("J2") & ".xlsx")
Or if you are using the Second_workbook variable anyway, you can set it like:
Set wb = Workbooks(Second_workbook & ".xlsx")
Remember that this range, just as in your example will be interpreted as ActiveWorkbook.ActiveSheet.Range("J").value unless you specify it. Make sure that this won't cuase problems.
To activate a cell in this workbook, you can use wb.Worksheets(1).Range("A1").Select, for example.
I currently run a sub in another (open) workbook using this line:
Application.Run ("'NDS Analytics.xlsm'!Process")
The names of the referenced workbooks are changing so I would like to change the reference so that instead of looking for file NDS Analytics.xlsm it looks for an open file that contains the words "NDS Analytics".
There will only ever be one file with this name open at a time and it could be called either NDS Analytics.xlsm, wNDS Analytics.xlsm or 40ghNDS Analytics.xlsm.
Application Run with Variable Workbook
Option Explicit
Sub runProcess()
Dim wb As Workbook
For Each wb In Workbooks
If UCase(wb.Name) Like UCase("*NDS Analytics*.xlsm") Then
Application.Run "'" & wb.Name & "'!Process"
Exit For
End If
Next wb
End Sub
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.
I want to loop through all open Excel workbooks to identify which one on which to perform operations. Problem is, the code exits the for loop after the active workbook and returns "Nothing" as a result, regardless of how many workbooks I have open.
I need to run this routine weekly to transfer working hours from a downloaded Excel workbook into an alternate workbook. The name of the file changes every week, but always begins with "Timesheets"
I used this routine every week from January through April without any problems. I tried to use it today and this problem cropped up. I've used the routine on several different computers with different operating systems (Windows 7, Windows 10).
I've saved, closed, and reopened the workbook I want to activate to no avail. I don't want to have to change the code every week to access a specific workbook, but use the first 4 letters in the file name to identify the file on which to perform operations.
Sub cmdImportHours_Click()
Dim ThisWB As Workbook
Dim ImportWB As Workbook
Dim WB As Workbook
Dim msg1 As String
Dim msg As Variant
' more variables
msg1 = "Required file not found. Open the import file and try again."
Set ThisWB = ThisWorkbook
ThisWB.Worksheets("Hours").Activate
'The following loop exits after one iteration (the active workbook),
'regardless of how many workbooks are open
For Each WB In Workbooks
If Left(WB.Name, 4) = "Time" Then
WB.Activate
Exit For
End If
Next WB
If WB Is Nothing Then
msg = MsgBox(msg1, vbOKOnly)
Exit Sub
End If
'more code
End Sub
I expect the loop to look at the name of every open Excel workbook, but it exits the For Loop after looking at the active workbook only.
Your For Each over all workbooks directly returns a usable variable, which references the wanted workbook, so you may even use the variable "ImportWB" here. Exiting the loop by Exit For, if you found the desired item, is good practice.
I introduced two variables for worksheets to use them for copy operations.
Sub cmdImportHours_Click()
Dim ImportWB As Workbook
Dim SourceSheet As Worksheet, DestSheet As Worksheet
Dim msg1 As String
Dim msg As Variant
For Each ImportWB In Workbooks
If Left(ImportWB.Name, 4) = "Time" Then Exit For
Next ImportWB
If ImportWB Is Nothing Then
msg1 = "Required file not found. Open the import file and try again."
msg = MsgBox(msg1, vbCritical + vbOKOnly, "Workbook not open")
Exit Sub
End If
Set DestSheet = ThisWorkbook.Worksheets("Hours")
'DestSheet.Activate is typically not necessary
Set SourceSheet = ImportWB.Sheets(1)
DestSheet.Range("A2:B10").Value = SourceSheet.Range("A2:B10").Value
' more code
End Sub
As ThisWorkbook is always the same (the workbook with your VBA-code), it's not necessary to give it an extra variable, and I omitted it.
If you don't get your already opened workbook by above code, then it's either opened within a protected view ...
For i = 1 To Application.ProtectedViewWindows.Count
Debug.Print "Protected Workbook: " & _
Application.ProtectedViewWindows(i).Workbook.Name
Next i
... or within another Excel instance. In that case you may reference it by e. g.
Set ImportWB = GetObject("Path\Filename.xlsx")
See here for more examples on that.
That because Exit For, just comment that line. And don't use WB outside for each use other variable instead, in this code variable count used to count matching workbooks
Dim count As String
count = 0
For Each WB In Workbooks
If Left(WB.Name, 4) = "Time" Then
count = count + 1
WB.Activate
'Exit For
End If
Next WB
If count < 1 Then
msg = MsgBox(msg1, vbOKOnly)
Exit Sub
End If
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