2
\$\begingroup\$

I am using a match formula inside of a for loop, but it is taking too much time. Is there any way to optimize this code to make it go faster?

 Lastrow = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
For i = 3 To Lastrow
 Sheets("sample").Range("AM1000000").End(xlUp).Offset(1, 0).Select
 Selection.FormulaArray = _
 "=IF(ISNUMBER(MATCH(1," & Chr(10) & " (order!R2C15:R1000000C15=RC[-24])*" & Chr(10) & " (order!R2C7:R1000000C7=RC[-32])*" & Chr(10) & " (order!R2C24:R1000000C24=RC[-15])," & Chr(10) & " 0)), ""pass"",""review"")"
 Next i
 Columns("AM:AM").Select
 Selection.Copy
 Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
 :=False, Transpose:=False
RubberDuck
31.1k6 gold badges73 silver badges176 bronze badges
asked May 15, 2017 at 23:36
\$\endgroup\$
1
  • \$\begingroup\$ What is the end result you're trying to achieve? I suspect there is a much easier way to accomplish a solution \$\endgroup\$ Commented May 17, 2017 at 13:23

2 Answers 2

1
\$\begingroup\$

The key optimisation can be found in this part:

Dim orderColumnOArray as Variant, orderColumnGArray as Variant, orderColumnXArray as Variant
orderColumnOArray = ThisWorkbook.Worksheets("order").Range("O2:O1000000").Value
orderColumnGArray = ThisWorkbook.Worksheets("order").Range("G2:G1000000").Value
orderColumnXArray = ThisWorkbook.Worksheets("order").Range("X2:X1000000").Value

There above, we are using arrays to store the order data, and we can traverse them more efficiently, rather than repeat a full array formula calculation for each cell.

Note that even then we could cut down on the million rows, and do a lastRow calculation for the order sheet. Perhaps that will bring great improvement too. However if we say for now that you will genuinely have that number of data rows in the order Worksheet, we can still go about it a bit better.

With ThisWorkbook.WorkSheets("sample")
 'I will assume that the column needs to filled from AM3 to AMLastrow
 'I also assume the tested values are strings or integers, not dates or floats
 Dim resultArray() as String
 ReDim resultArray(3 to Lastrow)
 Dim j as Long
 For i = 3 To Lastrow
 resultArray(i) = "review"
 For j = 1 To Ubound(orderColumnOArray)
 'The below nested Ifs can be done in many different ways
 'e.g. And with the 3 equality tests
 'or even by initially making two concatenated arrays!
 If .Range("O" & i).Value = orderColumnOArray(j, 1) Then
 If .Range("G" & i).Value = orderColumnGArray(j, 1) Then
 If .Range("X" & i).Value = orderColumnXArray(j, 1) Then
 resultArray(i) = "pass"
 Exit For
 End if
 End if
 End if
 Next j
 Next i
 'Now we can write back the array to the worksheet faster
 .Range("AM3").Resize(Lastrow - 3 + 1, 1).Value = resultArray
End With
answered May 17, 2017 at 17:00
\$\endgroup\$
-1
\$\begingroup\$

May want to read the cells into an array, process within the VBA world, then write out cells to the sheet. Going back and forth to the worksheets typically slow.

answered May 16, 2017 at 15:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.