VBA Evaluate Index Match - vba

I have done a fair bit of searching and can't find an answer for this specific case.
My data set is ~650k lines long so I have been trying to make the code as quick as possible.
What I am trying to do is get VBA to index match an entire column with another sheet.
So far my code is VB:
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("Q2:Q" & LastRow).Value = Evaluate("INDEX(MATCH(C2:C" & LastRow & ",'CC Map'!A:A,0),0)")
This very quickly compares column C to sheet 'CC Map'!A:A; and puts the value in column Q.
However, I want to return the corresponding value from 'CC Map'!B:B
When I use
VB:
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("Q2:Q" & LastRow).Value = Evaluate("INDEX('CC Map'!B:B,MATCH(C2:C" & LastRow & ",'CC Map'!A:A,0))")
It returns every value the same (corresponding to match C2...)
I think the issue is with having an array as the second argument in INDEX, but I am trying to avoid loops.
What I have at the moment runs almost instantly.

If the return values are text, you could use:
Range("Q2:Q" & LastRow).Value = Evaluate("INDEX(IF(1,T(OFFSET('CC Map'!B1,MATCH(C2:C" & LastRow & ",'CC Map'!A:A,0)-1,0))),)")
For numeric values, replace T with N.

Related

Insert formula in one cell using VBA

I know this topic was already asked and I tried to copy on how to insert a formula in one cell, however, I got an error in my vba code.
Here is my code:
ws.Range("C9").Formula = "=CountIf(wsRD.Range(C & Rows.count).End(xlUp).Row, ""Event"")" 'CountIf(wsRD.Range("C" & Rows.count).End(xlUp).Row, "Event") 'count(Search("Event", wsRD.Range("C" & Rows.count).End(xlUp).Row, 1))
I need to insert a formula in ws.Range("C9"), in which, it summarizes the count of the cell that have a value of "Event" in wsRD.Range("C" & Rows.count).End(xlUp).Row. May I know what's the problem in my code? Appreciate your help.
Thank you.
You could get rid of the LRow variable and just drop it in your equation if you wanted to.
Dim LRow as Long
LRow = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
ws.Range("C9").Formula = "=COUNTIF(C10:C" & LRow & ", ""Event"")"
I'm sure this could be the correct answer
ws.Select
LRow = ws.Range("C" & Rows.Count).End(xlUp).Row
Range("C9").FormulaLocal = "=COUNTIF(C10:C" & LRow & ";""Event"")"
So basically, I used FormulaLocal to write the formula the same way I write it in Excel, then, because the formula must be a big String, I separated it in 2 strings, put the value LRow, and used & & to concatenate

Auto-populating a Formula

Requirement :
Need to auto populate the formula only for the cells which has the data.
Solution :
Created formula via VB script :
Sub Insert_Formula()
Dim Lastrow As Long
Lastrow = Range("DJ" & Rows.Count).End(xlUp).Row
Range("DK2:DK" & Lastrow).Formula = "=TIMEVALUE(DH2)"
End Sub
Issue:
*Now the formula is being applied to first row also. How can I exclude the header row ?
And result of the first row is being populated in remaining rows (though the formula is relevantly populated).
Or is there any other way to auto populate the formulas dynamically based on the data available ?*
As mentioned in the comments by SJR, the value of Lastrow is 1. In order to fix it, simply write:
If Lastrow = 1 Then Lastrow = 2
Range("DK2:DK" & Lastrow).Formula = "=TIMEVALUE(DH2)"

Array Formula via VBA with or without .ArrayFormula For Dynamic Range

I am trying to translate a procedure previously done without VBA on an Excel sheet.
This inserts an array formula:
={MAX(IF(C2:C355=C2,F2:F355))} into cell CE2
and drag it down to the bottom of the data set, which is variable.
I have attempted different options looping through a variable data set, such as:
Dim i As Variant
LastRow = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
Cells(i, 83).FormulaArray = "=MAX(IF(cells(2,LastRow)= cells(5,i),cells(2,LastRow))"
Next i
The following code seems to work, but my attempts to work the code into a dynamic loop causes errors:
Range("CE2").FormulaArray = "=MAX(IF(C:C=C2,F:F))"
Often the error is:
"Unable to set the FormulaArray property of the range class".
I have noticed that array formulas placed onto the sheet via VBA are slow. I am guessing that there is a way to achieve the same result as my formula via VBA that does NOT use .VarriantArray.
I have looked into the MAX function.
How do I
Loop through a dynamic array and place my array formula on the sheet?
Achieve the same result as my array formula using VBA functions other than .ArrayFormula?
This without the loops using FillDown:
Dim LastRow As Long
With Worksheets("Sheet1")
LastRow = .Range("A" & .Rows.Count).End(xlUp).row
.Cells(2, 83).FormulaArray = "=MAX(IF(" & .Range(.Cells(2, 3), .Cells(LastRow, 3)).Address(1, 1) & "=C2," & .Range(.Cells(2, 6), .Cells(LastRow, 6)).Address(1, 1) & "))"
.Range(.Cells(2, 83), .Cells(LastRow, 83)).FillDown
End With
You seem to have the rows and columns of Cells reversed so I'm guessing you want:
Cells(i, 83).FormulaArray = "=MAX(IF(R2C3:R" & LastRow & "C3=R[0]C3,R2C5:R" & LastRow & "C5))"

How can I speed up this process since it takes a very long time to copy and paste?

Is there anyway to combine to following steps since I am pulling the data from the same sheet into another sheet and the process is very slow.
Sheets("CDGL").Select
Sheets("CDGL").Range("H2:J" & Cells(Rows.Count, "G").End(xlUp).Row).Copy Destination:=Sheets("Rec").Range("B6")
Sheets("CDGL").Select
Sheets("CDGL").Range("L2:O" & Cells(Rows.Count, "K").End(xlUp).Row).Copy Destination:=Sheets("Rec").Range("E6")
Sheets("CDGL").Select
Sheets("CDGL").Range("AJ2:AJ" & Cells(Rows.Count, "AI").End(xlUp).Row).Copy Destination:=Sheets("Rec").Range("I6")
You can simply assign the values directly using the Resize() Function to make the ranges the same size:
With Sheets("CDGL")
Sheets("Rec").Range("B6").Resize(.Cells(.Rows.Count, "G").End(xlUp).Row - 1, 3).Value = .Range("H2:J" & .Cells(.Rows.Count, "G").End(xlUp).Row).Value
Sheets("Rec").Range("E6").Resize(.Cells(.Rows.Count, "K").End(xlUp).Row - 1, 4).Value = .Range("L2:O" & .Cells(.Rows.Count, "K").End(xlUp).Row).Value
Sheets("Rec").Range("I6").Resize(.Cells(.Rows.Count, "AI").End(xlUp).Row - 1, 1).Value = .Range("AJ2:AJ" & .Cells(.Rows.Count, "AI").End(xlUp).Row).Value
End With
I also used a With Block and the Appropriate . identifier to reduce typing and removing the continual selection of sheets. This will also cut down the time.
When you need a fast copy/paste, avoid copying to clipboard and pasting again. You could have simply used the Range.Value method, something like the following:
With Sheets("CDGL")
rows_c1 = .Cells(Rows.Count, "G").End(xlUp).Row
Sheets("Rec").Range("B6:D" & rows_c1).Value = Sheets("CDGL").Range("H2:J" & rows_c1).Value
rows_c2 = .Cells(Rows.Count, "K").End(xlUp).Row
Sheets("Rec").Range("E6:H" & rows_c2).Value = Sheets("CDGL").Range("L2:O" & rows_c2).Value
rows_c3 = .Cells(Rows.Count, "AI").End(xlUp).Row
Sheets("Rec").Range("I6:I" & rows_c3).Value = Sheets("CDGL").Range("AJ2:AJ" & rows_c3).Value
End With
Should you need to have the formatting of cells copied, the Range property "Value" can have 3 optional arguments 10,11,12. 11 is what you need to transfer both value, formats, and formulas.
Something like this:
Sheets("Rec").Range("B6:D" & rows_c1).Value(11) = Sheets("CDGL").Range("H2:J" & rows_c1).Value(11)
Also, avoid using "Select" and use the "With....End With" statement to speed up the execution.
If your issue isn't the effectiveness of the code but the time it takes to work, add Application.ScreenUpdating = False to the start of your sub and Application.ScreenUpdating = True to the end. This will speed up the wait time immensely

converting excel sumifs formula to vba code

I'm trying to do a SUMIFS calculation in VBA. It works fine when I enter it on the spreadsheet, but when I try to convert it to VBA, it doesn't seem to work.
Sheets("Master").Range("B2:B" & Range("A" & Rows.Count).End(xlUp).Row).Formula = _
"=SUMIFS(Input!C32,Input!C37,Master!C1,Input!C31,Master!R1C)"
This is the snippet of code (originally in a comment):
Dim LastRow As Long
Dim rw As Long
LastRow = Range("A" & Rows.Count).End(xlUp).Row
For rw = 2 To LastRow
Sheets("Master").Cells(rw, 2).Value = Application.WorksheetFunction.SumIfs(Sheets("Input").Range("AF:AF"), Sheets("Input").Range("AK:AK"), Sheets("Master").Range("A:A"), Sheets("Input").Range("AE:AE").Sheets("Master").Range("B2"))
Next
You aren't specifying the values you want to lookup in your criteria1. You have to specify a value, not a range.
Your sum range is fine.
Sheets("Input").Range("AF:AF")
Your criteria range1 is fine.
Sheets("Input").Range("AK:AK")
Your criteria1 needs to be a value, not a range.
Use this Sheets("Master").Range("A2").value
instead of Sheets("Master").Range("A:A")
Obviously you can replace the 2 in the criteria1 with a variable if you need to to get your loop to work.