简体   繁体   中英

Can we change complex excel formula into VBA

Can anyone please write this formula in VBA code, this is making the sheet heavy and whenever i add or edit raw data (Data sheet) it starts "Calculating 4 processors" and takes much time.

In raw Data Sheet there are almsot 18000 entries and in other sheet where i am extracting the status contains 8000 entries, however it would be much helpful if it sees till the last raw.

=IF(SUMPRODUCT((Data:$A$2:$A$17989=A7076) (Data:$B$2:$B$17989=B7076) (Data:$C$2,$C$17989="Combine")),"Available":IF(COUNTIFS(Data,$A$2,$A$17989:A7076,Data,$B$2:$B$17989,B7076,Data,$C$2:$C$17989,"Feed *")=2,"Available","Not Available"))

I have read many articles on web and tried them but not helpful and i am wondering if VBA is one of the best solution for this complex formula.

what i have recorded is below:

Sub Macro1() ' ActiveCell.FormulaR1C1 = _

    "=IF(SUMPRODUCT((Data!R2C1:R17989C1=RC[-5])*(Data!R2C2:R17989C2=RC[-4])*(Data!R2C3:R17989C3=""Combine"")),""Available"",IF(COUNTIFS(Data!R2C1:R17989C1,RC[-5],Data!R2C2:R17989C2,RC[-4],Data!R2C3:R17989C3,""Feed *"")=2,""Available"",""Not Available""))"

Range("F2").Select

Selection.Copy

Range("F3:F7076").Select

ActiveSheet.Paste

Application.CutCopyMode = False

Selection.End(xlUp).Select

Range("F3").Select

ActiveWorkbook.Save

End Sub

thank you

Please, test the next solution. Activate the sheet to be processed and run SetAvailability :

Sub SetAvailability()
   Dim sh As Worksheet, shD As Worksheet, lastRA As Long, lastRD As Long, arrD, arr, arrF, i As Long
   
   Set sh = ActiveSheet
   Set shD = Worksheets("Data")
    lastRA = sh.Range("A" & sh.rows.count).End(xlUp).Row
    lastRD = shD.Range("A" & shD.rows.count).End(xlUp).Row
    
    arrF = sh.Range("F2:F" & lastRA).Value2
    arr = sh.Range("A2:B" & lastRA).Value2
    arrD = shD.Range("A2:C" & lastRD).Value2
    
    For i = 1 To UBound(arr)
        arrF(i, 1) = getAvailability(arrD, arr(i, 1), arr(i, 2), "Combine", "Feed *")
    Next i
    
    'drop the processed aray content at once:
    sh.Range("F2").Resize(UBound(arrF), 1).Value2 = arrF
    
    MsgBox "Ready..."
End Sub

Function getAvailability(arrD, strAA, strBB, strAv As String, strFeed As String) As String
   Dim countFeed As Long, i As Long
   For i = 1 To UBound(arrD)
        If arrD(i, 1) = strAA And UCase(arrD(i, 2)) = UCase(strBB) Then
            If UCase(arrD(i, 3)) = UCase(strAv) Then getAvailability = "Available": Exit Function
            If arrD(i, 3) Like strFeed Then countFeed = countFeed + 1
            If countFeed = 2 Then getAvailability = "Available": Exit Function
        End If
   Next i
   getAvailability = "Not Available"
End Function

It should be fast enough, working only in memory and dropping the processed array content at once, at the end of the code. And, no any workbook charge because of complicated formula...

The above solution assumes that strings as "Feed *" will be at least two, for matchings in A:A and B:B, meaning that more (than two) such matches are allowed to consider the return as "Available".

It will take some time, anyhow, but I am curious how match for your specific data ranges.

It will be faster if the availability is bigger (the iteration on "Data" sheet array stops after finding the match...).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM