Copy and pasting to a template and saving as new workbook - excel

I'm trying to loop through and paste each different group of IDs into a template I have in a separate workbook. I then want it to save as a new workbook, using the Vendor Name in C1 of the second sheet in the new workbook.
But there's a few problems in me trying to complete this;
It is giving me an error at the SaveAs line.
The filename is not pulling from the cell I want.
It stops after the first loop.
Anybody have any ideas of what I need to fix?
Here is my current macro:
Option Explicit
SubNewBillback()
Dim wsBData, wsBackup, wsCreditMemo As Worksheet
Dim wb, wbTemplate, wbAllRebates As Workbook
Dim rngHeader As Range
Dim i As Long, n As Long, LastRow As Long, StartRow As Long
Dim InvNum, InvDate, VendName, VendNum, strPath, FileName, openfile As String
Dim Amt As Integer
strPath = "\\Billback Data Base-Spreadsheet\2021\September\Excel\"
openfile = "\\Billback Data Base-Spreadsheet\2021\September\BillbackAutoTemplate.xlsx"
Set wbAllRebates = ActiveWorkbook
With wbAllRebates
Set wsBData = .Sheets("BackupData")
Set wsBackup = .Sheets("Backup")
End With
'copy data from query
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
StartRow = 2
Application.ScreenUpdating = False
'searches for change in ID#
With wsBackup
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rngHeader = .Range("A1:O1")
For i = 2 To LastRow
' change ID next row
If .Cells(i, "A") <> .Cells(i + 1, "A") Then
' create new workbook
Set wbTemplate = Workbooks.Open(openfile)
.Range("A" & StartRow & ":O" & i).Copy wbTemplate.Sheets(2).Range("A2")
wbTemplate.SaveAs FileName:=strPath & Sheets(2).Cells(i, "C") & ".xlsx"
wbTemplate.Close True
' move to next
StartRow = i + 1
n = n + 1
End If
Next
End With
Application.ScreenUpdating = True
MsgBox n & " billbacks created."
End Sub

The function at the bottom will remove invalid characters from your file name. I've added the call to the function in your Save As line in your original code. It will replace any of the following characters in the vendor name : \ / ? | * [ ] { } < > ~ " # % & with a _. If you would rather it replace it with something else just change the "_" in the line sFileName = Replace(sFileName, Mid(vInval, i, 1), "_") to some other valid character
Option Explicit
Sub NewBillback()
Dim wsBData, wsBackup, wsCreditMemo As Worksheet
Dim wb, wbTemplate, wbAllRebates As Workbook
Dim rngHeader As Range
Dim i As Long, n As Long, LastRow As Long, StartRow As Long
Dim InvNum, InvDate, VendName, VendNum, strPath, FileName, openfile As String
Dim Amt As Integer
strPath = "\\Billback Data Base-Spreadsheet\2021\September\Excel\"
openfile = "\\Billback Data Base-Spreadsheet\2021\September\BillbackAutoTemplate.xlsx"
Set wbAllRebates = ActiveWorkbook
With wbAllRebates
Set wsBData = .Sheets("BackupData")
Set wsBackup = .Sheets("Backup")
End With
'copy data from query
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
StartRow = 2
Application.ScreenUpdating = False
'searches for change in ID#
With wsBackup
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rngHeader = .Range("A1:O1")
For i = 2 To LastRow
' change ID next row
If .Cells(i, "A") <> .Cells(i + 1, "A") Then
' create new workbook
Set wbTemplate = Workbooks.Open(openfile)
.Range("A" & StartRow & ":O" & i).Copy wbTemplate.Sheets(2).Range("A2")
wbTemplate.SaveAs FileName:=strPath & ValidateFileName(Sheets(2).Cells(i, "C")) & ".xlsx"
wbTemplate.Close True
' move to next
StartRow = i + 1
n = n + 1
End If
Next
End With
Application.ScreenUpdating = True
MsgBox n & " billbacks created."
End Sub
Function ValidateFileName(ByVal sFileName As String) As String
Dim vInval As String
Dim i As Long
vInval = ":\/?|*[]{}<>~""#%&" & Chr(10) & Chr(13)
For i = 1 To Len(vInval)
sFileName = Replace(sFileName, Mid(vInval, i, 1), "_")
Next i
ValidateFileName = sFileName
End Function

Related

select data from one sheet and copy them to new different workbooks based on a specific colum value

I have a sheet like the following one (the real sheet contains 120 columns)
I would like to select the data based on the value of the Category column D, and create a new workbook by category with the total amount of each category.
So based on the sheet above, I would like using VBA code to create new workbooks, one for each category (something like New Worbook called category A, New Worbook called category B etc...)
I know how to create a new workbook, but I don't know how to select the data by category (unique) before creating a new workbook and paste them into the new workbook. Should I create a loop for and test the value for each cell in the colum D ? should I use filters to filter unique values ?
can any of you guide or help me on how to do that please ?
I got it work, so I will post my own answer, to help anyone who has a similar work to do.
Thanks to anyone who read this question or tried to help even if he couldn't.
Public Sub LaunchProg()
Call FilterData
Call CreateCategoriesFiles
End Sub
Public Sub FilterData()
'This Sub will filter data to get a colum with unique values of categories after joining column CX and CY
'"CX" contains first column of categories
'"CY" contains second column of categories
Dim MyColumn As String
Dim MyLastRow As Long
Dim SheetGroupe5 As Worksheet
Dim TempData As Worksheet
Dim RangeToFilter As String
Dim RangeFiltered As String
Dim StartAt As Integer
Dim copyFrom As String
Dim copyTo As String
Dim ToColumn As String
Const TempRegA As String = "E"
Const TempRegB As String = "F"
Const TempRegAB As String = "G"
Const TempHeader As Integer = 1
Set SheetGroupe5 = Groupe5
Set TempData = Tempo
'Copiying Data from the sheet called Groupe5 (Column CX) , to a temporary sheet called TempData
MyColumn = "CX"
'Range that we want to filter
RangeToFilter = MyColumn & ":" & MyColumn
'Destination range after filtering
RangeFiltered = TempRegA & TempHeader & ":" & TempRegA & TempHeader
'select the data using AdvancedFilter
'copy the selection to TempData
SheetGroupe5.Range(RangeToFilter).AdvancedFilter xlFilterCopy, , TempData.Range(RangeFiltered), True
'Copiying Data from the sheet called Groupe5 (Column CY) , to a temporary sheet called TempData
MyColumn = "CY"
'Range that we want to filter
RangeToFilter = MyColumn & ":" & MyColumn
'Destination range after filtering
RangeFiltered = TempRegB & TempHeader & ":" & TempRegB & TempHeader
'select the data using AdvancedFilter
'copy the selection to TempData
SheetGroupe5.Range(RangeToFilter).AdvancedFilter xlFilterCopy, , TempData.Range(RangeFiltered), True
'Copy the 2 columns of category into 1 column
'First column
MyColumn = TempRegA
MyLastRow = GetLastRow(TempData, MyColumn)
StartAt = TempHeader + 1
ToColumn = TempRegAB
If MyLastRow >= TempHeader + 1 Then
copyFrom = MyColumn & StartAt & ":" & MyColumn & MyLastRow
copyTo = ToColumn & StartAt & ":" & ToColumn & MyLastRow
TempData.Range(copyFrom).Copy TempData.Range(copyTo)
End If 'If MyLastRow >= StartAt Then
'second column
MyColumn = TempRegB
MyLastRow = GetLastRow(TempData, MyColumn)
StartAt = GetLastRow(TempData, ToColumn) + 1
If MyLastRow >= TempHeader + 1 Then
copyFrom = MyColumn & TempHeader + 1 & ":" & MyColumn & MyLastRow
copyTo = ToColumn & StartAt & ":" & ToColumn & (MyLastRow + StartAt)
TempData.Range(copyFrom).Copy TempData.Range(copyTo)
End If 'If MyLastRow >= StartAt Then
'Filter the data of the new created column using AdvancedFilter to get unique values
MyColumn = TempRegAB
MyLastRow = GetLastRow(TempData, MyColumn)
RangeToFilter = MyColumn & ":" & MyColumn
Debug.Print RangeToFilter
RangeFiltered = "D" & TempHeader & ":" & "D" & TempHeader
TempData.Range(RangeToFilter).AdvancedFilter xlFilterCopy, , TempData.Range(RangeFiltered), True
TempData.Range("A1").AutoFilter
Groupe5.Range("A1").AutoFilter
End Sub
Public Function GetLastRow(TheSheet As Worksheet, ColName As String) As Long
'Get last row of a given column for a given sheet
Dim LastRow As Long
LastRow = TheSheet.Columns(ColName).Cells.Find("*", SearchOrder:=xlByRows, LookIn:=xlValues, SearchDirection:=xlPrevious).Row
GetLastRow =LastRow
End Function
Public Sub CreateClientsFiles()
'This sub will create a workbook for each category after selecting the corresponding data for each category using the AutoFilter
'"CZ" contains all categories that I want to convert into files
Dim SheetGroupe5 As Worksheet
Dim TempData As Worksheet
Dim MyFolder As String
Dim MyExtension As String
Dim StartAt As Integer
Dim DistinctRange As String
Dim vArray As Variant
Dim iRow As Long
Dim iCol As Long
Dim wb As Workbook
Dim wsNewSht As Worksheet
Dim sCriteria1 As String
Dim sCriteria2 As String
Dim MyColumn As String
Dim RangeToFilter As String
Dim MyNewName As String
Dim FullFileName As String
Dim ToRange As String
Dim sFormulaMonth As String
Dim sFormulaYear As String
Const TempHeader As Integer = 1
Const Groupe5Header As Integer = 1
MyFolder = "C:\MyFolder\"
MyExtension = ".xlsx"
Set SheetGroupe5 = Groupe5
Set TempData = Tempo
'I have another temporay sheet called DataToFile
'I will store at this sheet each category before saving it to a workbook
Set wsNewSht = DataToFile
StartAt = TempHeader + 1
MyColumn = "D"
MyLastRow = GetLastRow(TempData, MyColumn)
DistinctRange = MyColumn & StartAt & ":" & MyColumn & MyLastRow
vArray = TempData.Range(DistinctRange).Value2
Application.ScreenUpdating = False
iCol = 1
With SheetGroupe5
For iRow = 1 To UBound(vArray, 1)
MyNewName = vArray(iRow, iCol)
'Criterias based on my data
sCriteria1 = vArray(iRow, iCol) & " - " & "*"
sCriteria2 = "*" & " - " & vArray(iRow, iCol)
.AutoFilterMode = False
MyLastRow = GetLastRow(SheetGroupe5, "CZ")
RangeToFilter = "CZ" & Groupe5Header & ":" & "CZ" & MyLastRow
.Range(RangeToFilter).AutoFilter Field:=104, Criteria1 _
:=sCriteria1, Operator:=xlOr, Criteria2:=sCriteria2
'Rename the sheet using the category Name
wsNewSht.Name = MyNewName
wsNewSht.Cells.Clear
.UsedRange.SpecialCells(xlCellTypeVisible).Copy _
Destination:=wsNewSht.Range("A1")
'Create a new workbook
Set wb = Workbooks.Add
wsNewSht.Copy Before:=wb.Sheets(1)
MyNewName = vArray(iRow, iCol)
FullFileName = MyFolder & MyNewName & MyExtension
wb.SaveAs FullFileName
wb.Close savechanges:=True
Next iRow
'Apply back Autofilter
.ShowAllData
End With
Application.ScreenUpdating = True
End Sub

Loop through 50,000+ rows and copy data until value in the first column changes

I have an Excel sheet with 50,000+ rows of data from A:N. I have a Master Data Sheet that has a query in the BackupData worksheet. I currently copy that data and paste as values into the Backup worksheet. With the headers:
ID
Vendor #
Name
Customer #
Customer
Invoice #
Date
Item#
Item Description
Qty
B/C
Lbs
Amt
Amt#2
I am trying to loop through all of these rows and copy the range of cells A:N until the first value change in Column A, the first different ID #.
I then need to paste the selected range into a new workbook.
Basically, I want to do the opposite of consolidating.
Sub inserting()
Dim wsBData, wsExport, wsCoverSht, wsBackup As Worksheet
Dim wbAllRebates, wbSingle As Workbook
Set wbAllRebates = ActiveWorkbook
Set wsBData = wbAllRebates.Sheets("BackupData")
Set wsBackup = wbAllRebates.Sheets("Backup")
Dim rID, rTopRow As Range
Dim i As Long
Dim Counter As Integer
i = 3
Set rTopRow = Rows(1)
Set rID = wsBackup.Range("A1")
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
Counter = 0
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Do
If rID.Offset(i).Value <> rID.Offset(i - 1).Value Then
Rows(rID.Offset(i).Row).Insert shift:=xlDown
Call SubTotals(rID.Offset(i), rTopRow)
i = i + 1
Set rTopRow = Rows(rID.Offset(i).Row)
End If
Exit Do
Loop
MsgBox i
End Sub
Sub SubTotals(rID As Range, firstRow As Range)
rID.Value = "Total"
rID.Offset(, 9).Value = Application.WorksheetFunction.Sum(Range(firstRow.Cells(1, 10).Address & ":" & rID.Offset(-1, 1).Address))
End Sub
Try
Option Explicit
Sub SeparateWB()
Dim wsBData As Worksheet, wsBackup As Worksheet, wb As Workbook
Dim wbAllRebates As Workbook, rngHeader As Range
Dim i As Long, n As Long, LastRow As Long, StartRow As Long
Set wbAllRebates = ActiveWorkbook
With wbAllRebates
Set wsBData = .Sheets("BackupData")
Set wsBackup = .Sheets("Backup")
End With
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
StartRow = 2
Application.ScreenUpdating = False
With wsBackup
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rngHeader = .Range("A1:N1")
For i = 2 To LastRow
' change ID next row
If .Cells(i, "A") <> .Cells(i + 1, "A") Then
' create new workbook
Set wb = Workbooks.Add(1)
rngHeader.Copy wb.Sheets(1).Range("A1")
.Range("A" & StartRow & ":N" & i).Copy wb.Sheets(1).Range("A2")
wb.SaveAs .Cells(i, "A") & ".xlsx"
wb.Close False
' move to next
StartRow = i + 1
n = n + 1
End If
Next
End With
Application.ScreenUpdating = True
MsgBox n & " workbooks created"
End Sub

Excel Macro updating rows in a file with new data

The code below runs and executes perfectly, I just want to add some features. The code imports the new rows from Report file to Workbook file, and I want it to check for a potential row with new data by every cell in the row, and not by just column G(contains number or numbers separated by comma), but in range A2:BQ. Also update the newly found cells even if the row exists in Workbook by the number in column G. Also to highlight the new rows with a bright color in the Workbook file. One last thing is to wrap the text after the importing of new cells finishes.
Sub Weekly_Report()
Const HAS_HEADER As Boolean = True 'Set true if the file has a header(Report)
Const NUM_COLS As Long = 69 '69 rows needed to be imported from the Report
Const FILENAME = "Report.xlsx"
Const PATH = "C:\Users\Documents\" 'path of the report
Dim wbReport As Workbook, wsReport As Worksheet, wsData As Worksheet
Dim next_blank_row As Long, iStartRow As Long, iLastRow As Long, iRow As Long
Dim sFilename As String
Set wsData = ThisWorkbook.Worksheets("Sheet1") 'for example: destination worksheet
next_blank_row = wsData.Cells(Rows.Count, "G").End(xlUp).Row + 1 'next blank row
sFilename = PATH & FILENAME
Debug.Print "Opening ", sFilename 'Openning file
On Error Resume Next
Set wbReport = Workbooks.Open(sFilename)
On Error GoTo 0
If wbReport Is Nothing Then
MsgBox "Can not open " & sFilename, vbCritical, "ERROR" 'If the file was not found or cannot be opened
Exit Sub
End If
Set wsReport = wbReport.Worksheets(1) 'Expects only one sheet in the Report
iStartRow = IIf(HAS_HEADER, 2, 1) 'If it has header start from row 2
iLastRow = wsReport.Cells(Rows.Count, 1).End(xlUp).Row
Dim s As String, rng As Range, m As Long
For iRow = iStartRow To iLastRow
s = CStr(wsReport.Cells(iRow, "G").Value)
Set rng = wsData.Columns("A:BQ").Find(s)
If rng Is Nothing Then
m = next_blank_row 'no match - use next blank row and increment
next_blank_row = next_blank_row + 1
Debug.Print iRow, s, "New row " & m
Else
m = rng.Row
Debug.Print iRow, s, "Match row " & m 'Match row:if the line already exists in the file
End If
wsData.Cells(m, 1).Resize(1, NUM_COLS).Value = wsReport.Cells(iRow, 1).Resize(1, NUM_COLS).Value 'Put the new line in Workbook
Next
MsgBox wsReport.Name & " scanned from row " & iStartRow & _
" to " & iLastRow, vbInformation, sFilename
wbReport.Close False 'Close the Report
End Sub
This updates column P and S for rows matching column G or adds the rows if no match.
Option Explicit
Sub Weekly_Report()
Const HAS_HEADER As Boolean = True 'Set true if the file has a header(Report)
Const NUM_COLS As Long = 69 '69 cells in the row needed to be imported from the Report
Const FILENAME = "Report.xlsx"
Const PATH = "C:\Users\Documents\" 'path of the report
Dim wbReport As Workbook, wsReport As Worksheet, wsData As Worksheet
Dim next_blank_row As Long, iStartRow As Long, iLastRow As Long, iRow As Long
Dim sFilename As String
Set wsData = ThisWorkbook.Worksheets("Sheet1") 'for example: destination worksheet
next_blank_row = wsData.Cells(Rows.Count, "G").End(xlUp).Row + 1 'next blank row
sFilename = PATH & FILENAME
Debug.Print "Opening ", sFilename 'Openning file
On Error Resume Next
Set wbReport = Workbooks.Open(sFilename)
On Error GoTo 0
If wbReport Is Nothing Then
MsgBox "Can not open " & sFilename, vbCritical, "ERROR" 'If the file was not found or cannot be opened
Exit Sub
End If
Set wsReport = wbReport.Worksheets(1) 'Expects only one sheet in the Report
iStartRow = IIf(HAS_HEADER, 2, 1) 'If it has header start from row 2
iLastRow = wsReport.Cells(Rows.Count, 1).End(xlUp).Row
Dim rng As Range, rng2 As Range, rng3 As Range
Dim m As Long, m2 As String, m3 As String, s As String, s2 As String, s3 As String, c As Variant
Dim iAdd As Long, iUpdate As Long
For iRow = iStartRow To iLastRow
s = CStr(wsReport.Cells(iRow, "G").Value)
Set rng = wsData.Columns("G").Find(s)
If rng Is Nothing Then
m = next_blank_row 'no match - use next blank row and increment
next_blank_row = next_blank_row + 1
With wsData.Cells(m, 1).Resize(1, NUM_COLS)
.Value = wsReport.Cells(iRow, 1).Resize(1, NUM_COLS).Value
.Interior.Color = vbYellow
End With
iAdd = iAdd + 1
Debug.Print iRow, s, "New row " & m
Else
m = rng.Row
For Each c In Array("P", "S")
If wsData.Cells(m, c) <> CStr(wsReport.Cells(iRow, c).Value) Then
wsData.Cells(m, c) = CStr(wsReport.Cells(iRow, c).Value)
wsData.Cells(m, c).Interior.Color = vbGreen
iUpdate = iUpdate + 1
End If
Next
Debug.Print iRow, s, "Match row " & m 'Match row:if the line already exists in the file
End If
Next
MsgBox wsReport.Name & " scanned from row " & iStartRow & _
" to " & iLastRow & vbCrLf & "added rows = " & iAdd & vbCrLf & _
"updated cells = " & iUpdate, vbInformation, sFilename
wbReport.Close False 'Close the Report
End Sub
Since you seem to be stuck on comparing two ranges:
'Do two ranges contain the same value(s)?
' does not handle error values...
Function RangesMatch(rng1 As Range, rng2 As Range) As Boolean
Dim rv As Boolean, v1, v2, r As Long, c As Long
If rng1.Rows.Count = rng2.Rows.Count And _
rng1.Columns.Count = rng2.Columns.Count Then
v1 = rng1.Value
v2 = rng2.Value
If rng1.Count = 1 Then
RangesMatch = (v1 = v2) 'single cell ranges...
Else
'multi-cell ranges: loop and compare values
For r = 1 To UBound(v1, 1)
For c = 1 To UBound(v1, 2)
If v1(r, c) <> v2(r, c) Then
Exit Function 'by default returns false
End If
Next c
Next r
RangesMatch = True
End If
End If
End Function
This is how far I got:
Sub Weekly_Report()
Const HAS_HEADER As Boolean = True 'Set true if the file has a header(Report)
Const NUM_COLS As Long = 69 '69 cells in the row needed to be imported from the Report
Const FILENAME = "Report.xlsx"
Const PATH = "C:\Users\Documents\" 'path of the report
Dim wbReport As Workbook, wsReport As Worksheet, wsData As Worksheet
Dim next_blank_row As Long, iStartRow As Long, iLastRow As Long, iRow As Long
Dim sFilename As String
Set wsData = ThisWorkbook.Worksheets("Sheet1") 'for example: destination worksheet
next_blank_row = wsData.Cells(Rows.Count, "G").End(xlUp).Row + 1 'next blank row
sFilename = PATH & FILENAME
Debug.Print "Opening ", sFilename 'Openning file
On Error Resume Next
Set wbReport = Workbooks.Open(sFilename)
On Error GoTo 0
If wbReport Is Nothing Then
MsgBox "Can not open " & sFilename, vbCritical, "ERROR" 'If the file was not found or cannot be opened
Exit Sub
End If
Set wsReport = wbReport.Worksheets(1) 'Expects only one sheet in the Report
iStartRow = IIf(HAS_HEADER, 2, 1) 'If it has header start from row 2
iLastRow = wsReport.Cells(Rows.Count, 1).End(xlUp).Row
Dim s As String, rng As Range, m As Long, m2 As String, m3 As String, s2 As String, s3 As String, rng2 As Range, rng3 As Range
For iRow = iStartRow To iLastRow
s = CStr(wsReport.Cells(iRow, "G").Value)
Set rng = wsData.Columns("G").Find(s)
s2 = CStr(wsReport.Cells(iRow, "P").Value)
Set rng2 = wsData.Columns("P").Find(s2)
s3 = CStr(wsReport.Cells(iRow, "S").Value)
Set rng3 = wsData.Columns("S").Find(s3)
If rng Is Nothing Then
m = next_blank_row 'no match - use next blank row and increment
next_blank_row = next_blank_row + 1
Debug.Print iRow, s, "New row " & m
Else
m = rng.Row
Debug.Print iRow, s, "Match row " & m 'Match row:if the line already exists in the file
m2 = rng2.Row
m3 = rng3.Row
End If
wsData.Cells(m, 1).Resize(1, NUM_COLS).Value = wsReport.Cells(iRow, 1).Resize(1, NUM_COLS).Value
wsData.Cells(m2, 1).Resize(1, NUM_COLS).Value = wsReport.Cells(iRow, 1).Resize(1, NUM_COLS).Value
wsData.Cells(m3, 1).Resize(1, NUM_COLS).Value = wsReport.Cells(iRow, 1).Resize(1, NUM_COLS).Value
Next
MsgBox wsReport.Name & " scanned from row " & iStartRow & _
" to " & iLastRow, vbInformation, sFilename
wbReport.Close False 'Close the Report
End Sub

VBA Excel Macro not responding after execution

I am trying to import data from Report file to my workbook file. Also to do it automatically with different files with new data, so that I can update my rows in the workbook file. The code opens the Report file after executing but it is not responding.
Sub Weekly_Report()
Path = "C:\Users\Documents\Report"
Filename = Dir(Report & "*.xlsx")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Report, ReadOnly:=True
Loop
Dim starting_row As Long
header_exists = True 'If the file has a header and you don't want to import it, set this to True
starting_row = 1
If header_exists Then starting_row = 2
Dim first_blank_row As Long
first_blank_row = Cells.SpecialCells(xlCellTypeLastCell).Offset(1, 0).Row 'Finds the last blank row
Dim r As Long
r = starting_row
Dim Filenames As String
Filenames = Path
Dim found As Range
Row = Workbooks(Filenames).ActiveSheet.Range("a" & r).Value
Do While Not Row = ""
Set found = Columns("x:x").Find(what:=Row, LookIn:=xlValues, lookat:=xlWhole)
If found Is Nothing Then
write_line_from_export Filenames, r, first_blank_row
first_blank_row = first_blank_row + 1
Else
write_line_from_export Filenames, r, found.Row
End If
r = r + 1
Row = Workbooks(Filenames).ActiveSheet.Range("a" & r).Value
Loop
End Sub
Sub write_line_from_export(Filenames As String, s As Long, d As Long)
For e = 1 To 69
Cells(d, e).Value = Workbooks(Filenames).ActiveSheet.Cells(s, e).Value
Next e
End Sub
Try this:
Sub Weekly_Report()
Const HAS_HEADER As Boolean = True '<< use contants for fixed values
Const NUM_COLS As Long = 69
Dim Path, Filename, wbReport As Workbook, wsReport As Worksheet, m
Dim wsData As Worksheet, next_blank_row As Long, r As Long, c As Range, rwStart As Long
Path = "C:\Users\Documents\Report\"
Filename = Dir(Path & "Report*.xlsx") '???
Set wsData = ThisWorkbook.Worksheets("Data") 'for example: destination worksheet
next_blank_row = next_blank_row = wsData.Cells(Rows.Count, 1).End(xlUp).Row + 1 'next blank row (edited)
'make sure row is really empty...
Do While Application.CountA(wsData.Rows(next_blank_row)) > 0
next_blank_row = next_blank_row + 1
Loop
Do While Filename <> ""
Set wbReport = Workbooks.Open(Path & Filename) '<< get a reference to the workbook
Set wsReport = wbReport.Worksheets(1) '<< assumes only one sheet
rwStart = IIf(HAS_HEADER, 2, 1)
For r = rwStart To wsReport.Cells(Rows.Count, 1).End(xlUp).Row
'Match is faster than Find
m = Application.Match(wsReport.Cells(r, 1).Value, wsData.Columns("X"), 0)
If IsError(m) Then
m = next_blank_row 'no match - use next blank row and increment
next_blank_row = next_blank_row + 1
End If
'don't go cell-by-cell
wsData.Cells(m, 1).Resize(1, NUM_COLS).Value = _
wsReport.Cells(r, 1).Resize(1, NUM_COLS).Value
Next r
wbReport.Close False
Filename = Dir()
Loop
End Sub

Looping through multiple sheets at once

I am trying to run through a column and get the value in the cell. The value is a unique code and only appears once on the first sheet.
When i get a value, it could be the first cell, i want to go through a column in sheet 4. The unique code can appear multiple times on sheet 4.
I want to match the code from sheet one with the code from sheet 4. If the codes are matching, i want to save the colum value on the row index and insert it into a completely new workbook.
Sub exportSheet2()
Const START_ROW = 11
Const MAX_ROW = 40
Const CODE_SHT1 = "C"
Const CODE_SHT4 = "E"
Const CVR_SHT4 = "C"
Const CVR_SHT3 = "C"
Const WB_OUTPUT = "MyResult.xlsx"
' sheet 4 columns
'C - Employer CVR MD
'D - Employer name
'E - broker code
'F - Broker name
'? Employer CVR CER
Dim wb As Workbook, wbNew As Workbook
Dim ws1 As Worksheet, ws4 As Worksheet, wsNew As Worksheet
Dim iRow As Long, iLastRow, iTargetRow As Long, iCopyRow As Long
Dim msg As String, i As Integer
Dim count As Long, countWB As Integer
Dim WkSht_Src As Worksheet
Dim WkBk_Dest As Workbook
Dim WkSht_Dest As Worksheet
Dim Rng As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("BrokerSelect")
Set ws3 = wb.Sheets("ContributionExceptionReport")
Set ws4 = wb.Sheets("MasterData")
Dim dict As Object, sKey As String, ar As Variant
Set dict = CreateObject("Scripting.Dictionary")
' build dictionary from sheet4 of code to rows number
iLastRow = ws4.Cells(Rows.count, CODE_SHT4).End(xlUp).Row
For iRow = 13 To iLastRow
sKey = ws4.Cells(iRow, CODE_SHT4)
If dict.exists(sKey) Then
dict(sKey) = dict(sKey) & ";" & iRow ' matched row on sheet 1
Else
dict(sKey) = iRow
End If
Next
' scan down sheet1
count = 0: countWB = 0
iRow = START_ROW
Do Until (ws1.Cells(iRow, CODE_SHT1) = "END") Or (iRow > MAX_ROW)
sKey = ws1.Cells(iRow, CODE_SHT1)
If dict.exists(sKey) Then
' rows on sheet4 to copy
ar = Split(dict(sKey), ";")
'create new workbook and copy rows
Dim Pheight As Integer
Pheight = 25000
Set WkSht_Src = ThisWorkbook.Worksheets(2)
Set Rng = WkSht_Src.Range(ThisWorkbook.Worksheets(2).Cells(1, 1), ThisWorkbook.Worksheets(2).Cells(Pheight, 48))
Set WkBk_Dest = Application.Workbooks.Add
Set WkSht_Dest = WkBk_Dest.Worksheets(1)
Rng.Copy
WkSht_Dest.Range("A1").PasteSpecial xlPasteValuesAndNumberFormats
Rng.Copy
WkSht_Dest.Range("A1").PasteSpecial xlPasteFormats
WkSht_Src.Pictures(1).Copy
WkSht_Dest.Range("A1").PasteSpecial
WkSht_Dest.Pictures(1).Top = 5
WkSht_Dest.Pictures(1).Left = 0
iTargetRow = 11
Set wsNew = WkSht_Dest
Set wbNew = WkBk_Dest
For i = LBound(ar) To UBound(ar)
iCopyRow = ar(i)
iTargetRow = iTargetRow + 1
' copy selected cols to new workbook
ws4.Range("C" & iCopyRow).Resize(1, 5).Copy wsNew.Range("A" & iTargetRow)
count = count + 1
Next
wbNew.SaveAs sKey & ".xlsx"
wbNew.Close
countWB = countWB + 1
End If
iRow = iRow + 1
Loop
MsgBox dict.count & " keys in dictionary ", vbInformation
msg = iLastRow & " rows scanned on sheet4 " & vbCr & _
count & " rows copied to " & countWB & " new workbooks"
MsgBox msg, vbInformation
End Sub '''
Use a Dictionary Object not a loop in a loop.
Sub exportSheet2()
Const START_ROW = 11
Const MAX_ROW = 40
Const CODE_SHT1 = "C"
Const CODE_SHT4 = "E"
Const CVR_SHT4 = "C"
Const CVR_SHT3 = "C"
' sheet 4 columns
'C - Employer CVR MD
'D - Employer name
'E - broker code
'F - Broker name
'? Employer CVR CER
Dim wb As Workbook, wbNew As Workbook
Dim ws1 As Worksheet, ws3 As Worksheet, ws4 As Worksheet, wsNew As Worksheet
Dim iRow As Long, iLastRow, iTargetRow As Long, iCopyRow As Long
Dim msg As String, i As Integer, j As Integer
Dim count As Long, countWB As Integer
Dim WkSht_Src As Worksheet
Dim WkBk_Dest As Workbook
Dim WkSht_Dest As Worksheet
Dim Rng As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("BrokerSelect")
Set ws3 = wb.Sheets("ContributionExceptionReport")
Set ws4 = wb.Sheets("MasterData")
Dim dict As Object, dictCVR As Object, sKey As String, ar As Variant
Dim sCVR As String, arCVR As Variant
Set dict = CreateObject("Scripting.Dictionary")
Set dictCVR = CreateObject("Scripting.Dictionary")
' build dictionary from sheet4 of code to rows number
iLastRow = ws4.Cells(Rows.count, CODE_SHT4).End(xlUp).Row
For iRow = 13 To iLastRow
sKey = ws4.Cells(iRow, CODE_SHT4)
If dict.exists(sKey) Then
dict(sKey) = dict(sKey) & ";" & iRow ' matched row on sheet 1
Else
dict(sKey) = iRow
End If
Next
' build dictCVR from sheet3
iLastRow = ws3.Cells(Rows.count, CVR_SHT3).End(xlUp).Row
For iRow = 18 To iLastRow
sKey = ws3.Cells(iRow, CVR_SHT3)
If dictCVR.exists(sKey) Then
dictCVR(sKey) = dictCVR(sKey) & ";" & iRow
Else
dictCVR(sKey) = iRow
End If
Next
' scan down sheet1
count = 0: countWB = 0
iRow = START_ROW
Do Until (ws1.Cells(iRow, CODE_SHT1) = "END") Or (iRow > MAX_ROW)
sKey = ws1.Cells(iRow, CODE_SHT1)
If dict.exists(sKey) Then
' rows on sheet4 to copy
ar = Split(dict(sKey), ";")
'create new workbook and copy rows
Set WkSht_Src = wb.Worksheets(2)
Set Rng = WkSht_Src.Range("A1:AV25000")
Set WkBk_Dest = Application.Workbooks.Add
Set WkSht_Dest = WkBk_Dest.Worksheets(1)
With WkSht_Dest
Rng.Copy
.Range("A1").PasteSpecial xlPasteValuesAndNumberFormats
.Range("A1").PasteSpecial xlPasteFormats
WkSht_Src.Pictures(1).Copy
.Range("A1").PasteSpecial
.Pictures(1).Top = 5
.Pictures(1).Left = 0
End With
Application.CutCopyMode = False
iTargetRow = 11
Set wsNew = WkSht_Dest
Set wbNew = WkBk_Dest
For i = LBound(ar) To UBound(ar)
iCopyRow = ar(i)
iTargetRow = iTargetRow + 1
' copy selected cols to new workbook
ws4.Range("C" & iCopyRow).Resize(1, 5).Copy wsNew.Range("A" & iTargetRow)
' add cvr records from sheet3 it any
sCVR = ws4.Cells(iCopyRow, CVR_SHT4)
If dictCVR.exists(sCVR) Then
arCVR = Split(dictCVR(sCVR), ";")
For j = LBound(arCVR) To UBound(arCVR)
If j > 0 Then iTargetRow = iTargetRow + 1
' copy col A to P
iCopyRow = arCVR(j)
Debug.Print sCVR, j, iCopyRow
ws3.Range("A" & iCopyRow).Resize(1, 16).Copy wsNew.Range("E" & iTargetRow)
count = count + 1
Next
Else
count = count + 1
End If
Next
wbNew.SaveAs sKey & ".xlsx"
wbNew.Close
countWB = countWB + 1
End If
iRow = iRow + 1
Loop
msg = dict.count & " keys in CODE dictionary" & vbCr & _
dictCVR.count & " keys in CVR dictionary"
MsgBox msg, vbInformation
msg = iLastRow & " rows scanned on sheet4 " & vbCr & _
count & " rows copied to " & countWB & " new workbooks"
MsgBox msg, vbInformation
End Sub '''

Resources