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
Related
Been trying to figure out how to copy a cell from worksheet A and paste it down a column in Worksheet B until it matches the same amount of rows as an adjacent column. Take the following screenshot for example. How would I properly accomplish this in VBA? Been trying to figure this out for a while now. All I've been able to do is copy the cell and paste it adjacent to the last cell in the adjacent column instead of down the entire column. The worksheet I'm copying data from is pictured below.
Copy From SpreadSheet down below
Paste to SpreadSheet down below
Current Code
Sub pullSecEquipment()
Dim path As String
Dim ThisWB As String
Dim wbDest As Workbook
Dim shtDest As Worksheet
Dim shtPull As Worksheet
Dim Filename As String
Dim Wkb As Workbook
Dim CopyRng As Range, DestRng As Range
Dim lRow As Integer
Dim destLRow As Integer
Dim Lastrow As Long
Dim FirstRow As Long
Dim UpdateDate As String
ThisWB = ActiveWorkbook.Name
Dim selectedFolder
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
selectedFolder = .SelectedItems(1) & "\"
End With
path = selectedFolder
Application.EnableEvents = False
Application.ScreenUpdating = False
Set shtDest = Workbooks("GPnewchapterTEST2.xlsm").Worksheets("START")
'clear content of destination table
shtDest.Rows("8:" & Rows.Count).ClearContents
Filename = Dir(path & "\*.xls*", vbNormal)
If Len(Filename) = 0 Then Exit Sub
Do Until Filename = vbNullString
Set Wkb = Workbooks.Open(Filename:=path & "\" & Filename)
'MsgBox Filename
'''''
'SEC
'''''
If InStr(Filename, "Equipment") <> 0 Then
Dim range1 As Range
Set range1 = Range("E:K")
'For Each Wkb In Application.Workbooks
'For Each shtDest In Wkb.Worksheets
'Set shtPull = Wkb.Sheets(1)
'If shtPull.Name Like "*-*" Then
'last row
destLRow = Wkb.Sheets(1).Cells.Find(what:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row
'1st row
lRow = Wkb.Sheets(1).Cells.Find(what:="EQUIPMENT DESCRIPTION", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
'STHours
Dim i As Integer
For i = lRow To destLRow
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 5).Address, Cells(i, 11).Address)
Set DestRng = shtDest.Range("O" & shtDest.Cells(Rows.Count, "O").End(xlUp).Row + 1)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 1).Address, Cells(i, 1).Address)
Set DestRng = shtDest.Range("C" & shtDest.Cells(Rows.Count, "O").End(xlDown).Row)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 3).Address, Cells(i, 3).Address)
Set DestRng = shtDest.Range("S" & shtDest.Cells(Rows.Count, "O").End(xlUp).Row)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
i = i + 2
Next i
'Dim cell As Integer
'Dim empname As String
'destLRow = 8 '' find out how to find first available row
'For cell = 2 To lRow
'empname = Wkb.Sheets(1).Cells(cell, 3).Value & " " & Wkb.Sheets(1).Cells(cell, 4).Value
' shtDest.Cells(8, 5).Value = empname
'shtDest.Cells(8, 1).Value = "Service Electric"
'Next cell
' Wkb.Close Save = False
End If
'End If
Filename = Dir()
Loop
MsgBox "Done!"
End Sub
if you want to do in VBA and want to copy one value in "ALL" column
Cells(1,1).Copy Columns(1)
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)
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
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
I have a main workbook and a sub workbook that macro commands to open
1) Main workbook = Database
Worksheet in Main Workbook = Customer database
Sub workbook = Orders
These two books are open for macro to run.
1) I need to import data Range C:F from Orders to Customer Database B:E if Cell B from Orders contains New Member
2) The worksheet in database already contains data. Hence, I want it to add on to the existing sheet in Database
Please help.
Dim wsSource As Worksheet
Dim wbSource As Workbook
Dim wsTarget As Worksheet
Dim wbTarget As Workbook
Dim findRange As Range
Dim lastline As Integer
Dim file As String
file = "Orders.xlsx"
Set wbSource = ThisWorkbook
Set wsSource = wbSource.Sheets(1)
Set wbTarget = Workbooks.Open(file)
Set wsTarget = wbTarget.Sheets(1)
wsTarget.Activate
Set findRange = wsTarget.Range("C2:F389")
findRange.Replace What:="xxx-string",Replacement:=wsSource.Range("b2:e2").Value, LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False
lastline = wbSource.Sheets(1).Range("X65536").End(xlUp).Row
Dim d As Integer
Dim j As Integer
d = 3
j = 2
For b = 1 To lastline
If wsTarget.Range("B" & j) = "New Member" Then
d = d + 1
wsSource.Range("B" & j).Value = wsTarget.Range("C" & d).Value
wsSource.Range("C" & j).Value = wsTarget.Range("D" & d).Value
wsSource.Range("D" & j).Value = wsTarget.Range("E" & d).Value
wsSource.Range("E" & j).Value = wsTarget.Range("F" & d).Value
End If
j = j + 1
Next b
This answer is based on items 1 and 2 you enumerated above.
I'm not sure what you want to accomplish with the .Replace method so I remove it.
Sub Consolidate()
Dim wsSource As Worksheet
Dim wbSource As Workbook
Dim wsTarget As Worksheet
Dim wbTarget As Workbook
Dim findRange As Range
Dim lastline As Integer
Dim file As Variant '~~> declared as Variant
Set wbSource = Thisworkbook
Set wsSource = wbSource.Sheets(1) '~~>use index only if you have 1 sheet only
file = Application.GetOpenFilename("Excel Files, *.xlsx") '~~> allows you to select the file to load
If file <> False Then
Set wbTarget = Workbooks.Open(file)
Set wsTarget = wbTarget.Sheets(1)
With wsTarget
lastline = .Range("B" & .Rows.Count).End(xlUp).Row
Set findRange = .Range("B1:F" & lastline)
With findRange
.Autofilter 1, "New Member"
.Offset(1,1).Resize(.Rows.Count-1, .Columns.Count-1).SpecialCells(xlCellTypeVisible).Copy _
wsSource.Range("B" & wsSource.Rows.Count).End(xlUp).Offset(1,0)
End With
End With
Else
MsgBox "No file selected. Exiting now." : Exit Sub
End If
wbTarget.Close False
wbSource.Save
End Sub
No need to loop through the whole range.
I used .AutoFilter method instead.
Hope this is close to what you want.