Excel VBA - loop over files in folder, copy range, paste in this workbook - vba

I have 500 excel files with data. I would merge all this data into one file.
Task list to achieve this:
I want to loop over all the files in a folder
open the file,
copy this range "B3:I102"
paste it into the 1st sheet of the active workbook
repeat but paste new data underneath
I've done task 1-4 but i need help with task 5, last bit - pasting the data under the existing data and making it dynamic. I've highlighted this bit with '#### in my code.
Here is my code which I've put together from other people's question :)
Any suggestions on how to do this?
Sub LoopThroughFiles()
Dim MyObj As Object,
MySource As Object,
file As Variant
Dim wbThis As Workbook 'workbook where the data is to be pasted, aka Master file
Dim wbTarget As Workbook 'workbook from where the data is to be copied from, aka Overnights file
Dim LastRow As Long
Dim sht1 As Worksheet
Dim sht2 As Worksheet
'set to the current active workbook (the source book, the Master!)
Set wbThis = ActiveWorkbook
Set sht1 = wbThis.Sheets("Sheet1")
Folder = "\\dne\ldc\research-dept\3 CEEMEA\15. EMB\Turkey\TLC Overnight & Weekly Reports\weekly (majeed)\"
Fname = Dir(Folder)
While (Fname <> "")
Set wbTarget = Workbooks.Open(Filename:=Folder & Fname)
wbTarget.Activate
Range("b3:i102").Copy
wbThis.Activate
'################################
'NEED HELP HERE. I GET A ERROR HERE. NEEDS TO BE MORE DYNAMIC.
sht1.Range("b1:i100").PasteSpecial
Fname = Dir
'close the overnight's file
wbTarget.Close
Wend
End Sub

I think using variant is useful than copy method.
Sub LoopThroughFiles()
Dim MyObj As Object, MySource As Object
file As Variant
Dim wbThis As Workbook 'workbook where the data is to be pasted, aka Master file
Dim wbTarget As Workbook 'workbook from where the data is to be copied from, aka Overnights file
Dim LastRow As Long
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim vDB As Variant
'set to the current active workbook (the source book, the Master!)
Set wbThis = ActiveWorkbook
Set sht1 = wbThis.Sheets("Sheet1")
Folder = "\\dne\ldc\research-dept\3 CEEMEA\15. EMB\Turkey\TLC Overnight & Weekly Reports\weekly (majeed)\"
Fname = Dir(Folder)
While (Fname <> "")
Set wbTarget = Workbooks.Open(Filename:=Folder & Fname)
vDB = wbTarget.Sheets(1).Range("b3:i102")
'################################
'NEED HELP HERE. I GET A ERROR HERE. NEEDS TO BE MORE DYNAMIC.
sht1.Range("b" & Rows.Count).End(xlUp)(2).Resize(UBound(vDB, 1), UBound(vDB, 2)) = vDB
Fname = Dir
'close the overnight's file
wbTarget.Close
Wend
End Sub

I see you already added a long variable for this, so do a lookup on the last row before you paste. Also, paste in a single cell in case of varying amounts of data.
I altered your script as follows.
Sub LoopThroughFiles()
Dim MyObj As Object,
MySource As Object,
file As Variant
Dim wbThis As Workbook 'workbook where the data is to be pasted, aka Master file
Dim wbTarget As Workbook 'workbook from where the data is to be copied from, aka Overnights file
Dim LastRow As Long
Dim sht1 As Worksheet
Dim sht2 As Worksheet
'set to the current active workbook (the source book, the Master!)
Set wbThis = ActiveWorkbook
Set sht1 = wbThis.Sheets("Sheet1")
Folder = "\\dne\ldc\research-dept\3 CEEMEA\15. EMB\Turkey\TLC Overnight & Weekly Reports\weekly (majeed)\"
Fname = Dir(Folder)
While (Fname <> "")
Set wbTarget = Workbooks.Open(Filename:=Folder & Fname)
wbTarget.Activate
Range("b3:i102").Copy
wbThis.Activate
'Just add this line:
lastrow = sht1.Range("b1").End(xlDown).Row + 1
'And alter this one as follows:
sht1.Range("B" & lastrow).PasteSpecial
Fname = Dir
'close the overnight's file
wbTarget.Close
Wend
End Sub

How about you define sht1.Range("b1:i102") as variables instead of constants?
Something like:
Dim x As Long
Dim y As Long
x = 1
y = 1
Dim rng As Range
Set rng = Range("b"&x ,"i"&y)
And then use:
sht1.rng
Just remember to add x = x+100 and y = y +100 at the end of your while statement (so it will update new values between each paste.)

Why don't you place a counter? Like this:
Dim counter As Long
counter = 1
And then:
While (Fname <> "")
Set wbTarget = Workbooks.Open(Filename:=Folder & Fname)
wbTarget.Activate
Range("b3:i102").Copy
wbThis.Activate
'Solution:
sht1.Range("b" & counter & ":i" & counter + 99).PasteSpecial
counter = counter + 100
Fname = Dir
'close the overnight's file
wbTarget.Close
Wend

You can addbelow section as step 5. I have used offset with Variable incremented in loop
Dim i as Long
Range("B1").Select // 'select the column where you want to paste value
ActiveCell.Offset(i, 0).Select //'place the offset counter with variable
sht1.Range("b1:i100").PasteSpecial
i=i+100 //'increment the offset with the number of data rows

Related

Automatically update macro when changing filename

I have the following macro to filter specific data out of my directory with employee hours files and place it into my zmaster file. However, I need various master documents for various projects (EG. change name to: "project 300000"). When I change my master file name from zmaster to anything else, my macro cannot find the appropriate file, obviously.
Is there a way to change my macro in such a way that zmaster.xlsm is automatically replaced in my macro by the current file name?
Option Explicit
Sub CopyToMasterFile()
Dim MasterWB As Workbook
Dim MasterSht As Worksheet
Dim MasterWBShtLstRw As Long
Dim FolderPath As String
Dim TempFile
Dim CurrentWB As Workbook
Dim CurrentWBSht As Worksheet
Dim CurrentShtLstRw As Long
Dim CurrentShtRowRef As Long
Dim CopyRange As Range
Dim ProjectNumber As String
FolderPath = "C:\test\"
TempFile = Dir(FolderPath)
Dim WkBk As Workbook
Dim WkBkIsOpen As Boolean
'Check if zmaster is open already
For Each WkBk In Workbooks
If WkBk.Name = "zmaster.xlsm" Then WkBkIsOpen = True
Next WkBk
If WkBkIsOpen Then
Set MasterWB = Workbooks("zmaster.xlsm")
Set MasterSht = MasterWB.Sheets("Sheet1")
Else
Set MasterWB = Workbooks.Open(FolderPath & "zmaster.xlsm")
Set MasterSht = MasterWB.Sheets("Sheet1")
End If
ProjectNumber = MasterSht.Cells(1, 1).Value
Do While Len(TempFile) > 0
'Checking that the file is not the master and that it is a xlsx
If Not TempFile = "zmaster.xlsm" And InStr(1, TempFile, "xlsx", vbTextCompare) Then
Set CopyRange = Nothing
'Note this is the last used Row, next empty row will be this plus 1
With MasterSht
MasterWBShtLstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Set CurrentWB = Workbooks.Open(FolderPath & TempFile)
Set CurrentWBSht = CurrentWB.Sheets("Sheet1")
With CurrentWBSht
CurrentShtLstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
For CurrentShtRowRef = 1 To CurrentShtLstRw
If CurrentWBSht.Cells(CurrentShtRowRef, "A").Value = ProjectNumber Then
'This is set to copy from Column A to Column L as per the question
If CopyRange Is Nothing Then
'If there is nothing in Copy range then union wont work
'so first row of the work sheet needs to set the initial copyrange
Set CopyRange = CurrentWBSht.Range("A" & CurrentShtRowRef & _
":L" & CurrentShtRowRef)
Else
'Union is quicker to be able to copy from the sheet once
Set CopyRange = Union(CopyRange, _
CurrentWBSht.Range("A" & CurrentShtRowRef & _
":L" & CurrentShtRowRef))
End If ' ending If CopyRange Is Nothing ....
End If ' ending If CurrentWBSht.Cells....
Next CurrentShtRowRef
CopyRange.Select
'add 1 to the master file last row to be the next open row
CopyRange.Copy MasterSht.Cells(MasterWBShtLstRw + 1, 1)
CurrentWB.Close savechanges:=False
End If 'ending If Not TempFile = "zmaster.xlsx" And ....
TempFile = Dir
Loop
ActiveSheet.Range("A1:L200").RemoveDuplicates Columns:=Array(1, 2, 4, 8, 9, 10, 11, 12), Header:=xlYes
End Sub
One way to escape from hard coded workbook names is to use ActiveWorkbook or ThisWorkbook objects - they both return instance of Workbook object.
ThisWorkbook
Returns a Workbook object that represents the workbook
where the current macro code is running. Read-only.
ActiveWorkbook
Returns a Workbook object that represents the workbook in the active
window (the window on top). Read-only. Returns Nothing if there are no
windows open or if either the Info window or the Clipboard window is
the active window.
Then you can get the name of the workbook with Name property of the returned Workbook object.
Another way could be if you pass such a data as parameter to your functions.
For example:
Sub CopyToMasterFile(wbName as String, sheetName as String)
In this variant if you call your Sub from another macro code, you can pass whatever you want to use - this ways you can escape the hard coded stuff in your functions.
This is also valid for the Worksheet objects - have a look on the ActiveSheet

Got stuck in using transpose

I was attempting to extract data from other workbooks into a master workbook. All of these workbooks were saved in one folder. And I wanted to open other workbooks automatically not manually. The data that I need to extract are non adjacent cells, and I want the data extracted from each source workbook to be shown in rows in the master workbook (because I have a head line in row 1, so after extracting data from the first workbook and paste in row 2, the data extracted from the second workbook will be listed in row 3 and so on)
However, when I ran the macro I got stuck in Transpose.
Below is my code
Sub LoopThroughDirectory()
Dim MyFile As String
Dim wkbSource As Workbook
Dim wkbTarget As Workbook
Dim erow As Single
Dim Filepath As String
Dim copyRange As Range
Dim cel As Range
Dim pasteRange As Range
Filepath = "C:\xxxxx\"
MyFile = Dir(Filepath)
Do While Len(MyFile) > 0
If MyFile = "Import Info.xlsm" Then GoTo NextFile
Set wkbTarget = Workbooks("Import Info.xlsm")
Set wkbSource = Workbooks.Open(Filepath & MyFile)
Set copyRange = wkbSource.Sheets("sheet1").Range("c3,f6,f9,f12,f15,f19,f21,f27,f30,f33,f37,f41")
Set pasteRange = wkbTarget.Sheets("sheet1").Range("a1")
For Each cel In copyRange
cel.Copy
ecolumn = wkbTarget.Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Offset(0, 1).Column
wkbTarget.Worksheets("Sheet1").Paste Destination:=wkbTarget.Worksheets("Sheet1").Range(Cells(1, ecolumn).Address)
pasteRange.Cells(1, ecolumn).PasteSpecial xlPasteValues
Next
Application.CutCopyMode = False
wkbSource.Close
NextFile:
MyFile = Dir
Loop
End Sub
What I have done so far:
I transposed the data I extracted from source workbooks but they were not shown in the master workbook as what I expected. All of them are in row 1
I don't have much experience in VBA and I feel like the code I wrote to copy non adjacent cells and transpose in the master workbook makes the loop much more complicated. But I don't know where I went wrong or how to fix that.
Please help me. Thank you so much!
You have to set the destination range outside of the loop and offset it inside of the loops:
Sub LoopThroughDirectory()
Dim Filepath As String, MyFile As String
Dim wkbSource As Workbook, wkbTarget As Workbook
Dim copyRange As Range, cel As Range, pasteRange As Range
Set wkbTarget = Workbooks("Import Info.xlsm")
Set pasteRange = wkbTarget.Sheets("sheet1").Range("a2") ' start at row 2
Filepath = "C:\xxxxx\"
MyFile = Dir(Filepath)
While MyFile > ""
If MyFile = "Import Info.xlsm" Then GoTo NextFile
Set wkbSource = Workbooks.Open(Filepath & MyFile)
Set copyRange = wkbSource.Sheets("sheet1").Range("c3,f6,f9,f12,f15,f19,f21,f27,f30,f33,f37,f41")
For Each cel In copyRange
pasteRange.Value = cel.Value ' "copy" the value
Set pasteRange = pasteRange.Offset(, 1) ' move to the next column
Next
wkbSource.Close
Set pasteRange = pasteRange.EntireRow.Resize(1,1) ' move back to the first cell in the row
Set pasteRange = pasteRange.Offset(1) ' move to the cell bellow (next row)
NextFile:
MyFile = Dir
Wend
End Sub

Copy multiple xls files data to single file using VBA

I have Multiple files in a folder.i wants to copy all Files data (i.e.all columns to new sheet) to one new sheet.
E.g. file 1 Contains 5 columns of data and file 2 contains 10 columns of data and so on. this data should copy on new sheet like first 5 columns are from file 1 and then on the same sheet from column 6, the file2 data should be copy and so on.
i tried but facing some problems like i am able to copy first file data successfully but when i am going to second file , second file data is overwriting on first file. i want second file data to the next column.
Below is my code
Public Sub CommandButton1_Click()
'DECLARE AND SET VARIABLES
Dim wbk As Workbook
Dim Filename As String
Dim Path As String
Dim mainwb As Workbook
Dim ws As Worksheet
Dim search_result As Range 'range search result
Dim blank_cell As Long
Dim wb As Workbook
Path = "C:\Test\"
Filename = Dir(Path & "*.xls")
'--------------------------------------------
'OPEN EXCEL FILES
Do While Len(Filename) > 0 'IF NEXT FILE EXISTS THEN
Set wbk = Workbooks.Open(Path & Filename)
Set wbk = ActiveWorkbook
sheetname = ActiveSheet.Name
wbk.Sheets(sheetname).Activate
Lastrow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To Lastrow
wbk.Sheets(sheetname).UsedRange.Copy
Workbooks("aaa.xlsm").Activate
Set wb = ActiveWorkbook
sheetname1 = ActiveSheet.Name
Lastrow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
wb.Sheets(sheetname1).Range("A1").Select
wb.Sheets(sheetname1).Paste
Next i
ActiveCell.Offset(0, 1).Select
wbk.Close SaveChanges:=False
Filename = Dir
Loop
End Sub
plz help me......
Thanks in Advance
With the For i = 1 To Lastrow loop you are pasting the content several times and I was unable to correct it without significant change. As a result may I recommend using the below sample, I have added comments to describe what is happening.
Public Sub Sample()
Dim Fl As Object
Dim Fldr As Object
Dim FSO As Object
Dim LngColumn As Long
Dim WkBk_Dest As Excel.Workbook
Dim WkBk_Src As Excel.Workbook
Dim WkSht_Dest As Excel.Worksheet
Dim WkSht_Src As Excel.Worksheet
'Using FileSystemObject to get the folder of files
Set FSO = CreateObject("Scripting.FileSystemObject")
Set Fldr = FSO.GetFolder("C:\Users\Gary\Desktop\New folder\")
'Setting a reference to the destination worksheet (i.e. where the
'data we are collecting is going to)
Set WkBk_Dest = ThisWorkbook
Set WkSht_Dest = WkBk_Dest.Worksheets("Sheet1")
'Look at each file in the folder
For Each Fl In Fldr.Files
'Is it a xls, xlsx, xlsm, etc...
If InStr(1, Right(Fl.Name, 5), ".xls") <> 0 Then
'Get the next free column in our destination
LngColumn = WkSht_Dest.Cells(1, WkSht_Dest.Columns.Count).End(xlToLeft).Column
If LngColumn > 1 Then LngColumn = LngColumn + 1
'Set a reference to the source (note in this case it is simply selected the first worksheet
Set WkBk_Src = Application.Workbooks.Open(Fl.Path)
Set WkSht_Src = WkBk_Src.Worksheets(1)
'Copy the data from source to destination
WkSht_Src.UsedRange.Copy WkSht_Dest.Cells(1, LngColumn)
Set WkSht_Src = Nothing
WkBk_Src.Close 0
Set WkBk_Src = Nothing
End If
Next
Set WkSht_Dest = Nothing
Set WkBk_Dest = Nothing
Set Fldr = Nothing
Set FSO = Nothing
End Sub

Copy Range from multiple workbooks in folder to Summary Workbook also in folder?

I have a folder with 100+ workbooks. These workbooks contain a range of data. For simplicity I will call the data range A1:D2, the range is located on Sheet1 of all 100+ workbooks.
I also have a Summary workbook.
I would like to place VBA code in the Summary workbook that loops through the folder, copying the range A1:D2 of each of the 100+ workbooks.
I would then like to paste the A1:D2 range from each workbook in to Sheet1 of the Summary workbook. Each paste will start on the next unused row.
I am stuck doing this via a manual process right now and it is driving me insane.
I do know some basic VBA coding however my problem is that I can't figure out how to loop it correctly, and I am stuck coding each individual workbook to open-->copy-->paste-->close. This was fine with 10-20 workbooks but now I am at 100+ and it is growing every week.
Thanks again,
Brian
I have something that does exactly what you are asking for, if you want to copy multiple workbooks I suggest creating a new worksheet to capture the workbook information onto a spreadsheet. Instructions below
Create a new worksheet and give it a name, in this case we'll call the sheet 'Control'
Create a new module in VBA and use the code below to operate the workbook copy
I have left a section out for you to write your code for the functions that you want to perform.
Sub WorkbookConsolidator()
Dim WB As Workbook, wb1 as workbook
Dim WBName as Range
Dim folderselect as Variant, wbA as Variant, wbB as Variant,
Dim I as long, J as long
Dim objFolder As Object, objFile As Object
Dim WBRange as String
'Set Core Variables and Open Folder containing workbooks.
Set WB = ThisWorkbook
Worksheets("Control").Activate
Set FolderSelect = Application.FileDialog(msoFileDialogFolderPicker)
FolderSelect.AllowMultiSelect = False
MsgBox ("Please Select the Folder containing your Workbooks")
FolderSelect.Show
WBRange = FolderSelect.SelectedItems(1)
Set objFolder = objFSO.GetFolder(FolderSelect.SelectedItems(1))
' Fill out File name Fields in Control Sheet
' The workbook names will be captured in Column B
' This allows allocation for up to 100 workbooks
For I = 1 To 100
For Each objFile In objFolder.files
If objFile = "" Then Exit For
Cells(I, 2) = objFile.Name ' Workbook Name
Cells(I, 3) = WBRange ' Workbook Path
I = I + 1
Next objFile
Next I
'Loop through the list of workbooks created in the 'Control' Directory, adjust the loop range as preferred
For J = 100 To 1 Step -1
With Workbooks(ThisWorkbook).Worksheets("Control")
BookLocation = .Range("C" & J).Value
BookName = .Range("B" & J).Value
End With
Set wb1 = Workbooks.Open(Booklocation & Bookname)
' Write your code here'
CleanUp:
wb1.Close SaveChanges:=False
Next J
End Sub()
`
Try this
Sub combine_into_one()
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim strPath$, Pivot$, sUserName$, sFolderName$, sSourceName$, x&
Dim oFldialog As FileDialog
Dim oFile As Scripting.File
Dim oFolder
Set oFldialog = Application.FileDialog(msoFileDialogFolderPicker)
With oFldialog
If .Show = -1 Then
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = strPath
sFolderName = .SelectedItems(1)
End If
End With
Set oFolder = FSO.GetFolder(sFolderName)
Workbooks.Add: Pivot = ActiveWorkbook.Name 'Destination workbook
For Each oFile In oFolder.Files
Workbooks(Pivot).Activate
x = Workbooks(Pivot).Sheets("Sheet1").Cells.SpecialCells(xlCellTypeLastCell).Row + 1
Workbooks.Open filename:=oFile: sSourceName = ActiveWorkbook.Name
Workbooks(sSourceName).Activate
Workbooks(sSourceName).Sheets("Sheet1").[A1:D1].Copy
Workbooks(Pivot).Activate
Workbooks(Pivot).Sheets("Sheet1").Cells(x, 1).PasteSpecial xlPasteAll
Workbooks(sSourceName).Close False
Next
End Sub

How to copy and append cells content from a different workbook to an Activework?

I have a macro that allows a user to browse and select multiple Excel files, after the user has selected the multiple Excel files, the content from multiple Excel files should be saved on the current active workbook, on one sheet. the content would be append one another.
The problem is that when the loop runs for the second time it complains with the range, it says the range should start at "A1".
here is my code below.
Sub Button3_Click()
Dim fileStr As Variant
Dim incount As Integer
Dim wbk1 As Workbook, wbk2 As Workbook
incount = 1
fileStr = Application.GetOpenFilename(FileFilter:="microsoft excel files (*.xlsx), *.xlsx", Title:="Get File", MultiSelect:=True)
For i = 1 To UBound(fileStr)
MsgBox fileStr(i), , GetFileName(CStr(fileStr(i)))
Set wbk1 = ActiveWorkbook
Set wbk2 = Workbooks.Open(fileStr(i))
wbk2.Sheets(1).Cells.Copy wbk1.Worksheets("Sheet3").Cells(incount, 1)
incount = Range("A" & Rows.Count).End(xlUp).Row
wbk2.Close
Next i
MsgBox incount
End Sub
Function GetFileName(fileStr As String)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
GetFileName = fso.GetFileName(fileStr)
End Function
Error message:
Run-time error '1004'
To paste all cells from an Excel worksheet into the current worksheet,
you must paste into the first cell(A1 or R1C1)
The cells.copy copies the whole sheet of data to the row of 'incount' which means that there is not room on the destination for the 'whole source sheet' below the already pasted data
Try the following code which removes incount and just picks up the UsedRange:
Sub Button3_Click()
Dim fileStr As Variant
Dim wbk1 As Workbook, wbk2 As Workbook
Dim ws1 As Worksheet
fileStr = Application.GetOpenFilename(FileFilter:="microsoft excel files (*.xlsx), *.xlsx", Title:="Get File", MultiSelect:=True)
Set wbk1 = ActiveWorkbook
Set ws1 = wbk1.Sheets("Sheet3")
For i = 1 To UBound(fileStr)
MsgBox fileStr(i), , GetFileName(CStr(fileStr(i)))
Set wbk2 = Workbooks.Open(fileStr(i))
wbk2.Sheets(1).UsedRange.Copy ws1.Cells(ws1.Range("A" & Rows.Count).End(xlUp).Row + 1, 1)
wbk2.Close
Next i
End Sub
Function GetFileName(fileStr As String)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
GetFileName = fso.GetFileName(fileStr)
End Function