VBA Macro crashes after 32000 rows

后端 未结 3 1610
遇见更好的自我
遇见更好的自我 2020-11-27 08:06

I have a VBA macro that copies rows from one worksheet into another based upon finding values in cells in 3 columns. The macro works, but crashes when it reaches row 32767.

相关标签:
3条回答
  • 2020-11-27 08:13

    The VBA 'Int' type is a signed 16-bit field so it can only hold values from -32768 to +32767. Change those variables to 'Long', which is a signed 32-bit field and can hold values from -2147483648 to +2147483647. Should be enough for Excel. ;)

    0 讨论(0)
  • 2020-11-27 08:27

    You can avoid the Integer vs. Long issue by using a For Each rather than incrementing rows. For Each is generally faster, as is avoiding Selecting Ranges. Here's an example:

    Sub CopySheets()
    
        Dim shSource As Worksheet
        Dim shDest As Worksheet
        Dim rCell As Range
        Dim aSheets() As Worksheet
        Dim lShtCnt As Long
        Dim i As Long
    
        Const sDESTPREFIX As String = "dest_"
    
        On Error GoTo Err_Execute
    
        For Each shSource In ThisWorkbook.Worksheets
            lShtCnt = lShtCnt + 1
            ReDim Preserve aSheets(1 To lShtCnt)
            Set aSheets(lShtCnt) = shSource
        Next shSource
    
        For i = LBound(aSheets) To UBound(aSheets)
            Set shSource = aSheets(i)
    
            'Add a new sheet
            With ThisWorkbook
                Set shDest = .Worksheets.Add(, .Worksheets(.Worksheets.Count))
                shDest.Name = sDESTPREFIX & shSource.Name
            End With
    
            'copy header row
            shSource.Rows(3).Copy shDest.Rows(3)
    
            'loop through the cells in column a
            For Each rCell In shSource.Range("A4", shSource.Cells(shSource.Rows.Count, 1).End(xlUp)).Cells
                If Not IsEmpty(rCell.Value) And _
                    rCell.Offset(0, 27).Value = "Yes" And _
                    rCell.Offset(0, 36).Value = "Yes" And _
                    rCell.Offset(0, 53).Value = "Yes" Then
    
                    'copy the row
                    rCell.EntireRow.Copy shDest.Range(rCell.Address).EntireRow
                End If
            Next rCell
        Next i
    
        MsgBox "All matching data has been copied."
    
    Err_Exit:
        'do this stuff even if an error occurs
        On Error Resume Next
        Application.CutCopyMode = False
        Exit Sub
    
    Err_Execute:
        MsgBox "An error occurred."
        Resume Err_Exit
    
    End Sub
    
    0 讨论(0)
  • 2020-11-27 08:29

    This sounds like an integer Problem

    The Integer and Long data types can both hold positive or negative values. The difference between them is their size: Integer variables can hold values between -32,768 and 32,767, while Long variables can range from -2,147,483,648 to 2,147,483,647.

    But which version are you using? Because:

    Traditionally, VBA programmers have used integers to hold small numbers, because they required less memory. In recent versions, however, VBA converts all integer values to type Long, even if they are declared as type Integer. Therefore, there is no longer a performance advantage to using Integer variables; in fact, Long variables might be slightly faster because VBA does not have to convert them.

    This Information is directly from MSDN

    UPDATE

    Please also read the first comment! I was interpreting the MSDN Information the wrong way!

    Thats MSDN being misleading: VBA does not itself convert Integer to Long. Under the covers the CPU converts integer to long , does the arithmetic and then converts the resulting long back to integer. So VBA integers still cannot hold numbers larger than 32K – Charles Williams

    0 讨论(0)
提交回复
热议问题