Create separate row for each item when merging multiple workbooks - vba

I have several hundred spreadsheets that I would like to combine into a single master sheet. Each spreadsheet contains general description information in several sells, and then a list of parts with columns of information that are specific to each part, as shown:
In the master sheet, I want a separate line for each part that includes the general information as well as the specific part information, as shown:
I have created a loop that pulls all the information I want, but all the information is written as a single line in the master sheet, as shown:
Can anyone tell me how to create a separate line for each item? The code I have pieced together is shown- I think the solution to my problem lies in how to format the section titled "change this range to fit your own needs"
Sub MergeNT154BatchCards()
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 dt As String
Dim bookName As String
Dim rnum As Long, CalcMode As Long
Dim a As Range, c As Range
Dim x As Long
Dim sourceRange As Range, destrange As Range
' 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)
ActiveSheet.Name = "Density"
bookName = "DensitySummary"
dt = Format(CStr(Now), "yyyy_mm_dd_hh.mm")
BaseWks.SaveAs Filename:="C:\Users\amiller\OneDrive - CoorsTek\temp\" & bookName & dt
rnum = 1
Range("A1").Value = "FileName"
Range("B1").Value = "Description"
Range("C1").Value = "WaterTemp(C)"
Range("D1").Value = "WaterDensity(g/cc)"
Range("E1").Value = "PartID"
Range("F1").Value = "DryMass(g)"
Range("G1").Value = "SuspendedMass(g)"
Range("H1").Value = "Density(g/cc)"
' 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 R1 = Range("A11, A5, B5")
Set R2 = Range("A13:D" & Range("A13").End(xlDown).Row)
Set RF = Union(R1, R2)
Set sourceRange = RF
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

I'm slightly worried because the headings you seem to be writing to the master sheet don't seem to line up with the data, and because you seem to be only copying Range("A11, A5, B5") from the top part of each sheet but your images show 5 fields being taken from the top, but I think you can replace your For FNum loop with the following:
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
With mybook.Worksheets(1)
Set SourceRange = .Range("A13:D" & .Range("A13").End(xlDown).Row)
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.Cells(rnum + 1, "A").Resize(SourceRcount).Value = MyFiles(FNum)
' Copy information such as date/time started, start/final temp, and Batch ID
BaseWks.Cells(rnum + 1, "B").Resize(SourceRcount).Value = .Range("A4").Value
BaseWks.Cells(rnum + 1, "C").Resize(SourceRcount).Value = .Range("B4").Value
BaseWks.Cells(rnum + 1, "D").Resize(SourceRcount).Value = .Range("A5").Value
BaseWks.Cells(rnum + 1, "E").Resize(SourceRcount).Value = .Range("A5").Value
BaseWks.Cells(rnum + 1, "F").Resize(SourceRcount).Value = .Range("A11").Value
'Copy main data
BaseWks.Cells(rnum + 1, "G").Resize(SourceRcount, SourceRange.Columns.Count).Value = SourceRange.Value
rnum = rnum + SourceRcount
End If
End With
End If
mybook.Close savechanges:=False
Next FNum

The root of your problem is that you are trying to do too much in a single subroutine. Whenever your subroutines are over 25-40 lines, you should consider extracting functionality into smaller subroutines. In this way, you will be able to test smaller portions of code at a time.
By implementing this strategy, I managed to reduce the OPs original subroutine from 152 lines of code to 5 easy to debug subroutines with 80 lines of code.
MergeNT154BatchCards - Main subroutine
AddBatchCard - Opens a Workbook and adds new rows of data to a range
getDensityTemplate - Creates a new Workbook based off a template
getFileList - Gets a list of file from a directory
ToggleEvents - Turns off and on events and returns the current Calculation mode
I haven't tested some parts of the code and as #YowE3K stated the headers don't line up. I would think that it will be fairly easy to modify the code to fit the OPs requirement using these smaller blocks of code.
Public Sub MergeNT154BatchCards()
Dim vFiles As Variant, FileFullName As Variant
Dim NextRow As Range, wb As Workbook
Dim CalculationMode As XlCalculation
CalculationMode = ToggleEvents(False, xlCalculationManual)
vFiles = getFileList("C:\Users\best buy\Downloads\stackoverfow", "*.xls*")
If UBound(vFiles) = -1 Then
MsgBox "No files found", vbInformation, ""
Exit Sub
End If
Set wb = getDensityTemplate
For Each FileFullName In vFiles
With wb.Worksheets(1)
'Add Header
.Range("A1:H1").Value = Array("FileName", "Description", "WaterTemp(C)", "WaterDensity(g/cc)", "PartID", "DryMass(g)", "SuspendedMass(g)", "Density(g/cc)")
'Target the next empty row
Set NextRow = .Range("A" & .Rows.Count).End(xlUp).Offset(1)
AddBatchCard CStr(FileFullName), NextRow
End With
Next
ToggleEvents True, CalculationMode
End Sub
Private Sub AddBatchCard(FileFullName As String, NextRow As Range)
Dim cell As Range
Dim x As Long, y As Long
With Workbooks.Open(FileFullName)
With .Worksheets(1)
For Each cell In .Range("A13", .Range("A" & .Rows.Count).End(xlUp)).Value
'NextRow
NextRow.Cells(1, 1).Value = .Range("A4").Value
NextRow.Cells(1, 2).Value = .Range("B4").Value
NextRow.Cells(1, 3).Value = .Range("A5").Value
NextRow.Cells(1, 4).Value = .Range("B5").Value
NextRow.Cells(1, 4).Resize(1, 4).Value = cell.Resize(1, 4).Value
Set NextRow = NextRow.Offset(1)
Next
End With
.Close SaveChanges:=False
End With
End Sub
Private Function getDensityTemplate(FilePath As String) As Workbook
Dim SheetsInNewWorkbook As Integer
Dim wb As Workbook
SheetsInNewWorkbook = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
Set wb = Workbooks.Add(xlWBATWorksheet)
wb.Worksheets(1).Name = "Density"
wb.SaveAs FileName:=FilePath & "DensitySummary" & Format(Now, "yyyy_mm_dd_hh.mm")
Set getDensityTemplate = wb
End Function
Private Function getFileList(FilePath As String, PatternSearch As String) As Variant
Dim FileName As String
If Right(FilePath, 1) <> "\" Then FilePath = FilePath & "\"
With CreateObject("System.Collections.ArrayList")
FileName = Dir(FilePath & PatternSearch)
Do While FileName <> ""
.Add FilePath & FileName
FileName = Dir()
Loop
getFileList = .ToArray
End With
End Function
Private Function ToggleEvents(EnabelEvents As Boolean, CalculationMode As XlCalculation) As XlCalculation
With Application
ToggleEvents = .Calculation
.Calculation = CalculationMode
.ScreenUpdating = EnabelEvents
.EnableEvents = EnabelEvents
End With
End Function

Related

Error selecting range cells to copy from multiple work books

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

How to copy multiple files in a folder into a single spreadsheet?

I just started using excel macros. My problem is that I have 500 excel files in a folder. I am looking for a way to copy the first and second column of each of these 500 files into a single spreadsheet. Is this something that can be done using the excel VBA. Any help is appreciated. Please see the VBA code I recorded. How can I modify this to achieve my objective?
Sub Macro1()
'
' Macro1 Macro
'
'
ActiveCell.Range("A1:B1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Windows("Book1").Activate
ActiveSheet.Paste
End Sub
Please read my comments within the code.
You have to correct your path(addresses), folder names and file names.
Option Explicit
Sub LoopAllFiles()
Dim myCalc As XlCalculation
Application.EnableCancelKey = xlDisabled
Application.ScreenUpdating = False
Application.Calculation = myCalc
Application.Calculation = xlCalculationManual
Dim folderPath As String
Dim Filename As String
Dim wb As Workbook, wbMaster As Workbook
Dim sh As Worksheet
Dim ColNo As Long
ColNo = 1
folderPath = "C:\testfolder\" 'contains folder path
'or folderPath = "C:\Users\AshleyLarson\Desktop\LoopThroughFolders\AnyFolder\"
' ==> Please correct your path otherwise code won't work. <==
If Right(folderPath, 1) <> "\" Then folderPath = folderPath + "\"
Filename = Dir(folderPath & "*.xlsx")
Do While Filename <> ""
Set wb = Workbooks.Open(folderPath & Filename)
Set wbMaster = Workbooks.Open(folderPath & "masterfolder\Master Template.xlsx") ' BE CAREFUL This should be your Master File's path
wb.Sheets(1).Range("A1:B" & (Range("A" & Rows.Count).End(xlUp).Row) + 100).Copy
Workbooks("Master Template").Worksheets("Sheet1").Range(Chr(ColNo + 64) & ":" & Chr((ColNo + 1) + 64)).PasteSpecial xlPasteValues
ColNo = ColNo + 2
Application.DisplayAlerts = False
Workbooks(Filename).Save
Workbooks(Filename).Close
Workbooks("Master Template.xlsx").Save
Workbooks("Master Template.xlsx").Close
Application.DisplayAlerts = True
Filename = Dir
Loop
Application.ScreenUpdating = True
Application.Calculation = myCalc
End Sub
This can be done in Power Query with just a few clicks on ribbon icons. No VBA required.
Start a new query
from file
navigate to folder
select all files
remove files you don't need with filters (optional step)
combine binaries
select the columns you want to keep
If the files in the folder change, just refresh the query.
Power Query is a free add-in from Microsoft for Excel 2010 and 2013 and built into Excel 2016 as Get & Transform.
Try it this way.
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
https://www.rondebruin.nl/win/s3/win008.htm

Excel VBA; copying specific worksheets from multiple workbooks in different locations

I can copy a sheet named "Alpha" from 6 separate workbooks in the one directory, but I'm not sure how to get the code to loop around to pick up sheets in other files & locations with slightly different names.
I thought I could use :
IF sheetname LIKE "Alpha" then
sheetToCopy = make this the name of the sheet I want to copy
END IF
It doesn't pass the name of the sheet onto the variable though. I think it's because I'm already looping through an array, using file names & numbers.
The code below works perfectly for the 6 Alpha sheets, but it won't pick up "Y Alpha" or "Alpha XZ".
Any help would be very much appreciated!
I use the following code:
Sub AlphaTest()
Dim MyPath 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 SaveDriveDir As String
Dim FName As Variant
Dim FirstCell As String
Dim sName As String
' Set application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
SaveDriveDir = CurDir
' Change this to the path\folder location of the files.
ChDirNet "Z:\"
FName = Application.GetOpenFilename(filefilter:="Excel Files (*.xl*), *.xl*", _
MultiSelect:=True)
If IsArray(FName) Then
' Add a new workbook with one sheet.
Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
rnum = 1
' Loop through all files in the myFiles array.
For FNum = LBound(FName) To UBound(FName)
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(FName(FNum), ReadOnly:=True)
On Error GoTo 0
If Not mybook Is Nothing Then
On Error Resume Next
'If ActiveWorkbook.Worksheets.Name Like "*Debtors*" Then
' sName = ActiveWorkbook.Worksheets.Name
'Else
' sName = "0"
'End If
With mybook.Worksheets("Alpha")
FirstCell = "A6"
Set sourceRange = .Range(FirstCell & ":" & RDB_Last(3, .Cells))
' Test if the row of the last cell is equal to or greater than the row of the first cell.
If RDB_Last(1, .Cells) < .Range(FirstCell).Row Then
Set sourceRange = Nothing
End If
End With
If Err.Number > 0 Then
Err.Clear
Set sourceRange = Nothing
Else
' If the 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 = FName(FNum)
End With
' Set the destination range.
Set destrange = BaseWks.Range("C" & 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 + 1
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
ChDirNet SaveDriveDir
End Sub
From what I can see, you simply want to keep reopening the GetOpenFile dialog until the user cancels out (i.e. doesn't want to bring anymore files in).
Option Explicit
Sub AlphaTest()
Dim FName As Variant
'bunch of code here
FName = Application.GetOpenFilename(filefilter:="Excel Files (*.xl*), *.xl*", _
MultiSelect:=True)
Do While FName <> "False"
If IsArray(FName) Then
'lots of code here
End If
FName = Application.GetOpenFilename(filefilter:="Excel Files (*.xl*), *.xl*", _
MultiSelect:=True)
Loop
ExitTheSub:
'bunch of code here
End Sub

Delete blank rows from Excel table

I have code the merges multiple excel workbooks together, and updates the data into another workbook "Master", however, when it paste the data into the master it leaves numerous blank rows prior to the insert of the data table.
I have tried various posted solutions, however, when I incorporate the new code it is failing. I could use some assistances in modifying my code to handle the removal of the inserted blank rows in my table, prior to the data being updated.
See '>>>>>>>>> marked in the code.
Public Function MergeMultipleSheets()
Dim MyPath As String, FilesInPath As String
Dim MyFiles() As String
Dim SourceRcount As Long, FNum As Long
Dim myBook As Workbook, wbMaster As Workbook
Dim BaseWks As Worksheet, ws As Worksheet
Dim sourceRange As Range, destrange As Range
Dim rnum As Long, CalcMode As Long
Dim rng As Range, SearchValue As String
Dim FilterField As Integer, RangeAddress As String
Dim ShName As Variant, ShNames As Variant, RwCount As Long, nName As Variant
Dim nFilter As String
Dim currentrow As Long
Dim LastRow As Long
MyPath = ThisWorkbook.Sheets("Data Input").Range("B1")
' ShNames = Array("ProjSum", "FinSum", "CommSum", "InvPlan", "ResPlan_Data")
ShNames = Array("ProjSum", "ResPlan_Data")
Set wbMaster = ActiveWorkbook
'**********************************************************
'Merge data into existing worksheets in this workbook
'**********************************************************
' Add a slash after MyPath if needed.
If Right(MyPath, 1) <> "\" Then
MyPath = MyPath & "\"
End If
' If there are no Excel files in the folder, exit.
'FilesInPath = Dir(MyPath & "week*.xl*")
nFilter = ThisWorkbook.Sheets("Data Input").Range("B2")
If nFilter = "" Or FilesInPath = "" Then
FilesInPath = Dir(MyPath & "*.xl*")
End If
' Fill the myFiles array 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 application properties.
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
' Clear data from summary worksheets
For Each ShName In ShNames
Set rng = Nothing
On Error Resume Next
Set rng = wbMaster.Worksheets(ShName).UsedRange
On Error GoTo 0
If Not rng Is Nothing Then
'Don't delete header labels in the first row
Set rng = rng.Offset(1, 0)
End If
Next
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), UpdateLinks:=0)
'**************************************************************************************************
'Removes unused Named Ranges from Name Manager from the Various JC files to prevent error dialogs.
'**************************************************************************************************
For Each nName In Names
If InStr(1, nName.RefersTo, "#REF!") > 0 Then
nName.Delete
End If
If InStr(1, nName.RefersTo, "https://") > 0 Then
nName.Delete
End If
Next nName
On Error GoTo 0
If Not myBook Is Nothing Then
For Each ShName In ShNames
Set ws = Nothing
On Error Resume Next
Set ws = myBook.Worksheets(ShName)
On Error GoTo 0
'****************************************************************************************************************************
'Calls function to update ResPlan in active workbook
'Executes Updating of the ResPlan data to proper format for extraction of data in correct format
'****************************************************************************************************************************
If ShName = "ResPlan_Data" Then
Call UnpivotResPlan
myBook.Save
End If
'**************************************************
'Updates template data per shName
'*************************************************
'>>>>>>>>>
If Not ws Is Nothing Then
Set BaseWks = wbMaster.Worksheets(ShName)
Set sourceRange = ws.UsedRange
'Exclude header labels
Set rng = sourceRange.Offset(1, 0).Resize(sourceRange.Rows.Count - 1, sourceRange.Columns.Count)
rng.ClearContents
Dim rngBlanks As Excel.Range
With wbMaster.Worksheets(ShName).ListObjects("Res_Plan_Data")
On Error Resume Next
Set rngBlanks = Intersect(.DataBodyRange, .ListColumns("New").Range).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanks Is Nothing Then
rngBlanks.Delete
End If
End With
RwCount = rng.Rows.Count
rnum = BaseWks.Cells(BaseWks.Rows.Count, 1).End(xlUp).Row + 1
BaseWks.Cells(rnum, "A").Resize(RwCount).Value _
= myBook.Name
BaseWks.Cells(rnum, "B").Resize(RwCount, rng.Columns.Count).Value = rng.Value
End If
Next
' Close the workbook without saving.
myBook.Close savechanges:=True
End If
' Open the next workbook.
Next FNum
' Set the column width in the new workbook.
BaseWks.Columns.AutoFit
'Prepares Salary Detail for Updating.
Call UnpivotSalaryDetail
End If
Call Reset
' ActiveWorkbook.Model.Refresh
If Worksheets("Resplan_Data").Visible = True Then
Worksheets("Resplan_Data").Visible = False
End If
MsgBox "Update completed!"
' Restore the application properties.
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Function
Sub ClearBlankCellsInColumnNew()
Dim rngBlanks As Excel.Range
With Worksheets("ResPlan_Data").ListObjects("Res_Plan_Data")
On Error Resume Next
Set rngBlanks = Intersect(.DataBodyRange, .ListColumns("New").Range).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanks Is Nothing Then
rngBlanks.Delete
End If
End With
End Sub
Not sure if this is what you are after but it will delete all the rows which have a blank cell in column A
Columns("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
A quick explination Columns("A:A") is the target column, change the letter and add numbers or varibles as you wish. .SpecialCells(xlCellTypeBlanks) is what cell it will target, in this case it will be the blank cells (record a macro and press Ctrl + G for any variations you need). And lastly .EntireRow.Delete will delete the target row(s).
So it will look in column A, and if there is any blank cells in column A it will delete that row.
Hope this helps, leave a comment if you need anything clarifed

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