「Sub」删掉指定内容的多种方法

「Sub」删掉指定内容的多种方法

首页休闲益智删除一部分2游戏更新时间:2024-04-24

现有一份销售明细,见下图,大约有会有2000行左右:

大约2000行销售明细中,有1200行0值

因为这里面有很多销售量为0的明细,为了后续操作方便,需要将C列销售量为0的记录删掉。

方法一:循环

这是最容易想到的方法,实现起来也很容易,代码及注释如下:

Sub 删掉0行() Rem 方法一: Do循环 Dim r As Integer Dim t As Double t = Timer r = 2 Do While Range("A" & r).Value <> "" If Range("C" & r).Value = 0 Then Rem 如果C列为0,就删掉当前行 Rows(r).Delete Rem 最重要的就是下面的r=r-1,如果不加这一行,【相邻两个0行的第二行】将不会被删掉。 Rem 原因:把第一个0行删掉后,第二个0行自动上移一行,而经过r=r 1后,r已经指向下一行, rem 正好跳过了上移的这一行 r = r - 1 End If r = r 1 Loop MsgBox "删除完毕,用时 " & Format(Timer - t, "0.00") & " 秒", , "" End Sub

该方法需要较长的时间,运行结果如下:

即使关闭屏幕更新,也需要0.16秒:(这说明关闭屏幕更新确实非常有效地提高了代码效率)

方法二:循环,标记,一次性删除

方法一循环之所以效率慢,是因为不断删除行、不断将下面的内容上移一行。如果循环的时候不删除行,只是做个标记,然后一次性删除,那么效率应该会高很多。代码如下:

Sub 删掉0行_2() Rem 方法二: 排序 Dim r As Integer Dim t As Double t = Timer r = 2 Do While Range("A" & r).Value <> "" If Range("C" & r).Value = 0 Then Rem 只是在E列做个标记,并不删除改行 Range("E" & r).Value = 1 End If r = r 1 Loop Rem 定位E列列有内容的单元格,将这些单元格的整行一次性删掉 Range("E:E").SpecialCells(xlCellTypeConstants).EntireRow.Delete MsgBox "删除完毕,用时 " & Format(Timer - t, "0.00") & " 秒", , "" End Sub

在没有关闭屏幕更新的情况下(其实这种方法关闭、不关闭屏幕更新没有影响),用时仅仅0.07秒:

方法三:排序

方法一循环之所以效率慢,是因为不断删除行、不断将下面的内容上移一行。是否能想办法只上移一次?这时候效率肯定高。方法很简单:排序。代码如下:

排序的代码太难写了,这时候VBA的巨大优势就体现出来了:录制宏。

Sub 删掉0行_3() Dim r As Integer Dim t As Double t = Timer Rem 以下一大坨代码实现按C列排序,完全录制的,稍加修改即可。不必深究。 ActiveSheet.Sort.SortFields.Clear ActiveSheet.Sort.SortFields.Add Key:=Range("C2"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal With ActiveSheet.Sort .SetRange Range("A1").CurrentRegion .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With Rem 在C列找第一个1出现的位置,从该位置往上直到第2行,都是应该被删除的。 Rem 当然这里面有个前提:事先已经知道C列销售量没有负数,且一定有销量为1的行 r = Range("C:C").Find(WHAT:=1).Row Rem 下面一次性删除0行 Rows("2:" & r).Delete MsgBox "删除完毕,用时 " & Format(Timer - t, "0.00") & " 秒", , "" End Sub

只需要0.03秒:

这个方法最核心的操作是排序。排序操作在实际工作中经常用到,但是录制的代码实在太恶心,而且也没必要去记住这么复杂的代码,因此可以将常用的单条件排序、二条件排序、三条件排序做成Sub过程,需要时直接调用即可。该Sub过程将在后续文章中展示。

这种方法非常快,但是有个问题:对原始数据进行了排序,因此打乱了原始数据的顺序。解决方法:排序前在E列顺序填写1、2、3……,删除完毕后,再按E列升序排序,然后删掉E列,即可恢复到原来的顺序。很简单,代码不再展示。这种方法是既想排序、又不想打乱原始数据顺序的最好方法,后续可能会陆续用到。

方法四:公式法

这个问题我所能想到的终极方法是用公式:在E列计算C列是否为0,然后替换掉False值,然后将True值的整行删掉。代码量很小,且代码不像方法三那么“恶心难记”,速度也很快。代码如下:

Sub 删掉0行_4() Dim t As Double t = Timer Rem 在E列填充公式 Range("E2").Value = "=C2=0" Range("E2").AutoFill Destination:=Range("E2:E" & Range("A1").CurrentRegion.Rows.Count) With Range("E:E") Rem 选择性粘贴数值,去掉公式 .Copy Range("E1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False Rem 取消复制剪切状态,可以提升下面的Replace操作的效率 Application.CutCopyMode = False Rem 将False值替换为空白 .Replace WHAT:="FALSE", REPLACEMENT:="" Rem 所有的非空白值(TRUE)就是要删掉的行 .SpecialCells(xlCellTypeConstants).EntireRow.Delete End With MsgBox "删除完毕,用时 " & Format(Timer - t, "0.00") & " 秒", , "" End Sub

以上填充公式、去掉公式的操作很繁琐,所以显得代码量比较大,实际上可以用一个自定义的Sub过程【填充并去掉公式】搞定,该Sub过程将在后面展示。代码如下:

Sub 删掉0行_5() Dim t As Double t = Timer Rem 在E列填充公式 Call 填充并去掉公式(Range("E2"), "=C2=0", True) With Range("E:E") .Replace WHAT:="FALSE", replacement:="" .SpecialCells(xlCellTypeConstants).EntireRow.Delete End With MsgBox "删除完毕,用时 " & Format(Timer - t, "0.00") & " 秒", , "" End Sub

以上几种方法,希望能对大家有所帮助。

I am a VBAer!

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved