Option Explicit
Sub test()
Dim rg As Range
Dim name As String
Dim name2 As String
Dim wsh1 As Worksheet, wsh2 As Worksheet
Dim i As Long
Set wsh1 = ThisWorkbook.Worksheets("Database")
Set wsh2 = ThisWorkbook.Worksheets("Løbs-skabelon")
On Error GoTo 0
Application.ScreenUpdating = False
name = wsh2.Range("a" & Rows.Count).End(xlUp).Value
name2 = wsh2.Range("e" & Rows.Count).End(xlUp).Value
For i = 1 To wsh1.Range("a" & Rows.Count).End(xlUp).Row
If wsh1.Cells(i, 1) = name And wsh1.Cells(i, 5) = name2 Then
wsh1.Range(wsh1.Cells(i, 1), wsh1.Cells(i, 9)).Copy
wsh2.Range("a" & Rows.Count).End(xlUp).PasteSpecial xlPasteValues
Application.CutCopyMode = False
End If
Next i
Application.ScreenUpdating = True
Worksheets("Løbs-skabelon").Range("a3").Select
Exit Sub
End Sub
I have two sheets. One is a database containing all information in rows from columns A to I. In the other sheet, I have the same structure in columns but only info in column A and E which will give a unique combination of only matching one row in database.
So ONLY when the cell in column A and E match a row in the database, I want the full row from the database copied into this row. My vba so far only copies one row/last row...
worksheet
database
Update Worksheet Rows
Option Explicit
Sub UpdateWorksheetRows()
Const sName As String = "Database"
Const sfRow As Long = 5
Const dName As String = "Lobs-skabelon"
Const dfRow As Long = 5
Dim sws As Worksheet: Set sws = ThisWorkbook.Worksheets(sName)
Dim slRow As Long: slRow = sws.Range("A" & sws.Rows.Count).End(xlUp).Row
Dim srCount As Long: srCount = slRow - sfRow + 1
Dim srg1 As Range: Set srg1 = sws.Range("A5").Resize(srCount)
Dim srg2 As Range: Set srg2 = sws.Range("E5").Resize(srCount)
Dim dws As Worksheet: Set dws = ThisWorkbook.Worksheets(dName)
Dim dlRow As Long: dlRow = dws.Range("A" & dws.Rows.Count).End(xlUp).Row
Dim drCount As Long: drCount = dlRow - dfRow + 1
Application.ScreenUpdating = False
Dim sIndex As Variant
Dim r As Long
For r = dfRow To dlRow
sIndex = dws.Evaluate("MATCH(1,('" & sName & "'!" & srg1.Address & "=" _
& dws.Range("A" & r).Address & ")*('" & sName & "'!" _
& srg2.Address & "=" & dws.Range("E" & r).Address & "),0)")
If IsNumeric(sIndex) Then
'Debug.Print r, sIndex
dws.Rows(r).Columns("A:I").Value _
= srg1.Cells(sIndex).EntireRow.Columns("A:I").Value
End If
Next r
Worksheets("Lobs-skabelon").Range("A3").Select
Application.ScreenUpdating = True
MsgBox "Worksheet rows updated.", vbInformation
End Sub
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
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
I am trying to program a Search button to look through all the data, return all rows with the common Number and all the date which is 9 columns of data, then populate and print the sheet with this data. the code is continuously giving me errors, any help is appreciated.
Dim erow As Long
Dim ws As Worksheet
Dim Lastrow As Long
Dim count As Integer
With Worksheets("DataSheet")
Lastrow = .Cells(.Rows.count, 1).End(x1Up).Row
For x = 1 To Lastrow
If Sheets("DataSheet").Cells(x, 1) = SearchSheet.Range("B4") Then
SearchSheet.Range("A12") = Sheets("DataSheet").Cells(x, 1)
SearchSheet.Range("B12") = Sheets("DataSheet").Cells(x, 2)
SearchSheet.Range("C12") = Sheets("DataSheet").Cells(x, 3)
SearchSheet.Range("D12") = Sheets("DataSheet").Cells(x, 4)
SearchSheet.Range("E12") = Sheets("DataSheet").Cells(x, 5)
SearchSheet.Range("F12") = Sheets("DataSheet").Cells(x, 6)
SearchSheet.Range("G12") = Sheets("DataSheet").Cells(x, 7)
SearchSheet.Range("H12") = Sheets("DataSheet").Cells(x, 8)
SearchSheet.Range("I12") = Sheets("DataSheet").Cells(x, 9)
End If
Next x
End With
Hard to see the difference between one and L but x1Up should be xlUp. All the results are being written to the same row 12, you need to use an incrementing counter.
Private Sub CommandButton1_Click()
Const SEARCH_CELL = "B4"
Const START_ROW = 12
Dim wb As Workbook, wsSource As Worksheet, wsTarget As Worksheet
Set wb = ThisWorkbook
Set wsSource = wb.Sheets("DataSheet")
Set wsTarget = wb.Sheets("SearchSheet")
Dim iRow As Long, iLastRow As Long, iTargetRow As Long
Dim sSearchTerm As String, res As Variant
iTargetRow = START_ROW
sSearchTerm = wsTarget.Range(SEARCH_CELL)
' clear results sheet
wsTarget.Range("A" & START_ROW & ":I" & Rows.count).Cells.Clear
'search
With wsSource
iLastRow = .Cells(.Rows.count, 1).End(xlUp).Row
For iRow = 1 To iLastRow
If .Cells(iRow, 1) = sSearchTerm Then
.Range("A" & iRow).Resize(1, 9).Copy wsTarget.Range("A" & iTargetRow)
iTargetRow = iTargetRow + 1
End If
Next
End With
' results
With wsTarget
.PageSetup.PrintArea = .Range("A1").Resize(iTargetRow - 1, 9).Address
res = MsgBox(iTargetRow - START_ROW & " Rows found, do you want to print results ?", vbYesNo, "Finished")
If res = vbYes Then
' print
.PrintOut Copies:=1
End If
End With
End Sub
I have written the below code but i would like the macro to repeat this process, copying the next row down in the SS21 Master Sheet until that row is blank (the end of the table).
Something like this?
Sub Run_Buysheet()
Sheets("SS21 Master Sheet").Range("A1:AH1, AJ1:AK1, AQ1").Copy Destination:=Sheets("BUYSHEET").Range("A1")
Sheets("SS21 Master Sheet").Range("A2:AH2, AJ2:AK2, AQ2").Copy Destination:=Sheets("BUYSHEET").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
Dim r As Range, i As Long, ar
Set r = Worksheets("BUYSHEET").Range("AK999999").End(xlUp) 'Range needs to be column with size list
Do While r.Row > 1
ar = Split(r.Value, "|") '| is the character that separates each size
If UBound(ar) >= 0 Then r.Value = ar(0)
For i = UBound(ar) To 1 Step -1
r.EntireRow.Copy
r.Offset(1).EntireRow.Insert
r.Offset(1).Value = ar(i)
Next
Set r = r.Offset(-1)
Loop
End Sub
SS21 Master Sheet
BUYSHEET
This scans the MASTER sheet and adds rows to the bottom of the BUYSHEET
Sub runBuySheet2()
Const COL_SIZE As String = "AQ"
Dim wb As Workbook, wsSource As Worksheet, wsTarget As Worksheet
Set wb = ThisWorkbook
Dim iLastRow As Long, iTarget As Long, iRow As Long
Dim rngSource As Range, ar As Variant, i As Integer
Set wsSource = wb.Sheets("SS21 Master Sheet")
Set wsTarget = wb.Sheets("BUYSHEET")
iLastRow = wsSource.Range("A" & Rows.Count).End(xlUp).Row
iTarget = wsTarget.Range("AK" & Rows.Count).End(xlUp).Row
With wsSource
For iRow = 1 To iLastRow
Set rngSource = Intersect(.Rows(iRow).EntireRow, .Range("A:AH, AJ:AK, AQ:AQ"))
If iRow = 1 Then
rngSource.Copy wsTarget.Range("A1")
iTarget = iTarget + 1
Else
ar = Split(.Range(COL_SIZE & iRow), "|")
For i = 0 To UBound(ar)
rngSource.Copy wsTarget.Cells(iTarget, 1)
wsTarget.Range("AK" & iTarget).Value = ar(i)
iTarget = iTarget + 1
Next
End If
Next
MsgBox "Completed"
End With
End Sub