掌握了Excel中最常见的range对象的属性和方法过后,再利用上VBA里的判断和循环控制结构语句,我们就可以自己慢慢解决一些小的需求了。 案例:删除零值单元格所在行,在一个range区域,如果有任何一个单元格的值为零值,则删除本行。数据大家可以自行举例,可以使用rand函数配合int函数来随机生成含有零值的区域。 在解决实际需求前,我们都需要拟定大体的思路。对于这个问题,我们很直观的可以想到:遍历每一个单元格,判断如果是零的话,就删除行。 那么,我们可以写这样一个程序: Sub delete_zero()Dim Rng As RangeDim i%, j%, Row_Num%, Col_Num%Row_Num = Range('a1').CurrentRegion.Rows.CountCol_Num = Range('a1').CurrentRegion.Columns.CountFor i = 1 To Row_Num For j = 1 To Col_Num If Cells(i, j).Value = 0 Then Cells(i, j).EntireRow.Delete Exit For End If NextNextEnd Sub 个中的逻辑也很简单,利用i循环行,j循环列。如果单元格的数值为0,那么就删除这行,并不再执行列的循环,跳出来继续执行行的循环。 看起来不错,运行一下看看吧! 等等,怎么里面还有零? 我们的逻辑似乎没有问题,但我们在执行过程中没有考虑excel删除行的执行方式问题。一般来说,执行行删除操作,下面的行会自动上移。因此,执行过一次行删除之后,每一行的行号相对于原始表已经发生了变化,自然会漏删一些行。 解决方法很简单,只要把行的循环进行倒序删除就可以。 Sub delete_zero()Dim Rng As RangeDim i%, j%, Row_Num%, Col_Num%Row_Num = Range('a1').CurrentRegion.Rows.CountCol_Num = Range('a1').CurrentRegion.Columns.CountFor i = Row_Num To 1 Step -1 For j = 1 To Col_Num If Cells(i, j).Value = 0 Then Cells(i, j).EntireRow.Delete Exit For End If NextNextEnd Sub F5运行看看,结果里面还有0吗? 这个需求的解决,到这里,似乎是结束了,然而并没有。我们刚才处理的是很小一部分数值,这种循环方式速度也还可以,但如果是大量数据,例如1000 行呢? 我们用上述方式,对1000 行数据进行了处理,处理时间为0.71秒,如果是处理10000条数据岂不是要更长? 有没有更快的运行方式呢? 我们再仔细观察一下上面的代码,我们发现,Excel每发现一行,就要执行一次删除操作,这会相当浪费时间。可不可以一次性把发现的单元格都删除呢? 这就要用到我们之前将的union方法了。 修改后的代码如下: Sub delete_zero_new()Dim Rng As RangeDim i%, j%, Row_Num%, Col_Num%Row_Num = Range('a1').CurrentRegion.Rows.CountCol_Num = Range('a1').CurrentRegion.Columns.CountFor i = Row_Num To 1 Step -1 For j = 1 To Col_Num If Cells(i, j).Value = 0 Then If Rng Is Nothing Then Set Rng = Cells(i, j) Else Set Rng = Union(Rng, Cells(i, j)) End If Exit For End If NextNextRng.EntireRow.DeleteSet Rng = NothingEnd Sub 这里要注意的是object的使用。
改进了代码之后,F5运行程序只需要0.32秒,是不是比之前快了很多? 根据以上这个案例,我们可以直观的得到一个经验:在处理大量数据的时候,要尽量减少excel的固有操作,如select, activate, delete等等,这样可以大大提高运行速度。 总结一下:
|
|
来自: liuyunhe1954 > 《Excel VBA》