Lets say I want to create 5 workbooks in certain location. I was trying to use this code but it doesn't work. (run-time error, automation error), what is wrong with it?
Sub blabal()
Dim wbk As Workbook
Dim i As Integer
i = 1
Set wbk = Workbook.Add
Do Until i = 5
wbk.SaveAs "C:\Users\User1\Desktop\abc\" & i
wbk.Close
i = i + 1
Loop
End Sub
Set wbk = Workbooks.Add
You need to specify Workbooks instead of Workbook.
Workbooks is a collection object. You're adding a Workbook to the collection of Workbooks.
You also need to change the order of your code, so you're either not closing the workbook each time, or so that you are closing the workbook, but you're then adding a new workbook (which doesn't really make much sense, but I'll show an example anyway).
Set wbk = Workbooks.Add
Do Until i = 5
wbk.SaveAs "C:\Users\User1\Desktop\abc\" & i
i = i + 1
Loop
Or
Do Until i = 5
Set wbk = Workbooks.Add
wbk.SaveAs "F:\" & i
wbk.Close
i = i + 1
Loop
Related
I'm having some issues when working with calling and working with multiple workbooks. I have a macro that updates some excel sheets using some data. All 5 of those spreadsheets are assigned a variable with the filename and the file path. When I run a second SUB / Macri to Save and Close all 5 of those workbooks after they are done updating - It doesn't select the right workbooks even though they've been assigned the same variable names as the previous macro. So I believe my issue is - If the workbooks are already open I can't associate a variable too them. - I assume that if the file name and file path are right, the workbooks open can be set as variables and then be able to close them - Thoughts?
Sub CloseWorkbooks()
Dim MB, WB1, WB2, WB3, WB4, WB5 As Workbook
Dim FP1, FN1, FN2, FN3, FN4, FN5 As String
FP1 = "G:\DATA......"
FN5 = "Book1.xlsx"
FN2 = "Book2.xlsx"
FN3 = "Book3.xlsx"
FN4 = "Book4.xlsx"
FN1 = "Book5.xlsx"
Application.DisplayAlerts = False
Set WB1 = Workbooks.Open(Filename:=FP1 & FN1)
WB1.Activate
WB1.Save
'Application.Wait (Now + TimeValue("00:00:05"))
WB1.Close
Set WB2 = Workbooks.Open(Filename:=FP1 & FN2)
WB2.Activate
WB2.Save
'Application.Wait (Now + TimeValue("00:00:05"))
WB2.Close
Set WB3 = Workbooks.Open(Filename:=FP1 & FN3)
WB3.Activate
WB3.Save
Application.Wait (Now + TimeValue("00:00:02"))
WB3.Close
Set WB4 = Workbooks.Open(Filename:=FP1 & FN4)
WB4.Activate
WB4.Save
Application.Wait (Now + TimeValue("00:00:02"))
WB4.Close
Set WB5 = Workbooks.Open(Filename:=FP1 & FN5)
WB5.Activate
WB5.Save
Application.Wait (Now + TimeValue("00:00:02"))
WB5.Close
End Sub
This works if the worksheets are NOT Open, but it doesn't work if the worksheets are open - which is what I want it to accomplish. The previous macro opens all the worksheets and updates them. I want this macro (2nd one shown above) to save and close all the workbooks.
-Thank you.
If you replace your Workbooks.Open(...) with a call to this it should return the workbook if its open, and open and return it if it is not.
Public Function getWorkbookByFileName(ByVal FileName As String) As Workbook
Dim Book As Workbook: Set Book = Nothing
Dim Count As Integer: Count = Application.Workbooks.Count
Dim Index As Integer: Index = 1
Do
If Application.Workbooks(Index).FullName = FileName Then
Set Book = Application.Workbooks(Index)
Exit Do
End If
If Index < Count Then
Index = Index + 1
Else
Exit Do
End If
Loop
If Book Is Nothing Then
Set Book = Application.Workbooks.Open(FileName:=FileName)
End If
Set getWorkbookByFileName = Book
End Function
This is fairly long winded, looking at some of the answers to Detect whether Excel workbook is already open I see that it can be achieved without looping through the workbooks.
This will close the correct workbook.
Sub CloseWorkbooks()
Application.DisplayAlerts = False
Dim wb As Workbook
Dim i As Long
For i = 1 To 6
Set wb = Workbooks.Open(Filename:="G:\DATA......Book" & i & ".xlsx")
Application.Wait (Now + TimeValue("00:00:02"))
wb.Close SaveChanges:=True
Next i
Exit Sub
I am writing a reporting system where the user fills out a form and a form button runs a macro to save the file with a name based on several fields including a timestamp.
All the data is is also on a second sheet but in one row for ease of copying to a master sheet.
I am trying to to extend the save macro to copy this row to the last line of a second workbook.
This was successful when the macro was run from a separate workbook but I can't for the life of me work out how to do it from within the file itself.
I've triple checked the paths themselves, I know they're right as the new files are being created, I've run msgbox in the code to check the filename and the variable are the same too.
timestampedfile = Worksheets("single_line").Range("b3")
totalpath = Path & timestampedfile & ".xlsm"
ActiveWorkbook.SaveCopyAs filename:=totalpath
master_wb = "s:\blah\blah\blah.xlsx"
master_sht = "Master_Database"
contact_wb = totalpath
contact_sht = "single_line"
Workbooks.Open (master_wb)
Workbooks.Open (contact_wb)
MsgBox (totalpath)
Workbooks(contact_wb).Worksheets(contact_sht).Range("A3:AQ3").Copy Worksheets(master_wb).Sheets(master_sht).Range("A" & Rows.Count).End(xlUp)(2)
'
Both the Workbooks open so I know the paths are right, can anyone help?
Solution by OP
Solved thanks to comment about workbook variables by BigBen:
Use workbook variables, instead of referencing the workbook by name: Dim masterWb as Workbook, then Set masterWb = Workbooks.Open("s:\blah\blah\blah.xlsx" ). Similarly for the contact workbook. You might consider using worksheet variables too, instead of using sheet names.
Code changed to:
Dim master_wb As Workbook
Dim contact_wb As Workbook
Dim master_sht As Worksheet
Dim contact_sht As Worksheet
Path = "S:\blah\" & Worksheets("report").Range("c8") & "\"
filename = Worksheets("back_end_formulas").Range("e10")
timestampedfile = Worksheets("single_line").Range("b3")
totalpath = Path & timestampedfile & ".xlsm"
ActiveWorkbook.SaveCopyAs filename:=totalpath
SetAttr totalpath, vbReadOnly
Set master_wb = Workbooks.Open("S:\blah\Master_Database2.xlsx")
Set master_sht = master_wb.Sheets("Master_Database")
Set contact_wb = Workbooks.Open(totalpath)
Set contact_sht = contact_wb.Sheets("single_line")
ThisWorkbook.Activate
contact_sht.Range("A3:AQ3").Copy master_sht.Range("A" & Rows.Count).End(xlUp)(2)
master_wb.Close SaveChanges:=True
contact_wb.Close SaveChanges:=False
ActiveWorkbook.Close SaveChanges:=False
I'm currently writing a macro that will allow you to select a folder, set bounds, and then loop through some numbers to read in all of a certain file type. (Excel in this instance.)
You can see that right here
Dim StringP1 As String
Dim iterator As Integer
Dim StringP2 As String
Dim i As Integer
Dim final As Integer
'number of files
final = 5
'main folder
StringP1 = " FOLDER NAME "
StringP2 = ".xls"
i = 1
While i < final
iterator = 1
FileName = StringP1 & iterator & StringP2
Call attempt1(FileName)
Call attempt2(FileName)
i = (i + 1)
iterator = (iterator + 1)
Wend
when it loads into my subs it uses this code
Sub attempt1(FN As String)
Dim Excel As New Excel.Application
Dim FileName As String
Set XL = CreateObject("Excel.Application")
Set MyRec = CurrentDb.OpenRecordset("Infor")
Excel.Workbooks.Open (FN)
Then it goes through some code, and eventually ends up exiting the subroutine.
Everything I've tried seems to fail.
I've been messing with this for a few hours, using various things I've found from Stackoverflow and other VBA sites, but nothing seems to work.
I've tried using
excel.workbooks.close savechanges:=false
workbook.close
workbooks.close
.
.
.
I'm curious if anyone knows a good way to exit all of these EXCEL.EXE that open?
If I understand correctly you are trying to close all workbooks (Excel files).
Proper way to close single workbook by its name:
XL.Workbooks("filename.xls").Close Savechanges:=False
If you have many workbooks to close you may use a cycle like this:
Public Sub WorkWithExcel()
Dim XL As New Excel.Application, WB As Excel.Workbook
' Open Excel file:
XL.Workbooks.Open ("my_file.xls")
' Open another Excel file
XL.Workbooks.Open ("another my file.xls")
' do some work with this files
' ...
' For every file in our application:
For Each WB In XL.Workbooks
' Close file without saving changes:
WB.Close savechanges:=False
Next WB
' Close Excel applicatioin:
XL.Quit
' Clear object:
Set XL = Nothing
End Sub
I am creating a function that reads column titles from two excel files and then place those column titles in checkboxes so the user can check which columns he will work with. It works when I do it with one file but when I modify it to work with two files I get the "run time error 9: Subscript out of range" and highlights the line => Set wks2 = ActiveWorkbook.Worksheets(SheetName2).
Even with this error message still works for the first file but it does not work with the second file. Can anybody help me to find the reason of this error message? Thank you very much in advance.
Function CallFunction(SheetName1 As Variant, SheetName2 As Variant) As Long
' This is a function used to retrieve column titles and place them as checkboxes in a listBox
Dim jTitles(200) As String
Dim sTitles(200) As String
Dim titless As Integer
Dim titlesj As Integer
Dim wks1 As Worksheet
Dim wks2 As Worksheet
Dim Item(200) As String
SPathName = Range("F18").Value
SFilename = Range("F19").Value
JPathName = Range("F22").Value
JFilename = Range("F23").Value
Workbooks.Open Filename:=SPathName & "\" & SFilename
Workbooks.Open Filename:=JPathName & "\" & JFilename
Set wks1 = ActiveWorkbook.Worksheets(SheetName1)
For j = 1 To 199
If Trim(wks1.Cells(4, j).Value) = "" Then
titlesj = j - 1
Exit For
End If
jTitles(j - 1) = wks1.Cells(4, j).Value
Next
j = 1
' Add column titles from files into the listbox as checkboxes
For j = 0 To titlesj
Sheet1.ListBox1.AddItem jTitles(j)
Sheet1.ListBox3.AddItem jTitles(j)
Next
Set wks2 = ActiveWorkbook.Worksheets(SheetName2) ' <=== HERE POPS THE ERROR MESSAGE
For s = 1 To 199
If Trim(wks2.Cells(1, s).Value) = "" Then
titless = s - 1
Exit For
End If
sTitles(s - 1) = wks2.Cells(1, j).Value
Next
s = 1
For s = 0 To titless
Sheet1.ListBox2.AddItem sTitles(s)
Sheet1.ListBox4.AddItem sTitles(s)
Next
Workbooks(JFilename).Close
' Workbooks(SFilename).Close
End Function
Subscript out of Range error arises in these circumstances when the specified sheetname does not exist in that workbooks Worksheets collection.
I notice you have two open workbooks specified by:
Workbooks.Open Filename:=SPathName & "\" & SFilename
Workbooks.Open Filename:=JPathName & "\" & JFilename
However, both of your worksheet assignments refer only to the ActiveWorkbook.
The cause of the error is certainly that SheetName2 does not exist in the ActiveWorkbok (which is specified by JFilename)
Especially when working with multiple books or worksheets, it is always preferable to avoid using Activate/Select methods-- otherwise you need to keep track of which workbook/worksheet/etc. is "Active", and that makes for spaghetti code and lots of unnecessary calls to the .Activate method.
I know that SheetName1 exists in JFilename, and I am assuming that SheetName2 exist in the workbook SFileName.
Instead, define two Workbook variables:
Dim wb1 as Workbook
Dim wb2 as Workbook
Assign the results of the Workbooks.Open method to these workbooks:
Set wb2 = Workbooks.Open(Filename:=SPathName & "\" & SFilename)
Set wb1 = Workbooks.Open(Filename:=JPathName & "\" & JFilename)
Now, wb1 is the "Active" workbook, so with the worksheet assignments:
Set wks1 = wb1.Worksheets(SheetName1)
And later for the Sheetname2:
Set wks2 = wb2.Worksheets(Sheetname2)
Otherwise, there is a typo in your worksheet names or the string parameters you're sending to this function. Doublecheck/debug that the value of SheetName2 is correct and that it exists.
I want to collect data from different files and insert it into a workbook doing something like this.
Do While THAT_DIFFERENT_FILE_SOMEWHERE_ON_MY_HDD.Cells(Rand, 1).Value <> "" And Rand < 65536
then 'I will search if the last row in my main worksheet is in this file...
End Loop
If the last row from my main worksheet is in the file, I'll quit the While Loop. If not, I'll copy everything. I'm having trouble finding the right algorithm for this.
My problem is that I don't know how to access different workbooks.
The best (and easiest) way to copy data from a workbook to another is to use the object model of Excel.
Option Explicit
Sub test()
Dim wb As Workbook, wb2 As Workbook
Dim ws As Worksheet
Dim vFile As Variant
'Set source workbook
Set wb = ActiveWorkbook
'Open the target workbook
vFile = Application.GetOpenFilename("Excel-files,*.xls", _
1, "Select One File To Open", , False)
'if the user didn't select a file, exit sub
If TypeName(vFile) = "Boolean" Then Exit Sub
Workbooks.Open vFile
'Set targetworkbook
Set wb2 = ActiveWorkbook
'For instance, copy data from a range in the first workbook to another range in the other workbook
wb2.Worksheets("Sheet2").Range("C3:D4").Value = wb.Worksheets("Sheet1").Range("A1:B2").Value
End Sub
You might like the function GetInfoFromClosedFile()
Edit: Since the above link does not seem to work anymore, I am adding alternate link 1 and alternate link 2 + code:
Private Function GetInfoFromClosedFile(ByVal wbPath As String, _
wbName As String, wsName As String, cellRef As String) As Variant
Dim arg As String
GetInfoFromClosedFile = ""
If Right(wbPath, 1) <> "" Then wbPath = wbPath & ""
If Dir(wbPath & "" & wbName) = "" Then Exit Function
arg = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
On Error Resume Next
GetInfoFromClosedFile = ExecuteExcel4Macro(arg)
End Function
Are you looking for the syntax to open them:
Dim wkbk As Workbook
Set wkbk = Workbooks.Open("C:\MyDirectory\mysheet.xlsx")
Then, you can use wkbk.Sheets(1).Range("3:3") (or whatever you need)
There's very little reason not to open multiple workbooks in Excel. Key lines of code are:
Application.EnableEvents = False
Application.ScreenUpdating = False
...then you won't see anything whilst the code runs, and no code will run that is associated with the opening of the second workbook. Then there are...
Application.DisplayAlerts = False
Application.Calculation = xlManual
...so as to stop you getting pop-up messages associated with the content of the second file, and to avoid any slow re-calculations. Ensure you set back to True/xlAutomatic at end of your programming
If opening the second workbook is not going to cause performance issues, you may as well do it. In fact, having the second workbook open will make it very beneficial when attempting to debug your code if some of the secondary files do not conform to the expected format
Here is some expert guidance on using multiple Excel files that gives an overview of the different methods available for referencing data
An extension question would be how to cycle through multiple files contained in the same folder. You can use the Windows folder picker using:
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
If .Selected.Items.Count = 1 the InputFolder = .SelectedItems(1)
End With
FName = VBA.Dir(InputFolder)
Do While FName <> ""
'''Do function here
FName = VBA.Dir()
Loop
Hopefully some of the above will be of use
I had the same question but applying the provided solutions changed the file to write in. Once I selected the new excel file, I was also writing in that file and not in my original file. My solution for this issue is below:
Sub GetData()
Dim excelapp As Application
Dim source As Workbook
Dim srcSH1 As Worksheet
Dim sh As Worksheet
Dim path As String
Dim nmr As Long
Dim i As Long
nmr = 20
Set excelapp = New Application
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
.Show
path = .SelectedItems.Item(1)
End With
Set source = excelapp.Workbooks.Open(path)
Set srcSH1 = source.Worksheets("Sheet1")
Set sh = Sheets("Sheet1")
For i = 1 To nmr
sh.Cells(i, "A").Value = srcSH1.Cells(i, "A").Value
Next i
End Sub
With excelapp a new application will be called. The with block sets the path for the external file. Finally, I set the external Workbook with source and srcSH1 as a Worksheet within the external sheet.