excelvbaforeachexcel-tableslistobject

For Each loop with 64K+ ListRows (out of memory)


I run a For Each loop through an Excel table (Listobject) which checks if a file exists based on a given path.

It runs with 63K lines (done within 5 minutes).

My table has expanded to 68K Listrows.

After launching the code

For Each lstrw In Headers.ListRows

quickly gives

Run-time-error '7': Out of memory

Based on googling there appears to be something called "64K segment boundary". It feels like my code buffers the row count at first and then bounces back w/o starting to run anything. Is there a workaround without the need to split my dataset into multiple batches?

Running on 64bit Excel 2019, but no luck with Office365 either.

Sub CheckFiles()

    Dim Headers As ListObject
    Dim lstrw As ListRow

    Dim strFileName As String
    Dim strFileExists As String

    Application.ScreenUpdating = False

    Set ws = ThisWorkbook.Sheets("Import")
    Set Headers = ws.ListObjects("Import")

    For Each lstrw In Headers.ListRows
    
        strFileName = lstrw.Range(7)
        strFileExists = Dir(strFileName)
        
        If strFileExists = "" Then
            lstrw.Range(4) = "not found"
        Else
            lstrw.Range(4) = "exists"
        End If
    
    Next lstrw

    Set ws = Nothing
    Set Headers = Nothing

    Application.ScreenUpdating = True

End Sub

Solution

  • Avoid Accessing the Worksheet

    Option Explicit
    
    Sub CheckFiles()
    
        Const wsName As String = "Import" ' Worksheet Name
        Const tblName As String = "Import" ' Table Name
        Const cCol As Long = 7 ' Criteria Column
        Const dCol As Long = 4 ' Destination Column
    
        Dim wb As Workbook: Set wb = ThisWorkbook
        Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
        Dim Headers As ListObject: Set Headers = ws.ListObjects(tblName)
    
        Dim Data As Variant ' Data Array
        With Headers.ListColumns(cCol).DataBodyRange
            If .Rows.Count = 1 Then
                ReDim Data(1 To 1, 1 To 1): Data = .Value
            Else
                Data = .Value
            End If
        End With
        
        Dim r As Long ' Array Row Counter (DataBodyRange Row Counter)
        Dim FileName As String ' File Name Retrieved by Dir
        
        For r = 1 To UBound(Data, 1)
            FileName = Dir(CStr(Data(r, 1)))
            If Len(FileName) = 0 Then
                Data(r, 1) = "not found"
            Else
                Data(r, 1) = "exists"
            End If
        Next r
        
        Headers.ListColumns(dCol).DataBodyRange.Value = Data
    
    End Sub