Search code examples
excelvba

Macro became very slow after Filter function


I have a worksheet with 30:31 pages for the month days and I have a Macro to add a symbol @ in the string between the two different lagnuages and it was working perfectly till I created a FILTER function in each page first row like this FILTER(E:F,G:G=D1041,"") then the macro became very slow I don't know why it even became very slow when i paste any text into the sheet. maybe it trys to check all the pages below my current page that I work on - .... please help

Sub englishATarabic()
    Dim L, count As Long, B, E As Range
    For R = 1 To ActiveSheet.Cells(ActiveSheet.Rows.count, "E").End(xlUp).Row
        Set B = ActiveSheet.Range("B" & R)
        Set E = ActiveSheet.Range("E" & R)
        If E.Value <> "" And B.Value <> "" And IsNumeric(B.Value) Then
            If InStr(E.Text, "@") < 1 Then
                count = 0
                For L = 1 To Len(E.Text)
                    If AscW(Mid(E.Text, L, 1)) < 1000 Then count = count + 1 Else Exit For
                Next
                
                E.Value = Left(E.Value, count) & "@" & Right(E.Value, Len(E.Value) - count)
                                                                           
            End If
        End If
    Next
                     
        ThisWorkbook.Save
End Sub

Solution

  • Thousands of questions and answers about this here on SO: What slows down VBA is the interface with Excel. It's way faster to read all relevant data into memory in one go, handle the logic with the data in memory and write back everything again in one go.

    Your code could look like this:

    Sub englishATarabic()
        With ActiveSheet
            Dim BData, EData
            Dim rowCount As Long
            rowCount = .Cells(.Rows.count, "E").End(xlUp).row
            BData = .Range("B1:B" & rowCount).Formula
            EData = .Range("E1:E" & rowCount).Formula
            
            Dim row As Long
            For row = 1 To UBound(BData)
                Dim eVal As Variant, bVal As Variant
                bVal = BData(row, 1)
                eVal = EData(row, 1)
                            
                If bVal <> "" And eVal <> "" And IsNumeric(bVal) Then
                    Dim count As Long, l As Long
                    If InStr(eVal, "@") < 1 Then
                        count = 0
                        For l = 1 To Len(eVal)
                            If AscW(Mid(eVal, l, 1)) < 1000 Then
                                count = count + 1
                            Else
                                Exit For
                            End If
                        Next
        
                        EData(row, 1) = Left(eVal, count) & "@" & Right(eVal, Len(eVal) - count)
                    End If
                End If
            Next
            
            .Range("E1:E" & rowCount).Formula = EData
        End With
    End Sub