我正在为Excel编写VBA宏,以删除没有特定标题的列。我已经接近了,但是在删除列的方式上遇到了一个奇怪的问题。
我正在使用一个简单的嵌套IF。奇怪的是,当我运行代码时,它只会删除列表中未包含的所有OTHER列。我必须运行宏4到5次才能获得想要的结果。该代码本应成为更大的宏的一部分,并且也将供其他用户使用,因此使其首次正常运行是关键。
Sub DeleteColumns()
Set MR = Range("A1:W1")
For Each cell In MR
If cell.Value <> "Cartons" Then
If cell.Value <> "ShipVia" Then
If cell.Value <> "Name" Then
If cell.Value <> "Address" Then
If cell.Value <> "City" Then
If cell.Value <> "State" Then
If cell.Value <> "Zip" Then
cell.EntireColumn.Delete
End If
End If
End If
End If
End If
End If
End If
Next
End Sub
答案 0 :(得分:3)
您看到的问题是由于您要删除循环范围内的列。删除列时,您要遍历的范围会发生变化,这会导致列被跳过(与结果一致)。为了解决这个问题,您可以使用Union
方法,该方法允许您删除循环外的列,这样就不会遇到报告的问题。底部的解决方案显示了如果您决定删除循环内的列,则如何解决所报告的问题。
Select Case
是我的首选方法。遍历该范围,如果在第一种情况下未列出该单元格,则在第二种情况下将其标记为删除(Case Else
)。
循环标题后,立即删除所有列,这意味着在循环时不会发生范围偏移。
Sub DeleteColumns()
Dim iCell As Range, DeleteMe As Range
For Each iCell In Range("A1:W1")
Select Case iCell
Case "Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip"
'Do Nothing
Case Else
If Not DeleteMe Is Nothing Then
Set DeleteMe = Union(DeleteMe, iCell)
Else
Set DeleteMe = iCell
End If
End Select
Next iCell
If Not DeleteMe Is Nothing Then DeleteMe.EntireColumn.Delete
End Sub
您也可以遍历数组。请注意,列循环将向后移动以阻止相关范围在循环内移动(您的初始问题)。为此,您需要放下For Each
循环并切换到For j = # - #
,以便可以利用Step -1
属性
Sub Array_Method()
Dim Arr: Arr = Array("Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip")
Dim i As Long, j As Long
For j = 23 To 1 Step -1
For i = UBound(Arr) To LBound(Arr)
If Arr(i) = Cells(1, j) Then
Cells(1, j).EntireColumn.Delete
End If
Next i
Next j
End Sub
答案 1 :(得分:0)
@urdearboy 在诊断问题上是绝对正确的。这是我针对Select Case
主题的一种变体,这是一种紧凑且描述性强(可读)的方法。
Sub DeleteColumns()
Dim LastCol As Long
Dim i As Long
LastCol = ActiveSheet.Range("A1:W1").Cells.Count
i = 1
Do
Select Case ActiveSheet.Cells(1, i)
Case "Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip"
i = i + 1 ' this column is to remain; examine the next column
Case Else
ActiveSheet.Cells(1, i).EntireColumn.Delete
LastCol = LastCol - 1 ' as you delete columns the right margin moves in
' do not increment "i" because the next column moves in place automatically
End Select
Loop Until i > LastCol
End Sub
希望这有助于说明列删除的“机制”。
要使代码具有更高的效率(鉴于上述情况),我们需要从右开始,以便只需要一个“位置”变量:
Sub DeleteColumns()
Dim i As Long
i= ActiveSheet.Range("A1:W1").Cells.Count
Do
Select Case ActiveSheet.Cells(1, i)
Case Is <> "Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip"
ActiveSheet.Cells(1, i).EntireColumn.Delete
End Select
i = i - 1
Loop While i > 0
End Sub
当然,这可以很容易地推广到例如范围不在“ A”列等开头的情况。