Conditional formatting cells between sheets and outputing to a seperate cell - vba

Sub MatchLiquor()
Dim lastRowOne As Long
Dim lastRowTwo As Long
Dim sheetNameOne As String
Dim sheetNameTwo As String
sheetNameOne = "Recipies" 'Recipies Sheet
sheetNameTwo = "Liquor Breakdowns" 'Liquor Breakdowns
lastRowOne = Sheets(sheetNameOne).Range("B" & Rows.Count).End(xlUp).Row
lastRowTwo = Sheets(sheetNameTwo).Range("A" & Rows.Count).End(xlUp).Row
For lRow = 2 To lastRowOne 'Loop through all rows
For lRowTwo = 2 To lastRowTwo 'Loop through all rows
If Sheets(sheetNameOne).Cells(lRow, "B") = Sheets(sheetNameTwo).Cells(lRowTwo, "A") Then
Sheets(sheetNameOne).Cells(lRow, "C") * Sheets(sheetNameOne).Cells(lRowTwo, "E") Then
End If
Next lRowTwo
Next lRow
End Sub
In sudo, what I'm attempting to accomplish is such:
Search through all rows of sheetA for "name" and compare to sheetB "name"
Upon being found, multiply different value in sheetA with different value in sheetB; output values into different cell in sheetA (example E).
I haven't yet figured out how to output, or even if this will work.
Ideas?

There was some confusion as to which worksheets were used where and no target for the product on a match was provided but this should clear up your loops.
Sub MatchLiquor()
Dim lastRowOne As Long, lastRowTwo As Long, prodct As Double
Dim sheetNameOne As String, sheetNameTwo As String
sheetNameOne = "Recipies" 'Recipies Sheet
sheetNameTwo = "Liquor Breakdowns" 'Liquor Breakdowns
With Sheets(sheetNameOne)
lastRowOne = .Range("B" & Rows.Count).End(xlUp).Row
lastRowTwo = Sheets(sheetNameTwo).Range("A" & Rows.Count).End(xlUp).Row
For lRow = 2 To lastRowOne 'Loop through all rows on Recipies Sheet
For lRowTwo = 2 To lastRowTwo 'Loop through all rows on Liquor Breakdowns
If .Cells(lRow, "B") = Sheets(sheetNameTwo).Cells(lRowTwo, "A") Then
prodct = .Cells(lRow, "C").Value * Sheets(sheetNameTwo).Cells(lRowTwo, "E").Value
'do something with prodct
.cells(lRow, "E") = prodct
Exit For 'found match and computed product; no need to continue this lRowTwo
End If
Next lRowTwo
Next lRow
End With
End Sub
If a match was found and a product calculated (and put somewhere) there is no need to continue running through the internal nested loop with lRowTwo. Just Exit For which will take you back to the outside loop and the next lRow.
Using Sheets(sheetNameOne) in a With ... End With statement cuts down the parent worksheet references by half.

Related

copy lane from different sheet if the same value

I have 5 columns in sheet1, and the same in sheet 2.The name of the product is in A. But sometimes the caracteristics of the products (in B,C,D,E) can change in sheet 2. I want that it actualize the caracteristics in Sheet1.
I tried a Vlookup, but it works only zith one Cell
Sub test()
With Sheets("Feuil1")
.Range("B1").Value = WorksheetFunction.VLookup(.Range("A1").Value, Sheets("Feuil2").Range("A1:B100"), 2, False)
End With
End Sub
Moreover, I cant copy all the line because the colomn F should not changeā€¦ And products in sheet1 in column A are not tidy and get some duplicates...
You need a loop for this to update each row and you need to update each column as well.
I recommend to use WorksheetFunction.Match instead so you only need to match once per row to get the row number and then you can copy the desired values of that row.
Option Explicit
Public Sub UpdateData()
Dim WsDest As Worksheet 'destination workbook to write in
Set WsDest = ThisWorkbook.Worksheets("Feuil1")
Dim WsSrc As Worksheet 'source workbook to match with
Set WsSrc = ThisWorkbook.Worksheets("Feuil2")
Dim LastRow As Long 'last used row in workbook
LastRow = WsDest.Cells(WsDest.Rows.Count, "A").End(xlUp).Row
Dim iRow As Long, MatchedRow As Long
For iRow = 1 To LastRow 'loop through all rows from row 1 to last used row and update each row
MatchedRow = 0 'initialize
On Error Resume Next 'if no match found then ignore error
MatchedRow = WorksheetFunction.Match(WsDest.Cells(iRow, "A"), WsSrc.Columns("A"), 0) 'get the row number of the match
On Error GoTo 0 'reactivate error reporting
'if it didn't match then MatchedRow is still 0
If MatchedRow > 0 Then 'if a match was found then copy values
WsDest.Cells(iRow, "B").Value = WsSrc.Cells(MatchedRow, "B").Value
WsDest.Cells(iRow, "C").Value = WsSrc.Cells(MatchedRow, "C").Value
WsDest.Cells(iRow, "D").Value = WsSrc.Cells(MatchedRow, "D").Value
WsDest.Cells(iRow, "E").Value = WsSrc.Cells(MatchedRow, "E").Value
Else
'didn't find a match
'you can remove the Else part if you want to do nothing here
End If
Next iRow
End Sub
If the columns you want to copy are continous like B, C, D, E you can do it in one copy action which is faster than 4 copy actions (1 for each column):
WsDest.Range("B" & iRow & ":E" & iRow).Value = WsSrc.Range("B" & MatchedRow & ":E" & MatchedRow).Value

How to store records from an Excel form to different rows using VBA?

so I have this invoice form that looks like this in Sheet Invoice_Form of an Excel workbook InvoiceForm.xlsm:
and a database of invoice records in Sheet Invoice Database of an Excel workbook InvoiceDatabase.xlsm:
I have created VBA codes that can link records from the form to the invoice database, but what the code manages to do right now is only recording the first row of the invoice form:
The code looks like this:
Sub Submit_Invoice()
Dim LastRow As Long, ws As Worksheet
Set ws = Sheets("InvoiceDatabase")
LastRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1
ws.Range("K" & LastRow).Value = Worksheets("Invoice Form").Range("C9:C16").Value
ws.Range("L" & LastRow).Value = Worksheets("Invoice Form").Range("D9:D16").Value
....
End Sub
So the question is: How do I modify my code so that it can create multiple records on different rows based on this one form if there are additional products added in the invoice form?
Thanks!
Build an array from the form and dump the array into the InvoiceDatabase.
Sub Submit_Invoice()
Dim lr As Long, ws As Worksheet
dim arr as variant, i as long
with Worksheets("Invoice Form")
lr = .cells(16, "C").end(xlup).row - 8
redim arr(1 to lr, 1 to 6)
for i=lbound(arr,1) to ubound(arr, 1)
arr(i, 1) = .cells(5, "D").value
arr(i, 2) = .cells(6, "D").value
arr(i, 3) = .cells(i+8, "C").value
arr(i, 4) = .cells(i+8, "D").value
arr(i, 5) = .cells(i+8, "E").value
arr(i, 6) = .cells(i+8, "F").value
next i
end with
WITH WORKSheets("InvoiceDatabase")
lr = .Range("I" & .Rows.Count).End(xlUp).Row + 1
.cells(lr, "I").resize(ubound(arr, 1), ubound(arr, 2)) = arr
end with
End Sub
You really should use a form/access database or Excel data form (2016) to do this.
That said, your code is overwriting each row as your write to the other sheet as it isn't incremented. Also, you are missing how you add dates and invoice numbers.
The following uses more meaningful names and adds in the missing data, along with some basic error checks (e.g. there is data to transfer) and housekeeping in terms of clearing the form after transfer.
Option Explicit
Public Sub Submit_Invoice()
Dim nextRowDest As Long, lastRowSource As Long, wsDest As Worksheet, wsSource As Worksheet, transferData As Range
Dim invoiceInfo As Range
Application.ScreenUpdating = False
Set wsDest = ThisWorkbook.Worksheets("InvoiceDatabase")
Set wsSource = Workbooks("Invoice_Form.xlsm").Worksheets("Invoice Form")
With wsSource
lastRowSource = wsSource.Range("C" & .Rows.Count).End(xlUp).Row
If lastRowSource < 9 Then Exit Sub '<==No data
Set transferData = .Range("C9:G" & lastRowSource)
Set invoiceInfo = .Range("D5:D6")
End With
With wsDest
nextRowDest = wsDest.Range("I" & Rows.Count).End(xlUp).Row + 1
If nextRowDest < 4 Then Exit Sub '<==Assume headers are in row 3
transferData.Copy .Range("K" & nextRowDest)
invoiceInfo.Copy
.Range("I" & nextRowDest).Resize(transferData.Rows.Count, invoiceInfo.Rows.Count).PasteSpecial Transpose:=True
End With
transferData.ClearContents
invoiceInfo.ClearContents
Application.ScreenUpdating = True
End Sub

Generate sheets based Excel column value

I am not an expert on excel vba, but need to assistance with it.
I have an excel worksheet currently with two sheets
"Datas" sheet : All my long list of data (click to see) is here.
"Template" sheet. A template (click to see) i created to format my data
I know this is going to be bulky.
I need a macro, or button that
can create a new sheet based on the template above for each line in the Column A value in "Datas" sheet
the name of the new sheet will be taken from the Column A value in "Datas" sheet
The new sheet should retain the formatting of the template after data has been copied
In summary it should look somewhat like this
this (click to see) for the first line in column A of Datas sheet
and this (click to see) for the second line in column A of Datas Sheet.
Here is a sample of the worksheet uploaded on
https://ufile.io/bxwo6
I have infact tried the following
http://sites.madrocketscientist.com/jerrybeaucaires-excelassistant/parse-functions/sheet1-to-sheets
PART 2 - Parse New Data To New Sheets (macro)
It did the job of taking each line and split it into different sheets. The results are
This is my Data sheet
This is the result of the split which is good
I am somehow stuck on how to make it adapt to my template formatting.
I would be grateful if you could provide any tip, help or suggestion that i can try
Many Thanks
UPDATE:
I have tried the following code. create a copy of the template and rename it according to the value in Column A from the source
Sub AutoAddSheet()
Dim MyCell As Range, MyRange As Range
Set MyRange = Sheets("Datas").Range("A1")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
For Each MyCell In MyRange
Sheets("TEMPLATE").Copy After:=Sheets(Sheets.Count) 'Create a new worksheet as a copy of Sheet number 9 in this example
Sheets(Sheets.Count).Name = MyCell.Value 'Renames the new worksheets
Next MyCell
End Sub
UPDATE 2: This is the code that i modified from the link above. Note we cannot rename the sheets using column ":" value therefore, i modified my source by changing it from 1:1 into 1, 1:2 into 2
Option Explicit
Sub ParseItems()
Dim LR As Long, Itm As Long, MyCount As Long, vCol As Long, iCol As Long, NR As Long
Dim ws As Worksheet, MyArr As Variant, vTitles As String, TitleRow As Long, Append As Boolean
Application.ScreenUpdating = False
'Column to evaluate from, column A = 1, B = 2, etc.
vCol = 1
'Sheet with data in it
Set ws = Sheets("Data")
'option to append new data below old data
If MsgBox(" If sheet exists already, add new data to the bottom?" & vbLf & _
"(if no, new data will replace old data)", _
vbYesNo, "Append new Data?") = vbYes Then Append = True
'Range where titles are across top of data, as string, data MUST
'have titles in this row, edit to suit your titles locale
vTitles = "A1:Z1"
TitleRow = Range(vTitles).Cells(1).Row
'Spot bottom row of data
LR = ws.Cells(ws.Rows.Count, vCol).End(xlUp).Row
'Get a temporary list of unique values from vCol
iCol = ws.Columns.Count
ws.Cells(1, iCol) = "key"
For Itm = TitleRow + 1 To LR
On Error Resume Next
If ws.Cells(Itm, vCol) <> "" And Application.WorksheetFunction _
.Match(ws.Cells(Itm, vCol), ws.Columns(iCol), 0) = 0 Then
ws.Cells(ws.Rows.Count, iCol).End(xlUp).Offset(1) = ws.Cells(Itm, vCol)
End If
Next Itm
'Sort the temporary list
ws.Columns(iCol).Sort Key1:=ws.Cells(2, iCol), Order1:=xlAscending, _
Header:=xlYes, OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
'Put list into an array for looping
MyArr = Application.WorksheetFunction.Transpose _
(ws.Columns(iCol).SpecialCells(xlCellTypeConstants))
'clear temporary list
ws.Columns(iCol).Clear
'Turn on the autofilter
ws.Range(vTitles).AutoFilter
'Loop through list one value at a time
'The array includes the title cell, so we start at the second value in the array
For Itm = 2 To UBound(MyArr)
ws.Range(vTitles).AutoFilter Field:=vCol, Criteria1:=CStr(MyArr(Itm))
If Not Evaluate("=ISREF('" & CStr(MyArr(Itm)) & "'!A1)") Then 'create sheet if needed
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = CStr(MyArr(Itm))
NR = 1
Else 'if it exists already
Sheets(CStr(MyArr(Itm))).Move After:=Sheets(Sheets.Count) 'ordering the sheets
If Append Then 'find next empty row
NR = Sheets(CStr(MyArr(Itm))).Cells(Rows.Count, vCol).End(xlUp).Row + 1
Else
Sheets(CStr(MyArr(Itm))).Cells.Clear 'clear data if not appending
NR = 1
End If
End If
If NR = 1 Then 'copy titles and data
ws.Range("A" & TitleRow & ":A" & LR).EntireRow.Copy Sheets(CStr(MyArr(Itm))).Range("A" & NR)
Else 'copy data only
ws.Range("A" & TitleRow + 1 & ":A" & LR).EntireRow.Copy Sheets(CStr(MyArr(Itm))).Range("A" & NR)
End If
ws.Range(vTitles).AutoFilter Field:=vCol 'reset the autofilter
If Append And NR > 1 Then NR = NR - 1
MyCount = MyCount + Sheets(CStr(MyArr(Itm))).Range("A" & Rows.Count).End(xlUp).Row - NR
Sheets(CStr(MyArr(Itm))).Columns.AutoFit
Next Itm
'Cleanup
ws.Activate
ws.AutoFilterMode = False
MsgBox "Rows with data: " & (LR - TitleRow) & vbLf & "Rows copied to other sheets: " _
& MyCount & vbLf & "Hope they match!!"
Application.ScreenUpdating = True
End Sub
This should give you an idea which you can start with. It loops through the datas and for each data row it copies the template, renames it and fills in the data row into specific ranges.
Option Explicit
Public Sub AutoParseItems()
Dim wsData As Worksheet
Set wsData = ThisWorkbook.Worksheets("Datas")
Dim lRow As Long
lRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row 'find last row in column A
Const fRow As Long = 1 'set first data row
Dim iRow As Long
For iRow = fRow To lRow 'loop throug data rows
'create a copy of the sheet
ThisWorkbook.Worksheets("TEMPLATE").Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
Dim wsNewTemplateCopy As Worksheet
Set wsNewTemplateCopy = ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
'determine new sheet name and rename the sheet
With wsData.Cells(iRow, "A")
wsNewTemplateCopy.Name = Right$(.Text, Len(.Text) - InStr(1, .Text, ":")) 'find : to determine new sheet name
End With
'fill in the text into the new sheet
wsNewTemplateCopy.Range("A1").Value = wsData.Cells(iRow, "A").Value
wsNewTemplateCopy.Range("A5").Value = wsData.Cells(iRow, "C").Value
wsNewTemplateCopy.Range("A22").Value = wsData.Cells(iRow, "D").Value
'modify the ranges where you need your data
Next iRow
End Sub

Excel VBA - Shift data across multiple columns to a single column

I have a macro right now that pulls data from a different sheet into a new sheet, then formats the data into a form I can use. The issue I have is that some of the PNs that I pull from the other sheet are in different cells for ease of viewing. (For example, the top level PN is in cell C2 and any parts that are a part of the part in C2 may be listed in D3, to show it's a sub-part).
I need code that will shift all PNs across varying columns into a single column. Once all PNs are moved, the other columns should be deleted (D through F). The data ranges from column C to F. Depending on the table the macro pulls data from, the length of the data varies. The macro will need to be able to handle this.
Here's an example of what my sheet looks like after my macro runs:
I'm trying to check column C for empty rows. If say C3 is empty, I then want to check D3 for text. If there is text, I want text in D3 to move to C3. If there is no text, check E3. Same process repeated. From what I've found online, I have this code so far (however, it doesn't run properly in my macro)...
'Copy PNs that are out of line and paste them in the correct column
Dim N As Long, i As Long, j As Long
Set ws1 = Worksheets("KDLSA")
N = ws1.Cells(Rows.Count, "C").End(xlUp).Row
j = 4
For Each cell In Range("D2:F" & ws1.Cells(Rows.Count, "F").End(xlUp).Row)
If cell.Value = "" Then 'if cell C is blank, I want to shift the text to fill column C
ws1.Range("C" & j).Value = ws1.Range("D" & cell.Row).Value 'copy PN in column E to column D - this needs to be more robust to cover my range of columns rather than just D and E
j = j + 1
End If
Next cell
Any help is appreciated.
Change your "For" block to:
With ws1.UsedRange
lastRow = .Rows(.Rows.Count).Row
End With
For Each cell In Range("C2:C" & lastRow)
If cell.Value = "" Then
thisRow = cell.Row
For Each horCell In Range(Cells(thisRow, "D"), Cells(thisRow, "F"))
If Not horCell.Value = "" Then
cell.Value = horCell.Value
Exit For
End If
Next horCell
End If
Next cell
Range("D:F").EntireColumn.Delete
By cycling only through column C, you can loop through D-F only if C is blank, and when you find the one with data, it puts it in C.
If you also need dynamic range on the number of columns, then do:
With ws1.UsedRange
lastRow = .Rows(.Rows.Count).Row
lastColumn = .Columns(.Columns.Count).Column
End With
For Each cell In Range("C2:C" & lastRow)
If cell.Value = "" Then
thisRow = cell.Row
For Each horCell In Range(Cells(thisRow, "D"), Cells(thisRow, lastColumn))
If Not horCell.Value = "" Then
cell.Value = horCell.Value
Exit For
End If
Next horCell
End If
Next cell
Range(Cells(2, "D"), Cells(2, lastColumn)).EntireColumn.Delete
Or with a correct lastRow in your for loop "to" range, change your code to
If Not cell = "" then
ws1.range ("C" & cell.Row).Value = cell.Value
End if
You are looping through columns D-F, so "cell" is a cell in that range, not in column C. You therefore want to test for the ones that are NOT empty and then put their values in the corresponding cell in column C. :-)
As Tehscript mentioned you dont need a macro. If you nevertheless want to use a macro (maybe your real case is more complex than the example) here is a starting point for you.
The example below will shift the cells only once. So you might want to execute the loop several times. (You could also loop over the rowIndex and use a while loop for each row.)
The code could be further refactored but I hope this way it is easy to read.
Sub ShiftCells()
Dim myWorkSheet As Worksheet
Set myWorkSheet = Worksheets("Tabelle1")
Dim maxRowIndex As Long
maxRowIndex = GetMaxRowIndex(myWorkSheet)
Dim rowIndex As Long
Dim columnIndex As Long
Dim leftCell As Range
Dim rightCell As Range
For Each Cell In Range("C2:F" & maxRowIndex)
If Cell.Value = "" Then
shiftedCell = True
rowIndex = Cell.Row
columnIndex = Cell.Column
Set leftCell = myWorkSheet.Cells(rowIndex, columnIndex)
Set rightCell = myWorkSheet.Cells(rowIndex, columnIndex + 1)
leftCell.Value = rightCell.Value
rightCell.Value = ""
End If
Next Cell
End Sub
Function GetMaxRowIndex(ByVal myWorkSheet As Worksheet) As Long
Dim numberofRowsInColumnC As Long
numberofRowsInColumnC = myWorkSheet.Cells(Rows.Count, "C").End(xlUp).Row
Dim numberofRowsInColumnD As Long
numberofRowsInColumnD = myWorkSheet.Cells(Rows.Count, "D").End(xlUp).Row
Dim numberofRowsInColumnE As Long
numberofRowsInColumnE = myWorkSheet.Cells(Rows.Count, "E").End(xlUp).Row
Dim numberofRowsInColumnF As Long
numberofRowsInColumnF = myWorkSheet.Cells(Rows.Count, "F").End(xlUp).Row
Dim maxNumberOfRows As Long
maxNumberOfRows = WorksheetFunction.Max(numberofRowsInColumnC, _
numberofRowsInColumnD, _
numberofRowsInColumnE, _
numberofRowsInColumnF _
)
GetMaxRowIndex = maxNumberOfRows
End Function

VBA SUMIFS - Not Working, All Inputs Return Correct Values

The following code is throwing an 1004 runtime error when I go to run. The debugger highlights the SUMIFS function in just above part 2.
The goal of this sub is to locate duplicate rows using columns 1, 3, and 5 as "primary-keys" and then combine values by column for rows 6-7 and 10-17 based off those values for each row. Hence the SUMIFS.
I'm confused. Using the immediate window I can return the correct values for each section of the SUMIFS fuction (ws.Cells(lRow, lCol).Select will select the correct cell, etc.). My next thought was that the ranges were not interpreted correctly by the SUMIFS so I popped the same function, using specific ranges, into the immediate window and received the same error. See line below for immediate window entry - note that the goal is to combine values between rows 21:23 in this example.
debug.Print application.WorksheetFunction.SumIfs(range("F21:F23"), range("A9:A30"), range("A21").Value, range("C9:C30"), range("C21").Value, range("E9:E30"), range("E21").Value)
I'm assuming, and 100% sure, that named ranges, .codenames, and variables are working as desired. That said, I've been mistaken before.
Any help would be greatly appreciated.
Private Sub dba_combine_rows()
Const COL_TRIPS = 6
Const COL_EMP_TRIP = 7
Const COL_LN_HC = 10
Const COL_USN_PR = 17
Dim lLastRow As Long
Dim ws As Worksheet
Set ws = DBA
Dim answer As Integer
answer = MsgBox("Are you sure you want to combine rows?", vbYesNo, "Combine Rows")
If answer = vbNo Then
Exit Sub
End If
'Get the last row
Dim i As Long
For i = Range("inputRange" & ws.CodeName).Column To (Range("inputRange" & ws.CodeName).Column + Range("inputRange" & ws.CodeName).Columns.Count - 1)
If ws.Cells(ws.Rows.Count, i).End(xlUp).Row > lLastRow Then
lLastRow = ws.Cells(ws.Rows.Count, i).End(xlUp).Row
End If
Next i
''Combine, start modify
'Set aliases for columns A & B & C, used for checking duplicates
Dim rngA As Range, rngB As Range, rngC As Range
Set rngA = ws.Range("inputRange" & ws.CodeName).Columns(1)
Set rngB = ws.Range("inputRange" & ws.CodeName).Columns(3)
Set rngC = ws.Range("inputRange" & ws.CodeName).Columns(5)
Dim lRow As Long, lCol As Long, strHolderA As String, lHolderR As Long
For lRow = ws.Range("inputRange" & ws.CodeName).Row To lLastRow
'Part 1 - Check for duplicate entity-country
If Application.CountIfs(rngA, ws.Cells(lRow, rngA.Column), rngB, ws.Cells(lRow, rngB.Column), rngC, ws.Cells(lRow, rngC.Column)) > 1 Then
strHolderA = (ws.Cells(lRow, rngA.Column).Value & ws.Cells(lRow, rngB.Column).Value & ws.Cells(lRow, rngC.Column).Value)
lHolderR = lRow
For lCol = COL_TRIPS To COL_USN_PR
If lCol = COL_EMP_TRIP Then
lCol = COL_LN_HC
End If
ws.Cells(lRow, lCol).Value = Application.WorksheetFunction.SumIfs( _
ws.Range(Col_Letter(lCol) & lRow & ":" & Col_Letter(lCol) & lLastRow), rngA, ws.Cells(lRow, rngA.Column).Value, rngB, ws.Cells(lRow, rngB.Column).Value, rngC, ws.Cells(lRow, rngC.Column).Value)
Next lCol
'Part 2 - Delete similar rows, excluding 1st
Dim lRow2 As Long
For lRow2 = ws.Range("inputRange" & ws.CodeName).Row To lLastRow
If (ws.Cells(lRow2, rngA.Column).Value & ws.Cells(lRow2, rngB.Column).Value & _
ws.Cells(lRow2, rngC.Column).Value) = strHolderA And lRow2 <> lHolderR Then
Rows(lRow2 & ":" & lRow2).Select
Selection.Delete Shift:=xlUp
lRow2 = lRow2 - 1
End If
Next lRow2
End If
Next lRow
End Sub
The sum_range parameter (the first one) has to be the same size as the criteria ranges, which all. also, have to be the same size.
"F21:F23" is just 3 cells, while the others i.e. "A9:A30" count 22 cells each.