【问题标题】:For loop deleting rows doesn't work, need to run macro multiple timesfor循环删除行不起作用,需要多次运行宏
【发布时间】:2017-05-12 07:07:30
【问题描述】:

工作环境:Excel 2013
目标:通过过滤第2行中的内容删除不必要的列。

我的想法是,只要第 2 行的内容是

  • Physical Location
  • PLC Tag Name
  • Test Step1/2/3/4/5/6/7,

保留这些列,否则将其删除。

我的问题是我需要多次运行这个宏来删除所有不必要的列。它应该从 1 循环到 40,然后只留下我想要的列。我不确定为什么它不起作用。 谁能帮我?谢谢!

我的代码:

Sub Reorder()
    Rows(1).Insert shift:=xlShiftDown

    For i = 1 To 40
        WY = Worksheets("Sheet4").Cells(2, i)
        Select Case WY
            Case "Physical Location"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "PLC Tag Name"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step1"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step2"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step3"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step4"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step5"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step6"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case "Test Step7"
                Worksheets("Sheet4").Cells(1, i) = 1
            Case Else
                Worksheets("Sheet4").Cells(1, i) = 0
        End Select
    Next i

    For i = 1 To 40
        If Worksheets("Sheet4").Cells(1, i) = 0 Then
            Columns(i).EntireColumn.Delete
        End If
    Next
End Sub

【问题讨论】:

  • 从 40 循环到 1。

标签: vba excel for-loop


【解决方案1】:

如果循环删除行,需要从底部开始。否则,实际删除行下方的行数会减少 1,i 会增加 1(来自循环),所以总而言之,您会错过一行。

而不是

For i = 1 To 40

使用

For i = 40 To 1 Step -1
    If Worksheets("Sheet4").Cells(1, i) = 0 Then
        Columns(i).EntireColumn.Delete
    End If
Next

向后循环。


旁注:(感谢@A.S.H)
您应该使用完全限定的范围/单元格/行/列,并且永远不要假设工作表。还使用选项显式声明所有变量。

因此

Rows(1).Insert shift:=xlShiftDown
'...
Columns(i).EntireColumn.Delete

应该是

Worksheets("Sheet4").Rows(1).Insert shift:=xlShiftDown
'...
Worksheets("Sheet4").Columns(i).EntireColumn.Delete

所以总而言之,我们最终在

Option Explicit 'first line in module

Public Sub Reorder()
    Dim i As Long
    Dim WY As Worksheet

    Set WY = Worksheets("Sheet4")

    WY.Rows(1).Insert shift:=xlShiftDown

    For i = 1 To 40
        Select Case WY.Cells(2, i)
            Case "Physical Location", "PLC Tag Name", "Test Step1", "Test Step2", _
                 "Test Step3", "Test Step4", "Test Step5", "Test Step6", "Test Step7"
                WY.Cells(1, i) = 1
            Case Else
                WY.Cells(1, i) = 0
        End Select
    Next i

    For i = 40 To 1 Step -1
        If WY.Cells(1, i) = 0 Then
            WY.Columns(i).EntireColumn.Delete
        End If
    Next
End Sub

或者如果我们只使用一个更快的循环:

Option Explicit 'first line in module

Public Sub Reorder()
    Dim i As Long
    Dim WY As Worksheet

    Set WY = Worksheets("Sheet4")

    WY.Rows(1).Insert shift:=xlShiftDown

    For i = 40 To 1 Step -1
        Select Case WY.Cells(2, i)
            Case "Physical Location", "PLC Tag Name", "Test Step1", "Test Step2", _
                 "Test Step3", "Test Step4", "Test Step5", "Test Step6", "Test Step7"
                WY.Cells(1, i) = 1
            Case Else
                WY.Columns(i).EntireColumn.Delete
        End Select
    Next i
End Sub

【讨论】:

  • 只是为了完整性;限定第一行Worksheets("Sheet4").Rows(1).Insert shift:=xlShiftDown(避免另一个问题;))
  • @Peh 谢谢!我什至没有意识到我需要向后循环。现在我知道了。
  • @A.S.H 也谢谢你!一开始就保持良好的练习对每个人都是有益的。再次感谢你们两个!
  • 哈,还有待改进;我刚刚意识到完全没有必要有 2 个循环,因此我们可以大大减少运行时间。因此,如果这只是一个辅助列,您甚至可以省略将 1 写入第 1 列。
猜你喜欢
  • 2023-01-04
  • 1970-01-01
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
  • 2016-04-25
  • 2015-08-19
  • 1970-01-01
  • 2020-09-01
相关资源
最近更新 更多