Error selecting range cells to copy from multiple work books - vba

Updated in response to comment from dwirony:
I am trying to create a code that copies information from the same cells in multiple workbooks and combines the information into a single summary workbook. The code below works as written, however, if I add more cell address to the sourceRange (starting on line 69) the macro still runs but no information is copied into the new summary workbook.
Original Question:
I am trying to select the same specific cells from multiple worksheets within a single folder and combine them into a master spreadsheet. The code works up to a certain number of cells, but if I try to include any more, the macro returns a blank workbook (except for the column headings I've assigned). Cells that work initially will won't work if there are too many selected cells. i.e., in the code shown below, cell J2 is the first and the last cell called and the program runs. If I add J2 again, (range ends ...J2, J2")or any other cell, it appears that I've hit a limit somewhere and I get a blank workbook.
I have zero previous experience with VBA and macros, and everything I've put together comes from a variety of internet and internal sources. Maybe the multiple sources are the source of the error?
Any help would be greatly appreciated!
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
Dim a As Range, c As Range
Dim x As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Users\amiller\OneDrive - CoorsTek\temp"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xls*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(1)
Set sourceRange = .Range("J2, C2, D7, F7, K7, G10, J10, G11, J11, G12, J12, G14, J14, G15, J15, G16, J16, G17, J17, J21," _
& "J2, D24, E24, G24, I24, J24, O24, P24, Q24, R24, S24, D25, E25, G25, I25, J25, O25, P25, Q25, R25, S25," _
& "D26, E26, G26, I26, J26, O26, P26, Q26, R26, S26, D27, J2")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
With sourceRange
BaseWks.Cells(rnum + 1, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("B" & rnum + 1)
x = 0
For Each a In sourceRange.Areas
For Each c In a.Cells
x = x + 1
destrange.Offset(0, x - 1).Value = c.Value
Next c
Next a
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub

Related

I am trying to have this macro include the ability to copy data from multiple worksheets in a workbook but it will only copy from the first worksheet [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
This is my data below.
The code works just doesn't fit my requirements. I need to add the functionality that will allow me to pull data from multiple worksheets in 1 workbook but currently it will only pull the data from 1 worksheet in 1 workbook.
I've included the code to go through different worksheets but as of now the code will only extract data from 1 worksheet in 1 workbook.
Any help is greatly appreciated. Thanks!
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Users\mp180423\Desktop\Gas"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
Dim ws As Worksheet
For Each ws In Worksheets
ws.Activate
Debug.Print ws.Name
Next
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(3)
Set sourceRange = .Range("A15:B20")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
For Each ws In Worksheets
ws.Activate
Debug.Print ws.Name
Next
With sourceRange
BaseWks.Cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("B" & rnum)
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
Range("B1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$C$66").AutoFilter Field:=2, Criteria1:= _
"Kilowatt hours used Current period"
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
MsgBox ("Merge Completed.")
End Sub
I expect that the single worksheet from the single workbook which this code was correctly working for, would be the only workbook with at least 3 worksheets.
When selecting the range you have:
With mybook.Worksheets(3)
Set sourceRange = .Range("A15:B20")
End With
Note that this restricts the data to the range from only the 3rd (third) worksheet from every workbook.
Also note that on the line prior, you have:
On Error Resume Next
This would effectively mask the errors coming from attempting to extract data from all the non-existing 3rd worksheets. For the workbook with at least 3 worksheets, since the With mybook.Worksheets(3) is hard-coded into your code, this was the only worksheet the data was pulled from.
(And the reason it wasn't duplicated for each worksheet in that workbook, is because the cycles through the worksheets were restricted to the Debug.Print lines. The code for the data-moving only cycled through once for each workbook)
Below, you will see three (3) sections:
Change Details.
This is to help high-light the changes I made to your code so that it cycles through the data-moving for each worksheet, pulling once from each worksheet.
Corrected
This is for ease of copy/pasting the code
Original
This is to maintain a copy of the original code I based my answer off of (in case of changes).
Change Details
From original:
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
Dim ws As Worksheet
For Each ws In Worksheets
ws.Activate
Debug.Print ws.Name
Next
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(3)
Set sourceRange = .Range("A15:B20")
End With
Changed to:
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
Dim ws As Worksheet
If Not mybook Is Nothing Then
For Each ws In Worksheets
On Error Resume Next
' Change this range to fit your own needs.
With ws
Set sourceRange = .Range("A15:B20")
End With
Top-half:
Although I kept the Dim ws As Worksheet, I removed the Debug.Print cycle through all worksheets, as it had no effect on any other code.
Lower-half:
Added a For Each ws In Worksheets around the functional code (which required adding Next ws above mybook.Close savechanges:=False), and shifted the with statement from With mybook.Worksheets(3) to With ws
Since there was another extraneous Debug.Print cycle right before the file name was added to column A, I replaced it with Debug.Print ws.Name & ": #" & FNum to be a bit more informative.
Corrected
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Users\mp180423\Desktop\Gas"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
' Added cycle through worksheets
Dim ws As Worksheet
If Not mybook Is Nothing Then
For Each ws In Worksheets
On Error Resume Next
' Change this range to fit your own needs.
' Shifted reference to current worksheet-of-interest
With ws
Set sourceRange = .Range("A15:B20")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Prints file name and index number in immediate window.
Debug.Print ws.Name & ": #" & FNum
' Copy the file name in column A.
With sourceRange
BaseWks.Cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("B" & rnum)
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
'Cycles through next worksheet-of-interest
Next ws
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
Range("B1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$C$66").AutoFilter Field:=2, Criteria1:= _
"Kilowatt hours used Current period"
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
MsgBox ("Merge Completed.")
End Sub
Original
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Users\mp180423\Desktop\Gas"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
Dim ws As Worksheet
For Each ws In Worksheets
ws.Activate
Debug.Print ws.Name
Next
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(3)
Set sourceRange = .Range("A15:B20")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
For Each ws In Worksheets
ws.Activate
Debug.Print ws.Name
Next
With sourceRange
BaseWks.Cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("B" & rnum)
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
Range("B1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$C$66").AutoFilter Field:=2, Criteria1:= _
"Kilowatt hours used Current period"
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
MsgBox ("Merge Completed.")
End Sub

Link Value In Unopened/Closed Excel Workbook File

I have list of Excel in same format with different date entry! About 100 excel files, which have different titles. I need to build one master table where I would need to reference some cells from the template used and do some analysis in my master table.
Anyhow, I tried to use the tutorial "How To Reference Or Link Value In Unopened/Closed Excel Workbook File?" to do that and it works fine for closed worksheet!
However, I could not figure way in how to use this tutorial and change the File path dynamically?
Note:
All files in the same folder and every excel sheet have its code and title example: Meal Code-Title.All files have the same structure.
Every Excel have General information in the sheet1, example (Meal Title, Time to prepare,cost, profit, Number of likes, and Number of dislike).The excel sheet have 4 sheets which am not interested on.
I don’t want to merge all files into one file "workbook".I need to have one master excel which do analysis base on the data in the 100 files from Sheet1 (without opening the files).
Here how I did it using index :
=INDEX('D:\Meals[100-Pasta.xlsx]Sheet1'!$B:B,3,1)
Here the formula
Why do the workbooks have to stay closed? You can easily import data from all workbooks in a folder, into a mater file, which contains everything.
Sub Basic_Example_1()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, Fnum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
'Fill in the path\folder where the files are
MyPath = "C:\Users\Ron\test"
'Add a slash at the end if the user forget it
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
'If there are no Excel files in the folder exit the sub
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
'Fill the array(myFiles)with the list of Excel files in the folder
Fnum = 0
Do While FilesInPath <> ""
Fnum = Fnum + 1
ReDim Preserve MyFiles(1 To Fnum)
MyFiles(Fnum) = FilesInPath
FilesInPath = Dir()
Loop
'Change ScreenUpdating, Calculation and EnableEvents
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
'Add a new workbook with one sheet
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
'Loop through all files in the array(myFiles)
If Fnum > 0 Then
For Fnum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(Fnum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
With mybook.Worksheets(1)
Set sourceRange = .Range("A1:C1")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
'if SourceRange use all columns then skip this file
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "Sorry there are not enough rows in the sheet"
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
'Copy the file name in column A
With sourceRange
BaseWks.cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(Fnum)
End With
'Set the destrange
Set destrange = BaseWks.Range("B" & rnum)
'we copy the values from the sourceRange to the destrange
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next Fnum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
'Restore ScreenUpdating, Calculation and EnableEvents
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
You may also want to consider using the AddIn from the link below.
https://www.rondebruin.nl/win/addins/rdbmerge.htm
My answer is untested, as am on mobile. It wasn't clear to me whether you had an existing list of the 100 Excel files, with codes and meals for each one, somewhere (your Master Table image shows only one row/file) -- or whether you wanted to look up all the files.
Code below attempts to look up the files.
Option Explicit
Sub InsertExternalReferences()
' Change if/as needed to the folder of the 100 Excel files. '
Const FOLDER_PATH as string = "D:\Meals"
Dim Filename as string
Filename = dir$(folder_path &"\*-*.xlsx" , vbnormal)
Dim Index as long
Dim FileIndex as long
' Change this line to the name of the sheet that contains the MasterTable -- else you'll get an error. '
With thisworkbook.worksheets("MasterTable")
Do until Len(filename) = 0
FileIndex = FileIndex + 1
' To me, does not make sense to use the INDEX function. It would make sense if you were looking up the value dynamically with a combination of INDEX and MATCH, but you do not appear to be. You may as well just give the cell reference if structure throughout 100 workbooks is not going to change. '
' Reading rows 2 to 8 on each Sheet1'
For Index = 2 to 8
'Index+2 below means we start writing from column 4 (AKA column D).'
'5+ below means we are skipping the first 5 rows on the MasterTable sheet and begin writing from the sixth row. Change it to however many rows you need to skip.'
.cells(5+FileIndex,Index+2).formula = "='" & folder_path & "[" & filename & "]Sheet1'!B" & cstr(Index)
Next index
Filename = dir$()
Loop
End with
End sub
If I have misunderstood, let me know.

VBA to Import Excel data from from sub-Folders too - Consolidated Excel File

It's my first in using VBA, excuse my rustiness.
My Situation: I have a master excel (2010) file to which I need to import excel files from a folder. The existing code works almost fine but does not look into the sub-folders. Along with below important requirements. Please help!
Desired Output:
The code should not create a new excel sheet, instead import the data into the same master excel file that the code sits in.
Currently, the code fetches excel files only from the parent folder. I need it to look into any sub-folders with excel files in them too
The current code changes the destination files format, I would like to keep the destination format as is.
Should not copy empty rows from the defined range
Existing code (From MSDN: Ron de Bruin)
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Users\zatin.dharmapuri\Desktop\Reviews"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(1)
Set sourceRange = .Range("B2:G50")
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name.
With sourceRange
BaseWks.Cells(rnum, "L"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("A" & rnum)
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
There are several ways to do this. Probably the easiest is to use Ron deBruin's AddIn.
http://www.rondebruin.nl/win/addins/rdbmerge.htm
Check the box that says 'Include Sub Folders'.

Selecting a range on merged workbooks

I also need to change the "destination" of the merged data to be pasted starting on cell row 4.The code I found in Microsoft.com (with a little modification thanks to the answer below) is as follow
Sub Button1_Click()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Documents and Settings\laragon2\Desktop\Week's Routers"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = ThisWorkbook.Sheets("Routers")
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(1)
Set sourceRange = .Range("A4", .Range("E700").End(xlUp))
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
With sourceRange
BaseWks.Cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("b4")
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
The source range is being set in the line immediately after: ' Change this range to fit your own needs. It looks like this:
Set sourceRange = .Range("A1:C1")
The destination is being set in the line immediately after the comment indicating: ' Set the destination range. It looks like this:
Set destrange = BaseWks.Range("B" & rnum)
EDIT Here is an example. Create an empty workbook. Put some values in cells A1:A5 on sheet 1. The do this:
Sub CopyRangeToRange()
Dim sourceRange As Range
Dim destRange As Range
Set sourceRange = Range("A1:A5")
Set destRange = Sheets(2).Range("A1")
With sourceRange
Set destRange = destRange.Resize( _
.Rows.Count, .Columns.Count)
End With
Sheets(2).Activate
destRange.Activate
destRange.Value = sourceRange.Value
End Sub
This is the exact same method I propose above. If this works, but the macro you are writing does not work, you need to debug where it is going wrong, because the method is the same.
EDIT #2
After trying this on your workbook, I think this is what you're after. I believe I commented all of my changes, which you can find by the '## comments. Almost all of the changes applied within the With sourcerange block. I also changed the initial value of rnum to 4, since that seems to be where the data should begin being pasted in the Routers worksheet, and modified the way rnum increments for each file in the loop.
Sub Button1_Click()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long, mybook As Workbook
Dim BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\Documents and Settings\laragon2\Desktop\Week's Routers"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Set the destination worksheet:'
Set BaseWks = ThisWorkbook.Sheets("Routers")
'## set rnum to 4 because we begin pasting data in row 4... ##'
rnum = 4
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(1)
Set sourceRange = .Range("A4", .Range("E4:E700").End(xlUp)) '## changed dz ##'
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
BaseWks.Activate
With sourceRange
''## changed to make this range the same number of rows as sourceRange ##'
BaseWks.Cells(rnum, 1). _
Resize(.Rows.Count).Value = MyFiles(FNum)
'## moved this code and changed to begin at the last non-blank row in column A, but use column B ##'
'## resize the destrange to the same dimensions as sourcerange ##'
Set destrange = BaseWks.Cells(rnum, 1). _
Resize(.Rows.Count, .Columns.Count).Offset(, 1)
'## Insert the source values in the destination range ##'
destRange.Value = .Value
'## increment rnum to the next appropriate value ##'
rnum = rnum + .Rows.Count
End With
'## Removed as redundant
'With sourceRange
' Set destrange = destrange. _
' Resize(.Rows.Count, .Columns.Count)
'End With
' Copy the values from the source range
' to the destination range.
'## This has been moved to above. ##
' destrange.Value = sourceRange.Value
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub

How to append data to existing workbook's sheet and don't create a new workbook

I am trying to work out what I need to change in the following VBA code to append the data at the bottom of data that already exists in a workbook named "Main" and a worksheet named "summary":
Sub MergeAllWorkbooks()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim mybook As Workbook, BaseWks As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
' Change this to the path\folder location of your files.
MyPath = "C:\test\"
' Add a slash at the end of the path if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
FilesInPath = Dir(MyPath & "*.xl*")
If FilesInPath = "" Then
MsgBox "No files found"
Exit Sub
End If
' Fill the myFiles array with the list of Excel files
' in the search folder.
FNum = 0
Do While FilesInPath <> ""
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
FilesInPath = Dir()
Loop
FNum = FNum - 1
' Set various application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
If FNum > 0 Then
For FNum = LBound(MyFiles) To UBound(MyFiles)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(MyPath & MyFiles(FNum))
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
' Change this range to fit your own needs.
With mybook.Worksheets(1)
Set sourceRange = .Range("A2:T" & CStr(mybook.Worksheets(1).Range("A2").CurrentRegion.Rows.Count))
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If source range uses all columns then
' skip this file.
If sourceRange.Columns.Count >= BaseWks.Columns.Count Then
Set sourceRange = Nothing
End If
End If
On Error GoTo 0
If Not sourceRange Is Nothing Then
SourceRcount = sourceRange.Rows.Count
If rnum + SourceRcount >= BaseWks.Rows.Count Then
MsgBox "There are not enough rows in the target worksheet."
BaseWks.Columns.AutoFit
mybook.Close savechanges:=False
GoTo ExitTheSub
Else
' Copy the file name in column A.
With sourceRange
BaseWks.Cells(rnum, "A"). _
Resize(.Rows.Count).Value = MyFiles(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("B" & rnum)
' Copy the values from the source range
' to the destination range.
With sourceRange
Set destrange = destrange. _
Resize(.Rows.Count, .Columns.Count)
End With
destrange.Value = sourceRange.Value
rnum = rnum + SourceRcount
End If
End If
mybook.Close savechanges:=False
End If
Next FNum
BaseWks.Columns.AutoFit
End If
ExitTheSub:
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
Thank you
I do not like this code. There is lots I object to but I am most unhappy about the use of error handling:
The error handling functionality is there to allow your routine to fail gracefully when something goes wrong. It is not there to allow you to ignore errors and carry on as though they did not happen.
The error handling failed to handle a problem with one of my workbooks. I have not investigated but I suspect the problem is either the length of a single cell or the total length of the data being transferred by destrange.Value = sourceRange.Value.
However, you ask how to make a single change so I will limit myself to that.
I suggest the easiest approach would be to create workbook "Main" with worksheet "Summary" and to include your macro in it.
Add new statements under the Dim statements:
Dim rnum As Long, CalcMode As Long
'### Start of new code
If Workbooks.Count > 1 Then
' It is easy to get into a muddle if there are multiple workbooks
' open at the start of a macro like this. Avoid the problem until
' you understand it.
Call MsgBox("Please close all other workbooks", vbOKOnly)
Exit Sub
End If
Set BaseWks = ActiveWorkBook.Worksheets("Summary")
With BaseWks
rnum = .Cells(Rows.Count, "A").End(xlUp).Row + 1
End With
'### End of new code
' Change this to the path\folder location of your files.
The first block of the above code ensures there are no other workbooks open.
The second block (1) sets BaseWks to worksheet "Summary" and (2) sets rnum to the first unused row in "Summary". End(xlUp) is the VBA equivalent of clicking Ctrl+Up. So I have gone to the bottom of column A, gone up until I hit a row with a value and then down 1 row.
Replace the loop that locates the filenames with:
Do While FilesInPath <> ""
If FilesInPath <> ActiveWorkbook.Name Then
FNum = FNum + 1
ReDim Preserve MyFiles(1 To FNum)
MyFiles(FNum) = FilesInPath
End If
FilesInPath = Dir()
Loop
I assume that workbook "Main" will be in the same folder as the other workbooks. This change ensures that "Main" is not used as a source.
Discard these statements:
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
because I have already set BaseWks and rnum to the values I require.
If you want to save the updated workbook "Main" automatically, add the following statement above ExitTheSub::
ActiveWorkbook.Save