如何删除没有特定标题的列?

时间:2019-01-18 20:40:35

标签: excel vba

我正在为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

2 个答案:

答案 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”列等开头的情况。