简体   繁体   中英

endless loop while deleting rows?

I have a large csv file that i have sorted by a column. now i want to delete rows that don't contain a certain sring in another column. My code looks like this so far:

Private Sub sortcsvfile(filename)
    Workbooks.OpenText filename, Origin:=65001, StartRow:=1 _
        , DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
        ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=True, Comma:=False, _
        Space:=False, Other:=False, FieldInfo:=Array(Array(1, 1), Array(2, 1), Array( _
        3, 1), Array(4, 1), Array(5, 1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10 _
        , 1), Array(11, 1), Array(12, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array(16, 1), _
        Array(17, 1), Array(18, 1), Array(19, 1), Array(20, 1), Array(21, 1), Array(22, 1), Array( _
        23, 1), Array(24, 1), Array(25, 1), Array(26, 1), Array(27, 1), Array(28, 1), Array(29, 1), _
        Array(30, 1), Array(31, 1), Array(32, 1), Array(33, 1), Array(34, 1), Array(35, 1), Array( _
        36, 1), Array(37, 1), Array(38, 1), Array(39, 1), Array(40, 1), Array(41, 1), Array(42, 1), _
        Array(43, 1), Array(44, 1), Array(45, 1), Array(46, 1), Array(47, 1)), _
        TrailingMinusNumbers:=True
    x = Cells(Rows.Count, 1).End(xlUp).Row
    Cells.Select
    ActiveWorkbook.Worksheets("merged").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("merged").Sort.SortFields.Add Key:=Range("D2:D" & x _
        ), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("merged").Sort
        .SetRange Range("A1:AT" & x)
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

    For y = 0 To x
        If (Range("J2").Offset(y, 0) <> "condition") Then
            Range("J2").Offset(y, 0).EntireRow.Delete
            y = y - 1
        End If
    Next
End Sub

however, at the part where i want to delete the rows

For y = 0 To x
    If (Range("J2").Offset(y, 0) <> "condition") Then
        Range("J2").Offset(y, 0).EntireRow.Delete
        y = y - 1
    End If
Next

it appears to go in an endless loop. why is that? when i try For y = 0 To LastRow it doesn't delete anything, if I try an absolute value (like 60) it works perfectly up until line number 60.

You need to adjust the last row variable (x) at the same time as adjusting the for loop counter (y). Your code currently tries to execute until y = x, but it will only get there if all of the rows meet the conditions specified (so nothing is deleted).

Here is how your code should look like :

Option Explicit 'This is a must

Private Sub sortcsvfile(filename)
Dim x&, y& 'declare variables

With Application 'make things a bits faster
    .Screenupdating=false
    .Calculation = xlCalculationManual
    .EnableEvents = False ' EDIT 3 : This event can trigger infinite loop too, if =True
End With

'your other code

For y = x To 2 step -1 'Go Backwards , impossible to infinite loop, impossible to miss rows
    with Cells(y, 7) 'Use a with. "J" is 7.
        if .value2 <> "condition" Then .EntireRow.Delete '.value2 is slightly faster, do not use it with dates or currency...
    End with
Next y 'add the variable name, in multi loops it's easier to read, and good practice

With Application 'reset to normal
    .Screenupdating= True
    .Calculation = xlCalculationAutomatic
    .EnableEvents = True
End With

End Sub

EDIT : Shai Rondo's idea should work, but maybe your code was just slow and looked infinite with his idea (depending of the value of x)...

EDIT2 : An even faster way is to add the "Bad" cells to a range (named Rg), and after the loop, Rg.entireRow.delete . I'm giving it a shot, with arrays too :

Option Explicit 'This is a must
'Please make a copy of your sheet before tring someone else's code.

Private Sub sortcsvfile(filename)
Dim x&, y& 'declare variables
Dim DATA() 'as Variant
Dim Rg As Range

With Application 'make things a bits faster
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
    .EnableEvents = False
End With

'your other code
' ...
'

With ActiveSheet 'reference the sheet you are working with , change this line as needed.
    x = .Cells(.Rows.Count, 1).End(xlUp)
    DATA = .Range(.Cells(1, 7), .Cells(x, 7)).Value2 'write the Array with the Worksheet's contents without loop.

    For y = 2 to x ' For y=x To 2 Step -1 ' EDIT 4 : with the RG/DATA approach you can Go Backwards or upwards, both do the same result...
        If DATA(y, 7) <> "condition" Then
            '2 cases possible
            If Not Rg Is Nothing Then ' i explain the use of "Not" in the folowing line's comment
                Set Rg = Union(Rg, .Cells(y, 7)) 'in a "If" , always do the "Often Used" option, and the lesser used in the "Else"
            Else
                Set Rg = .Cells(y, 7) 'the "lesser used option"
        End If
    Next y 'add the variable name, in multi loops it's easier to read, and good practice

    Rg.EntireRow.Delete 'do only one Delete

End With 'this with refers to the worksheet

Erase DATA 'free memory
Set Rg = Nothing

With Application 'reset to normal
    .ScreenUpdating = True
    .Calculation = xlCalculationAutomatic
    .EnableEvents = True
End With

End Sub

You need to introduce a variable (t) aside from y.

t = x

For y = 0 To x

    If (Range("J2").Offset(y, 0) <> "condition") Then
        Range("J2").Offset(y, 0).EntireRow.Delete
        y = y - 1
        t = t - 1
    End If

    If t < 0 Then
        y = x
    End If

Next y

A couple of things. Firstly, you need to use the .value command when using if statements checking a cell value. Secondly, you should Dim your variables (ie type Dim x as integer , Dim y as integer ) at the beginning of the subroutine, before anything else.

Here is your code using .value :

For y = 0 To x
    If (Range("J2").Offset(y, 0).value <> "condition") Then
        Range("J2").Offset(y, 0).EntireRow.Delete
        y = y - 1
    End If
Next

You could also use the cells() command so you don't have to offset (col 10 is col J):

For y = 0 To x
    If (Cells(2 + y,10).value <> "condition") Then
        Cells(2 + y,10).EntireRow.Delete
        y = y - 1
    End If
Next

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