Excel VBA: How to activate a workbook without its complete name? - vba

I have multiple excel workbooks open. I want to activate a workbook which has "Final" in its name.
Example: I have three open workbooks called "Workbook1.xlsx", "worKbook2.xlsm" and "workbookFinal.xlsx" open at the same time.
My VBA code is in "Macro.xlsm". Using VBA I want to activate the workbook which has "Final" in it. FYI .. all workbooks are in different paths.

Try the code below, using the Like Operator with the wild-card *.
Option Explicit
Sub FindFinalWorkbook()
Dim wb As Workbook
' loop through all open workbooks
For Each wb In Application.Workbooks
If wb.Name Like "*Final*" Then '< -- check if workbook name is Like *Final*
wb.Activate
Exit For
End If
Next wb
End Sub

loop through Workbooks collection until finding the right named workbook:
Sub wbs()
Dim wb As Workbook
For Each wb In Workbooks
If InStr(wb.Name, "Final") > 0 Then
wb.Activate
Exit For
End If
Next
End Sub

Related

Subscript Out Of Range when accessing Sheet in another opened Workbook

I want to reference to the first opened Workbook. 2 workbooks are open: one that is calling the macro to execute, and the workbook which contains the macro. Somehow, the code runs smoothly very often. But sometimes, there occurs a referencing error when accessing data in the first opened workbook: Subscript Out Of Range.
On this line, the error occurs:
Set mastersheet = Workbooks(1).Sheets("Setting")
So there should be two workbooks in the collection. What am I overseeing? Please keep in mind, that the first opened workbook doesn't have a fixed name, so the name of the open workbook changes. The second Workbook, the workbook which contains the macro to execute, doesn't change it's name.
Unfortunately, you don't provide more code or any information about what kind of code "container" the macro is in. The following solution assumes the macro is in a Worksheet or Workbook code container (Sheet1 or ThisWorkbook in the VBA Editor, for example).
It's possible to get the workbook from the code container. If the code is in a Worksheet code container, then use Me.Parent. If it's in ThisWorkbook use Me. These containers are actually classes that represent the Worksheet / the Workbook object. So Me refers to that object. The parent of a Worksheet is its workbook.
So a Workbook object is set to its container workbook. Then the open workbooks are looped in a For...Each and the workbook is tested whether it's the same as the code container workbook, or if it's another. If it's another, then the loop is exited. Debug.Print shows the result (two different names) and demonstrates how to continue to work with the separate workbook objects.
Sub GetOtherWorkbook()
Dim wbWithMacro As Workbook
Dim wbOther As Workbook, wb As Workbook
Set wbWithMacro = Me.Parent 'Assumes macro is in a "Sheet" code container
'Set wbWithMacro = Me 'Assumes macro is in "ThisWorkbook" code container
For Each wb In Workbooks
If Not wb Is Me Then
Set wbOther = wb
Exit For
End If
Next
Debug.Print wbWithMacro.Name, wbOther.Name
End Sub
I suggest the following to find the Setting worksheet:
Option Explicit
Public Sub FindSettingWorksheet()
Dim MasterSheet As Worksheet
Dim wb As Workbook
For Each wb In Workbooks 'loop through all open workbooks
On Error Resume Next 'stop error reporting
Set MasterSheet = wb.Worksheets("Setting") 'if this throws an error it's the wrong workbook
On Error GoTo 0 're-enable error reporting
If Not MasterSheet Is Nothing Then Exit For 'if we found the setting worksheet we can exit/stop
Next wb
If Not MasterSheet Is Nothing Then 'test if we found it
Debug.Print MasterSheet.Name
Else
Debug.Print "Settings not found"
End If
End Sub

VBA Macro: Copying worksheets from one Excel file to another

I need help on copying worksheets from one excel workbook to another. Currently, this is my code but it does not run:
Sub Code()
Workbooks.Open Filename:="C:\Users\xxx\Desktop\w1.xlsm"
Sheets (Array("Sheet1", "Sheet2"))
Copy after:=Workbooks("w2.xlsm").Sheets(Sheets.Count)
Workbooks("Client Info Template.xlsm").Close savechanges:=False
End Sub
Instead of Sheets... and Copy ... as two lines, try a single line:
Sheets(Array("Sheet1", "Sheet2")).Copy After:=Workbooks("w2.xlsm").Sheets(Sheets.Count)
This probably still won't work, or at least not reliably, because Sheets.Count may exceed the count of sheets in the destination workbook, so it is better to fully qualify all of your objects:
Sub Code()
Dim w1 as Workbook, w2 as Workbook
Set w1 = Workbooks.Open(Filename:="C:\Users\xxx\Desktop\w1.xlsm")
Set w2 = Workbooks.Open(Filename:="C:\Users\xxx\Desktop\w2.xlsm") '## Modify as needed
w1.Sheets(Array("Sheet1", "Sheet2")).Copy After:=w2.Sheets(w2.Sheets.Count)
End Sub

Excel Macro: Setting a variable for a workbooks location?

I need to write a macro script that will copy data from one xml workbook and paste the values to another workbook. I've written the below macro that works fine, but i need to run this every week for several different documents so it means i have to replace the document name for each run.
Here's what i have so far:
Sub copying()
''''''Section 1''''''
Workbooks("Results_2561").Activate 'workbook i'm copying from
Range("B27:B41").Select
Selection.Copy
Workbooks("Overall_Results").Activate 'workbook i'm pasting to
Range("G2").PasteSpecial
''''''Section 2''''''
Workbooks("Results_2561").Activate
Range("C27:C41").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("C2").PasteSpecial
''''''Section 3''''''
Workbooks("Results_2561").Activate
Range("I28:I40").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("G17").PasteSpecial
''''''Section 4''''''
Workbooks("Results_2561").Activate
Range("J28:J40").Select
Selection.Copy
Workbooks("Overall_Results").Activate
Range("C17").PasteSpecial
End Sub
...
and that's only half the script. Is there a way i can declare a variable at the start and set it as the Workbooks file path so i can call that instead of typing and retyping it over and over again?
Preferably without using something like
Dim book1 as Workbook
Set book1 = Workbooks.Open("C://Results_2561.xlsm")
..as this keeps opening and closing the document when i run the script.
Thanks
since you're only interested in copying values you could use this helper Sub
Sub CopyValues(rngToCopyFrom As Range, rngToCopyTo As Range)
With rngToCopyFrom
rngToCopyTo.Resize(.Rows.COUNT, .Columns.COUNT).Value = .Value
End With
End Sub
to be exploited in your main code like follows:
Sub main()
Dim wsTo As Worksheet
Set wsTo = Workbooks("Overall_Results").ActiveSheet '<--| set the worksheet to paste values to
With Workbooks("Results_2561").ActiveSheet '<--| reference the worksheet to copy values from
CopyValues .Range("B27:B41"), wsTo.Range("G2")
CopyValues .Range("C27:C41"), wsTo.Range("C2")
CopyValues .Range("I28:I40"), wsTo.Range("G17")
CopyValues .Range("J28:J40"), wsTo.Range("C17")
End With
End Sub
should your relevant workbooks have more than one sheet, then just substitute
ActiveSheet
with
Worksheets("myRelevantShetName") '<--|change "myRelevantShetName" to the actual name of the relevant worksheet in each workbook
First of all, you don't have to Activate workbook every time when you want to copy/paste something. Just declare it in Range() property, for example:
''''''Section 1''''''
Workbooks("Results_2561").Sheets(1).Range("B27:B41").Copy
Workbooks("Overall_Results").Sheets(1).Range("G2").PasteSpecial
You can set Workbook as variable like:
Sub copying()
Dim wb1 As Workbook, wb2 As Workbook
Set wb1 = Workbooks("Results_2561")
Set wb2 = Workbooks("Overall_Results")
''''''Section 1''''''
wb1.Sheets(1).Range("B27:B41").Copy
wb2.Sheets(1).Range("G2").PasteSpecial
End Sub
Finally, as #A.S.H suggested, you can add a file dialog where you point which files you want to use. I have put it in some function (don't forget to put it in the same project as your copying macro):
Function strPath() As String
Dim intResult As Integer
Application.FileDialog(msoFileDialogFilePicker).Title = "Select file"
intResult = Application.FileDialog(msoFileDialogFilePicker).Show
If intResult <> 0 Then
strPath = Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
End If
End Function
So your final code for Section 1 would look like:
Sub copying()
Dim wb1 As Workbook, wb2 As Workbook
MsgBox "Show file to copy form."
Set wb1 = Workbooks.Open(strPath())
MsgBox "Show file to paste in."
Set wb2 = Workbooks.Open(strPath())
''''''Section 1''''''
wb1.Sheets(1).Range("B27:B41").Copy
wb2.Sheets(1).Range("G2").PasteSpecial
End Sub

VBA Error 'Subscript out of Range'

I am trying to create a copy of a large macro enabled (xlsm) file in xlsx format.
Sub Button1_Click()
Dim wb As Workbook
Set wb = Workbooks.Open("C:\original.xlsm")
Dim mySheetList() As String
ReDim mySheetList(0 To (ThisWorkbook.Sheets.Count) - 1)
Dim a As Integer
a = 0
For Each ws In ActiveWorkbook.Worksheets
mySheetList(a) = ws.Name
a = a + 1
Next ws
'actually save
Worksheets(mySheetList).Copy
ActiveWorkbook.SaveAs Filename:="ORIGINAL_COPY.xlsx" 'default ext
wb.Close
End Sub
I am getting subscript out of range error at following line:
mySheetList(a) = ws.Name
You are sizing the array with ThisWorkbook.Sheets but the loop use ActiveWorkbook.Worksheets. You need the same reference to avoid issues when multiple workbooks are opened.
You're using 4 different references to workbooks:
wb, ThisWorkbook and ActiveWorkbook are not necessarily the same thing. Furthermore, when you use Worksheets without prefixing it with a workbook reference, you're implicitly referencing the Activeworkbook. And, when you use Worksheets.Copy without any arguments, you're implictly creating a new workbook.
Currently, if ThisWorkbook has fewer sheets than original.xlsm, then your array will not be large enough to accommodate indexes larger than the count of sheets in ThisWorkbook. That is what is causing your out of bounds error.
I've adjusted the code. This will open the XLSM, copy the sheets, save the new XLSX workbook, and close the original XLSM, leaving the new XLSX workbook open.
Sub Button1_Click()
Dim wbOriginal As Workbook
Dim wbOutput As Workbook
Set wbOriginal = Workbooks.Open("C:\original.xlsm")
Dim mySheetList() As String
ReDim mySheetList(0 To (wbOriginal.Sheets.Count) - 1)
Dim a As Integer
a = 0
For Each ws In wbOriginal.Worksheets
mySheetList(a) = ws.Name
a = a + 1
Next ws
'Unfortunately, Worksheets.Copy isn't a function, so it doesn't
'return the workbook that it creates, so we have to execute the
'copy, then find the activeworkbook
Worksheets(mySheetList).Copy
Set wbOutput = ActiveWorkbook
'actually save
wbOutput.SaveAs Filename:="ORIGINAL_COPY.xlsx" 'default ext
wbOriginal.Close
End Sub
Why bother with all that looping?
Sub MM()
Dim sourceWB As Excel.Workbook
Set sourceWB = Workbooks.Open("C:\Original.xlsm")
sourceWB.SaveAs "C:\ORIGINAL_COPY.xlsx", FileFormat:=xlOpenXMLWorkook
sourceWB.Close False '// Optional
End Sub
The .SaveAs() method would be far more effective.
As mentioned in other answers, your issue seems to be with wb, ActiveWorkbook and ThisWorkbook being used interchangeably when they are actually different things.
wb is a workbook object that has been set to "C:\original.xlsm". It will always refer to that workbook unless you close the workbook, empty the object, or assign a new object to it.
ActiveWorkbook refers to the workbook that is currently active in Excel's forefront window. (i.e. The workbook you can see on your screen)
ThisWorkbook refers to the workbook in which the currently executing code belongs to. To quickly explain the difference:
Workbook A is the only workbook open, and has some code in to open another workbook (let's call it Workbook B).
At the moment, Workbook A is the ActiveWorkbook.
The code in workbook A starts running, workbook A is now the ActiveWorkbook and ThisWorkbook (because the running codes resides in this workbook)
The code opens Workbook B, which naturally opens in the forefront of Excel. Now Workbook B is the ActiveWorkbook and Workbook A is still the ThisWorkbook
Hopefully that clears it up a bit for you...

How to select an open Excel file with different file ending name

I have an Excel Macro which look for specific file name Jobs in Lab.xlsx and copy to other macro file.
However, on certain event, the file naming may change to Jobs in Lab (0 - 195).xlsx.
How do I implement Excel Left Syntax into below VBA?
Sub Test()
Windows("Jobs in Lab").Activate
End Sub
You can use the LIKE operator.
Sub Sample()
Dim wb As Workbook
For Each wb In Application.Workbooks
If wb.Name Like "Jobs in Lab*" Then
wb.Activate
Exit Sub
End If
Next wb
End Sub
The code assumes that the file is opened in the same Excel instance.
EDIT:
However if you still want to use LEFT then you can use it like this. Notice the use of Ucase. It converts the text into upper case and then does a comparison. You can use LCASE as well.
Sub Sample()
Dim wb As Workbook
For Each wb In Application.Workbooks
If UCase(Left(wb.Name, 11)) = "JOBS IN LAB" Then
wb.Activate
Exit Sub
End If
Next wb
End Sub