VBA loop throught each cell to copy files - vba

I have an Excel file where columns (icol) each cells contains a path of some files like this :
column A column B column c
P:\Desktop\Source\Test1-folder\file1.txt empty column P:\Desktop\Source\Test1-folder\filetest.txt
P:\Desktop\Source\Test1-folder\file2.txt .....
and I need to loop through these cells to copy files from the cells into destination folder, but i couldn't succeed .Can anyone help how to do it?
Dim strSlash As String, destinationFolder As String
Dim lastcolumn As Long, icol As Long, lastLigne As Long
Dim rngCell As Range, rngFiles As Range
Dim FSO As New FileSystemObject
destinationFolder = "P:\Desktop\folderdestination"
Dim maListe As Object
Dim workboo As Workbook
Dim worksh As Worksheet
Set workboo = Workbooks.Open(P:\Desktop\Source\excelfile.xlsx)
Set worksh = workboo.Worksheets("path_files")
lastcolumn = Cells(1, Cells.Columns.Count).End(xlToLeft).Column
If Dir(destinationFolder, 16) = "" Then MkDir (destinationFolder)
For icol = 1 To lastcolumn Step 2
lastLigne = Cells(Rows.Count, icol).End(xlUp).Row
Set rngFiles = Cells(1, icol).Resize(lastLigne)
For Each rngCell In rngFiles.Cells
If Dir(rngCell.Value) <> "" Then
strFile = Right(rngCell.Value, Len(rngCell.Value) - InStrRev(rngCell.Value, "\"))
If Dir(destinationFolder & "\" & Left(strFile, 5) , 16) = "" Then
FSO.CopyFile rngCell.Value, destinationFolder & "\" & Left(strFile, 5)
End If
End If
Next rngCell
Next icol
end sub

edited to add a check for source file existence
this should do
Option Explicit
Sub main()
Dim strSlash As String, destinationFolder As String
Dim lastcolumn As Long, icol As Long, lastLigne As Long
Dim rngCell As Range, rngFiles As Range
Dim FSO As New FileSystemObject
strSlash = "\"
destinationFolder = "P:\Desktop\folderdestination"
lastcolumn = Cells(1, Cells.Columns.Count).End(xlToLeft).Column
For icol = 1 To lastcolumn Step 2
lastLigne = Cells(Rows.Count, icol).End(xlUp).Row
Set rngFiles = Cells(1, icol).Resize(lastLigne)
For Each rngCell In rngFiles.Cells
If Dir(rngCell.Value) <> "" Then '<~~ check if the source file is actually there!
If Dir(destinationFolder & "\" & Right(rngCell.Value, Len(rngCell.Value) - InStrRev(rngCell.Value, strSlash)), 16) = "" Then
FSO.CopyFile rngCell.Value, destinationFolder & "\" & Right(rngCell.Value, Len(rngCell.Value) - InStrRev(rngCell.Value, strSlash))
End If
End If
Next rngCell
Next icol
End Sub
but it could still be improved to a good extent, exploiting FileSystemObject more thoroughly (which of course needs adding reference to "Microsoft Scripting Runtime" library: Tools->References and then scroll down List Box and select "Microsoft Scripting Runtime" checkbox)

Related

Saving a xlsx file in a particular folder

I am trying to copy the content from source workbook to a new workbook and save it in xlsx format in a specified folder.
I am trying the below code and I get application defined error in the Last line of the code, where I am trying to save my new workbook as .xlsx
Also, It takes long time approx. 5min for this small piece of code.
Sub newWB()
Dim myWksht As String
Dim newWB As Workbook
Dim MyBook As Workbook
Dim i As Integer, j As Integer
Dim LastRow As Long, totalrows As Long
Dim path1, path2 As String
path1 = ThisWorkbook.Path
path2 = path1 & "\Tru\Sq\"
Set newWB = Workbooks.Add
With ThisWorkbook.Worksheets("Pivottabelle")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With newWB.Sheets("Sheet1")
.Name = "PivotTable"
j = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
With Worksheets("Pivottabelle")
For i = 1 To LastRow
ThisWorkbook.Sheets("Pivottabelle").Range("A1:Y400").Copy: newWB.Sheets("PivotTable").PasteSpecial
Next i
End With
With newWB.Worksheets("PivotTable")
totalrows = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = totalrows To 2 Step -1
If .Cells(i, 8).Value <> "TRU" Then
Cells(i, 8).EntireRow.Delete
End If
Next
newWB.SaveAs Filename:=path2 & ".xlsx"
End With
End Sub
This should show all the improvements from the comments (plus some more) …
It can be that you run into issues when saving because this
DestinationPath = ThisWorkbook.Path & "\Tru\Sq\"
only works if the macro containing workbook is already saved. Otherwise ThisWorkbook.Path is empty. And you probably need to be sure that these subfolders already exist.
Option Explicit 'force variable declare
Public Sub AddNewWorkbook() 'sub and newWB had the same name (no good practice)
'Dim myWksht As String 'not used therefore can be removed
Dim newWB As Workbook
'Dim MyBook As Workbook 'not used therefore can be removed
'Dim i As Integer, j As Integer
Dim i As Long, j As Long 'use long instead of integer whenever possible
'see https://stackoverflow.com/a/26409520/3219613
Dim LastRow As Long, totalrows As Long
'Dim path1, path2 As String 'always specify a type for every variable
Dim DestinationPath As String 'we only need one path
DestinationPath = ThisWorkbook.Path & "\Tru\Sq\"
'path2 = path1 & "\Tru\Sq\" ' can be reduced to one path
Set newWB = Workbooks.Add
With ThisWorkbook.Worksheets("Pivottabelle")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With newWB.Sheets("Sheet1")
.Name = "PivotTable"
j = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
'With Worksheets("Pivottabelle") 'unecessary with (not used at all)
'For i = 1 To LastRow 'unecessary loop
ThisWorkbook.Sheets("Pivottabelle").Range("A1:Y400").Copy
newWB.Sheets("PivotTable").PasteSpecial
'Next i
'End With
With newWB.Worksheets("PivotTable")
totalrows = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = totalrows To 2 Step -1
If .Cells(i, 8).Value <> "TRU" Then
.Cells(i, 8).EntireRow.Delete 'was missing a . before Cells(i, 8).EntireRow.Delete
End If
Next
newWB.SaveAs Filename:=DestinationPath & "FILENAME" & ".xlsx" 'was missing a filename
End With
End Sub

Loop not working between directories

I worked around with a vba code to search a list of cells in a column of a workbook and those cells need to be searched in a folder and if cell is matched in any of the workbook all corresponding data needs to be copied to the main workbook.
I was working with 2 loops but if one is working another one is not for example if I loop through all files in a folder I can't loop with the column in the main workbook to search one cell after another.
Below is the code:
Sub SearchFolders()
Dim fso As Object
Dim fld As Object
Dim strSearch As String
Dim strPath As String
Dim strFile As String
Dim wOut As Worksheet
Dim wbk As Workbook
Dim wks As Worksheet
Dim rFound As Range
Dim irow As Integer
Dim rng As Range
Dim strFirstAddress As String
On Error GoTo ErrHandler
Application.ScreenUpdating = False
strPath = "\dfs\Home\Tes"
Set wOut = ThisWorkbook.Worksheets("Data")
With wOut
lRow = 2
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(strPath)
strFile = Dir(strPath & "\*.xls*")
Do While Cells(lRow, 1) < Empty
strSearch = Cells(lRow, 1)
Set wbk = Workbooks.Open _
(Filename:=strPath & "\" & strFile, _
UpdateLinks:=0, _
ReadOnly:=True, _
AddToMRU:=False)
For Each wks In wbk.Worksheets
Set rFound = wks.UsedRange.Find(strSearch)
If Not rFound Is Nothing Then
strFirstAddress = rFound.Address
End If
Do
If rFound Is Nothing Then
Exit Do
Else
Cells(lRow, 2) = rFound.Offset(0, 1).Value
Cells(lRow, 3) = rFound.Offset(0, 2).Value
End If
Set rFound = wks.Cells.FindNext(After:=rFound)
Loop While strFirstAddress < rFound.Address
Next
wbk.Close (False)
lRow = lRow + 1
Loop
End With
MsgBox "Done"
End Sub
I think you have to change the do while to
Do While .Cells(lRow, 1) <> Empty
Explanation: If you use Cells(lRow, 1) (without dot), you access the active sheet. But in the moment you do a workbook.open, the active sheet will change, so at the next iteration you no longer look to the sheet wOut but to a sheet of the opened wokbook.
If you write .Cells(lRow, 1) (with leading dot), Cells is seen as a property of whatever you have used in a with-clause, in your case With wOut. Alternatively, you could write wOut.Cells(lRow, 1) (this is just a matter of taste)

Excel looping through directory continue search without matches

When I'm looping through directory to find matches between files in a specific folder and cell/row one of my master file, and copy these matched rows to my master file, I get an error 91 notification if there are no matches between the master file and a file in the folder I'm looping through.
If a specific file doesn't have a match I want my macro to automatically look at the next file and so on without giving me this error obviously. Any suggestions how to solve this?
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
Dim wbname As String
Dim sheetname As String
wbname = ActiveWorkbook.Name
sheetname = ActiveSheet.Name
FolderPath = "C:\data\"
TempFile = Dir(FolderPath)
Dim WkBk As Workbook
Dim WkBkIsOpen As Boolean
For Each WkBk In Workbooks
If WkBk.Name = wbname Then WkBkIsOpen = True
Next WkBk
If WkBkIsOpen Then
Set MasterWB = Workbooks(wbname)
Set MasterSht = MasterWB.Sheets(sheetname)
Else
Set MasterWB = Workbooks.Open(FolderPath & wbname)
Set MasterSht = MasterWB.Sheets(sheetname)
End If
ProjectNumber = MasterSht.Cells(1, 1).Value
Do While Len(TempFile) > 0
If Not TempFile = wbname And InStr(1, TempFile, "xlsx", vbTextCompare) Then
Set CopyRange = Nothing
With MasterSht
MasterWBShtLstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Set CurrentWB = Workbooks.Open(FolderPath & TempFile)
Set CurrentWBSht = CurrentWB.Sheets(1)
With CurrentWBSht
CurrentShtLstRw = .Cells(.Rows.Count, "AD").End(xlUp).Row
End With
For CurrentShtRowRef = 1 To CurrentShtLstRw
If CurrentWBSht.Cells(CurrentShtRowRef, "AD").Value = ProjectNumber Then
If CopyRange Is Nothing Then
set CopyRange = CurrentWBSht.Range("AE" & CurrentShtRowRef & _
":AQ" & CurrentShtRowRef)
Else
Set CopyRange = Union(CopyRange, _
CurrentWBSht.Range("AE" & CurrentShtRowRef & _
":AQ" & CurrentShtRowRef))
End If
End If
Next CurrentShtRowRef
CopyRange.Select
CopyRange.Copy
MasterSht.Cells(MasterWBShtLstRw + 1, 1).PasteSpecial xlPasteValues
Application.DisplayAlerts = False
CurrentWB.Close savechanges:=False
Application.DisplayAlerts = True
End If
TempFile = Dir
Loop
ActiveSheet.Range("A1:M200").RemoveDuplicates Columns:=Array(1, 2, 4, 8, 9, 10, 11, 12), Header:=xlYes
End Sub
Use this condition after your if matching condition (it will be executed after the matching condition, but keep it in the loop)
if index = lastindex then 'if you have reached the end of the current file
'proceed to next file
Where index is the index of the row/columns you are scanning within the current file and lastindex is the lastindex of the current file (therefore the end of the current file).
This will however require you to know the lastindex of the files you scan through. But you can easily accomplish this with a do while loop:
index= 1
Do While (Not IsEmpty(Sheets("YourSheetName").Cells(index, 1)))
index= index+ 1
Loop
index= index- 1 'remove last cell corresponding to first empty cell
This above loop works for rows but you can easily use it for columns.
Hope this helped!
Changing the following part of my macro solved this problem:
Next CurrentShtRowRef
If Not CopyRange Is Nothing Then
CopyRange.Select
CopyRange.Copy
MasterSht.Cells(MasterWBShtLstRw + 1, 1).PasteSpecial xlPasteValues
End If

Excel VBA code for Looping through files and copying specific data to one file

I am new to VBA and If anyone can help, I'd greatly appreciate it. I just need help in simple VBA loop in following code.
I am trying to loop through excel files in a folder and copy specific data from source Worksheet in all files to a new workbook (sheet 2). I have a code which does 70% of the job but I am having difficulty in picking some data and copying it in specific format.
Option Explicit
Const FOLDER_PATH = "C:\Temp\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
Dim FirstRow As Long, LastRow As Long
FirstRow = 1
LastRow = 5
Dim RowRange As Range
rowTarget = 2
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error Goto errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Sheet2")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = Sheets("DispForm") 'EDIT IF NECESSARY
'import the data
With wsTarget
For Each rw In RowRange
If wsSource.Cells(rw.Row, 1) & wsSource.Cells(rw.Row + 1, 1) = "" Then
Exit For
End If
.Range("A" & rowTarget).Value = wsSource.Range("B1").Value
.Range("B" & rowTarget).Value = wsSource.Cells(rw.Row, 2)
.Range("C" & rowTarget).Value = wsSource.Cells(rw.Row, 4)
.Range("D" & rowTarget).Value = sFile
rowTarget = rowTarget + 1
Next rw
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
you only copy one row of data from your source file. so you need either to have a loop inside your file loop to loop all the rows, or to have a range to select all the rows.
try something like the following:
Dim FirstRow As Long, LastRow As Long
FirstRow = 9
LastRow = 100
Set rowRange = wsSource.Range("A" & FirstRow & ":A" & LastRow)
With wsTarget
For Each rw In rowRange
If wsSource.Cells(rw.Row, 2) = "" Then
Exit For
End If
.Range("A" & rowTarget).Value = wsSource.Cells(rw.Row, 2)
.Range("B" & rowTarget).Value = wsSource.Cells(rw.Row, 3)
Next rw
End With

Sorting data from multiple .csv's into a single workbook

I have a VBA script that reads through each CSV in a given folder, reads the data in and places it into a workbook. It then goes to the next .csv and appends that data to the very last row of the previous set of data.
I would instead like it to append the data from each .csv along the columns not the rows, however I am having some trouble wrapping my head around how to do this. Here is the code:
Sub MergeAllWorkbooks()
Dim SummarySheet As Worksheet
Dim FolderPath As String
Dim NRow As Long
Dim FileName As String
Dim WorkBk As Workbook
Dim SourceRange As Range
Dim DestRange As Range
Dim LastRow As Long
Dim inputValue As Variant
Set SummarySheet = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
inputValue = InputBox("Input File Path:")
FolderPath = inputValue
NRow = 1
FileName = Dir(FolderPath & "*csv*")
Do While FileName <> ""
Set WorkBk = Workbooks.Open(FolderPath & FileName)
SummarySheet.Range("A" & NRow).Value = FileName
LastRow = WorkBk.Worksheets(1).Cells.Find(What:="*", _
After:=WorkBk.Worksheets(1).Cells.Range("A1"), _
SearchDirection:=xlPrevious, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows).Row
Set SourceRange = WorkBk.Worksheets(1).Range("A1:B" & LastRow)
Set DestRange = SummarySheet.Range("B" & NRow)
Set DestRange = DestRange.Resize(SourceRange.Rows.Count, SourceRange.Columns.Count)
DestRange.Value = SourceRange.Value
NRow = NRow + DestRange.Rows.Count
WorkBk.Close savechanges:=False
FileName = Dir()
Loop
SummarySheet.Columns.AutoFit
End Sub
This macro might help.
Sub simpleXlsMerger() Dim bookList As Workbook Dim mergeObj As Object, dirObj As Object, filesObj As Object, everyObj As Object Application.ScreenUpdating = False Set mergeObj = CreateObject("Scripting.FileSystemObject")
'change folder path of excel files here Set dirObj = mergeObj.Getfolder("C:\Users\guillermo.rojas\Documents\Desktop\Reports\EOD") Set filesObj = dirObj.Files For Each everyObj In filesObj Set bookList
= Workbooks.Open(everyObj)
'change "A2" with cell reference of start point for every files here 'for example "B3:IV" to merge all files start from columns B and rows 3 'If you're files using more than IV column, change it to the latest column 'Also change "A" column on "A65536" to the same column as start point Range("A2:IV" & Range("A65536").End(xlUp).Row).Copy ThisWorkbook.Worksheets(1).Activate
'Do not change the following column. It's not the same column as above Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial Application.CutCopyMode = False bookList.Close Next End Sub
Find the LastColumn in the SummarySheet using the following code:
LastColumn = Workbk.Worksheets(1).Cells(1, Columns.Count).End(xlToLeft).Column
Then convert the LastColumn Number to letter using the following code or function:
LastColumnLetter = CovertToLetter(LastColumn)
Public Function ConvertToLetter(iCol As Long) As String
Dim iAlpha As Long
Dim iRemainder As Long
iAlpha = Int(iCol / 27)
iRemainder = iCol - (iAlpha * 26)
If iAlpha > 0 Then
ConvertToLetter = Chr(iAlpha + 64)
End If
If iRemainder > 0 Then
ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
End If
End Function
Now Change DestRange like below
DestRange = SummarySheet.Range(LastColumnLetter & 1)
Then increase the count of LastColumn as LastColumn = LastColumn + 1