[英]What am I doing wrong? Removing duplicates using Excel VBA
I'm new to VBA so this is probably a very obvious mistake. 我是VBA的新手,所以这可能是一个非常明显的错误。
To keep it short, I am trying to delete rows based on two criteria: In Column A, if they have the same value (duplicate) and in Column B, the difference is less than 100, then one row is deleted from the bottom. 为了简短起见,我试图根据两个条件删除行:在A列中,如果它们具有相同的值(重复),而在B列中,相差小于 100,则从底部删除一行。
Example data: 示例数据:
Column A Column B
1 300
1 350 SHOULD be deleted as second column diff. is <100 compared to row above
2 500
2 700 Should NOT be deleted as second column diff. is not <100
Here is the code I have come up with: 这是我想出的代码:
Sub deduplication()
Dim i As Long
Dim j As Long
Dim lrow As Long
Application.ScreenUpdating = False
With Worksheets("Sheet1")
lrow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = lrow To 2 Step -1
For j = i To 2 Step -1
If .Cells(i, "A").Value = .Cells(j, "A").Value And .Cells(i, "B").Value - .Cells(j, "B").Value < 100 Then
.Cells(i, "A").EntireRow.Delete
End If
Next j
Next i
End With
End Sub
This largely works, but only if the second criterion is greater than (>) rather than less than (<). 这在很大程度上有效,但前提是第二个条件大于 (>)而不是小于 (<)。 When it is less than, it deletes every row .
小于时,将删除每一行 。 What am I doing wrong?
我究竟做错了什么? Is there an easy fix?
有简单的解决方法吗?
Thank you 谢谢
Not 不
If .Cells(i, "A").Value = .Cells(j, "A").Value And .Cells(i, "B").Value - .Cells(j, "B").Value < 100 Then
Here in the second part of the statement, you're just comparing .Cells(j, "B").Value
to const 100 ! 在语句的第二部分,您只是将
.Cells(j, "B").Value
与const 100进行比较!
But 但
If .Cells(i, "A").Value = .Cells(j, "A").Value And Abs(.Cells(i, "B").Value - .Cells(j, "B").Value) < 100 Then
Abs() may help, else keep just the ( ) Abs()可能有帮助,否则仅保留()
Something like this should work for you: 这样的事情应该为您工作:
Sub tgr()
Dim ws As Worksheet
Dim rDel As Range
Dim rData As Range
Dim ACell As Range
Dim hUnq As Object
Set ws = ActiveWorkbook.Sheets("Sheet1")
Set hUnq = CreateObject("Scripting.Dictionary")
Set rData = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
If rData.Row = 1 Then Exit Sub 'No data
For Each ACell In rData.Cells
If Not hUnq.Exists(ACell.Value) Then
'New Unique ACell value
hUnq.Add ACell.Value, ACell.Value
Else
'Duplicate ACell value
If Abs(ws.Cells(ACell.Row, "B").Value - ws.Cells(ACell.Row - 1, "B").Value) < 100 Then
If rDel Is Nothing Then Set rDel = ACell Else Set rDel = Union(rDel, ACell)
End If
End If
Next ACell
If Not rDel Is Nothing Then rDel.EntireRow.Delete
End Sub
Sticking to the format of your code, you can do this using one For
loop as well. 坚持使用代码格式,也可以使用一个
For
循环来执行此操作。
For i = lrow To 3 Step -1
If .Cells(i, "A") = .Cells(i - 1, "A") And (.Cells(i, "B") - .Cells(i - 1, "B")) < 100 Then
.Cells(i, "A").EntireRow.Delete
End If
Next i
Every first j-cycle starts off by comparing a row to itself since you start with j = i
. 自从
j = i
开始,每个第一个j周期都会通过将一行与自身进行比较而开始。 The difference between a value and itself is always zero. 值与其自身之间的差始终为零。 (It also compares row 2 with itself as the very last step.)
(最后一步,它还将第2行与其自身进行比较。)
However, if you switch: 但是,如果您切换:
For i = lrow To 2 Step -1
For j = i To 2 Step -1
to: 至:
For i = lrow To 3 Step -1
For j = i - 1 To 2 Step -1`
the code will compare all the various rows without the self-compares. 该代码将比较所有各行,而不进行自我比较。
Another point (which @Proger_Cbsk 's answer brought to mind), is that doing the comparison with just the subtraction .Cells(i, "B").Value - .Cells(j, "B").Value < 100
will sometimes cause unexpected results. 另一点(@Proger_Cbsk的答案浮现在脑海)是,只用减法
.Cells(i, "B").Value - .Cells(j, "B").Value < 100
有时进行比较导致意外结果。
For example, assume .Cells(i, "B").Value = 1
and .Cells(j, "B").Value = 250
. 例如,假设
.Cells(i, "B").Value = 1
和.Cells(j, "B").Value = 250
。 We can tell by just looking, that there is a difference of at least 100, so you would expect this part of the expression to evaluate to False. 我们可以看出,两者至少相差100,因此您希望表达式的这一部分的值为False。 However, from straight substitution, you get the expression:
1 - 250 < 100
. 但是,从直接替换中,您可以获得表达式:
1 - 250 < 100
。 Since 1 - 250 = -249
, and since -249 < 100
, the expression would actually evaluate to True. 由于
1 - 250 = -249
,并且-249 < 100
,因此该表达式实际上将计算为True。
However, if you were to change .Cells(i, "B").Value - .Cells(j, "B").Value < 100
to Abs(.Cells(i, "B").Value - .Cells(j, "B").Value) < 100
, the expression will now be looking at if the difference is greater or less than 100, instead of looking at if the subtraction result is greater or less than 100. 但是,如果要将
.Cells(i, "B").Value - .Cells(j, "B").Value < 100
更改为Abs(.Cells(i, "B").Value - .Cells(j, "B").Value) < 100
,现在表达式将查看差值是大于还是小于100,而不是减法结果是大于还是小于100。
Why not to use the built-in command: 为什么不使用内置命令:
Worksheets("Sheet1").Range("$A:$A").RemoveDuplicates Columns:=1, Header:=xlYes
Range.RemoveDuplicates Method (Excel) Range.RemoveDuplicates方法(Excel)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.