Reputation: 67
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.
Upvotes: 1
Views: 385
Reputation: 1654
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
Upvotes: 1
Reputation: 61
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 (i.e. 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
Upvotes: 0
Reputation: 762
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
Upvotes: 0
Reputation: 380
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).
Upvotes: 2