逐行检查数据、遍历所有工作表、批量删除空白行、按条件跳过某些记录。VBA 的循环语法不复杂,但“边循环边删除行”和“修改集合的同时遍历”很容易漏数据。
Dim i As Long
For i = 1 To 10
Debug.Print i
Next i
For i = 10 To 1 Step -1
Debug.Print i
Next i
For i = 1 To 10 Step 2
Debug.Print i
Next i
Step 可以为负;从大到小循环时起始值要大于结束值。Exit For 可以提前跳出当前循环。Long,不要用 Integer。Sub CheckRows()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Set ws = ThisWorkbook.Worksheets("数据")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
If ws.Cells(i, "C").Value < 0 Then
ws.Cells(i, "D").Value = "异常"
Else
ws.Cells(i, "D").Value = "正常"
End If
Next i
End Sub
数据量大时不要逐格读写,先读入数组、循环数组、再写回,见 vba-range-cells。
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Next ws
Dim cell As Range
For Each cell In ws.Range("A2:A" & lastRow)
If cell.Value = "" Then cell.Interior.Color = RGB(255, 235, 156)
Next cell
For Each 适合遍历集合,但不要在遍历集合的同时删除元素:删除一个工作表后,集合索引会变化,后面的元素可能被跳过。要删除时用倒序的 For i = ... To ... Step -1。
Dim i As Long
i = 1
Do While i <= 10
Debug.Print i
i = i + 1
Loop
i = 1
Do Until i > 10
Debug.Print i
i = i + 1
Loop
还有“先执行一次再判断”的写法:
Do
Debug.Print i
i = i + 1
Loop While i <= 10
Exit Do 可以提前跳出。写 Do While 时确认循环体里一定会修改条件变量,否则会死循环;调试时按 Ctrl+Break 中断。
If score >= 90 Then
grade = "优秀"
ElseIf score >= 80 Then
grade = "良好"
ElseIf score >= 60 Then
grade = "及格"
Else
grade = "不及格"
End If
Select Case grade
Case "A"
bonus = 1000
Case "B"
bonus = 500
Case Else
bonus = 0
End Select
Select Case 适合等值分支,范围判断用 Case Is >= 90:
Select Case score
Case Is >= 90
grade = "优秀"
Case Is >= 60
grade = "及格"
Case Else
grade = "不及格"
End Select
正序删除会跳过下一行:
Sub DeleteBlankRows()
Dim ws As Worksheet
Dim i As Long
Set ws = ThisWorkbook.Worksheets("数据")
Application.ScreenUpdating = False
For i = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row To 2 Step -1
If Trim(ws.Cells(i, "A").Value & "") = "" Then
ws.Rows(i).Delete
End If
Next i
Application.ScreenUpdating = True
End Sub
从最后一行往前删,当前行删除后不会影响尚未处理的行。也可以用 AutoFilter 筛出空白行后一次删除可见行,速度更快。
For Each 中删除集合元素:工作表、单元格集合都会变;改用倒序索引。For i = 1 To lastRow 包含表头时,表头也会被处理;从第 2 行开始。Do While 条件不变:忘记在循环体里 i = i + 1,直接死循环。And/Or 没有短路:VBA 会计算两边;If IsNumeric(x) And x > 0 Then 在 x 是文本时仍可能报类型不匹配,改成嵌套 If。Exit For 只跳一层:嵌套循环里只退出当前层,外层继续;需要标志变量或 GoTo。ScreenUpdating,设置 Calculation = xlCalculationManual;务必在结束时恢复。Delete 会明显变慢;先标记、再排序删除,或用 AutoFilter 批量删。合上页面,先回答,再展开对照。
For Each 遍历工作表时为什么不能直接 Delete?And/Or 有短路求值吗?If。
小程序版
微信扫码,随时查命令