【问题标题】:For Each Loops and Multiple Ranges对于每个循环和多个范围
【发布时间】:2013-06-07 17:33:45
【问题描述】:

我有一个颜色编码的表格。我想循环浏览每一行,并返回一个字符串,该字符串表示该行中的哪些列是彩色的。我的方法是定义要循环通过的垂直单元格范围,然后为该范围内的每个单元格定义要循环通过的水平范围。我得到的错误表明 For 变量已在使用中。这是我正在使用的代码:

Public Sub Months()

Dim Tally As String
Dim R1 As Range
Dim R2 As Range
Dim Col As String

Range("A2").Select
Range(Selection, Selection.End(xlDown)).Select
Set R1 = Range(Selection.Address)

For Each cell In R1
    cell.Activate
    Range(Selection, Selection.End(xlRight)).Select
    Set R2 = Range(Selection.Address)
    For Each cell In R2
        If cell.Interior.ColorIndex > 0 Then
            Col = Split(ActiveCell(1).Address(1, 0), "$")(0)
            If Tally Is Nothing Then
                Set Tally = Col
            Else
                Set Tally = Tally + ";" + Col
            End If
            Range("DF" & (ActiveCell.Row)).Select
            ActiveCell.Value = Tally
        End If
    Next
Next

End Sub

有什么想法吗?

非常感谢。

【问题讨论】:

  • 这不能回答你的问题,但我注意到你没有在顶部声明cell。或许可以添加Dim cell as Cell 以便更清楚地了解?
  • 尝试将“R2 中的每个单元格”更改为“R2 中的每个单元格2”
  • @sous2817 会从表面上“修复”它,但它没有回答why 的问题。此外,使用未声明的变量是一种不好的做事方式。此代码中还有其他错误。
  • @PowerUser 不会修复它,因为cell 循环已经在使用中,它不能被重复使用。 OP 需要另一个变量用于第二个循环,并且根据您的评论正确标注它们也是一个好主意:)

标签: vba excel


【解决方案1】:

一如既往,Option Explicit 将帮助您确定此错误的原因。

对于初学者,您不需要多个范围,只需要一个定义整个表格的范围。我将在下面向您展示如何做到这一点。

至于直接的问题

在上下文中,For each cell in ... R1 其中cell 不是特殊关键字,而是正在使用的隐含变量。当您稍后执行For each cell in R2 时,Excel 会对您大笑,因为上面的cell 循环已经启动。

也就是说,如果我们使用伪关键字cell以外的东西,问题可能会更明显:

For i = 1 to 10
    For i = 3 to 44
        Msgbox i
    Next
Next

如果编译器可以到达消息框行,您希望它显示的i 的值是多少?这是错误的原因。您的迭代器已在使用中,您无法重复使用它。

声明所有变量,并使用Option Explicit 以避免将来出现这些错误:)

定义表格范围的更好方法

但是,简单地定义一个范围会更有效,而不是随意尝试为表中的每一行或每一列定义和重新定义行范围。试试这样的。

Option Explicit
Public Sub Months()
Dim Tally As String
Dim tbl As Range
Dim r As Range
Dim c As Range
Dim cl As Range
Dim Col As String

Set tbl = Range(Range("A2").End(xlDown), Range("A2").End(xlToRight))

For Each r In tbl.Rows
    For Each c In tbl.Columns
        Set cl = tbl.Cells(r, c)
        If cl.Interior.ColorIndex > 0 Then
            Col = Split(cl.Address(1, 0), "$")(0)
'            If Tally Is Nothing Then
'                Set Tally = Col
'            Else
'                Set Tally = Tally + ";" + Col
'            End If
            Range("DF" & (cl.Row)).Select
            cl.Value = Tally
        End If
    Next
Next

End Sub

注意:

我已经注释掉了与 Tally 变量有关的代码块,因为有几个错误:

  • Tally 是一个字符串变量。不要使用关键字Set 来分配字符串变量。
  • Tally 是一个字符串变量,因此 Is Nothing 将不匹配。请改为检查 Tally = vbNullStringLen(Tally) = 0
  • 虽然运算符 + 可能允许字符串连接,但我相信 VBA 中的首选运算符是 &,因此虽然这可能不会导致错误,但您可以更改它以消除歧义。

【讨论】:

    【解决方案2】:

    您在嵌套的 For 循环中使用相同的变量名:

    For Each cell In R1
    ...
        For Each cell In R2
    

    将第二个循环中的“cell”变量更改为其他内容。

    另外,这一行:

    If Tally Is Nothing Then
    

    会坏掉。 Tally 被定义为一个字符串,而不是一个对象,所以你应该使用 "If Tally "" Then"

    【讨论】:

      【解决方案3】:

      您应该尽可能避免做出选择。

      未经测试:

      Public Sub Months()
      
      Dim Tally As String
      Dim R1 As Range
      Dim R2 As Range
      Dim Col As String
      Dim c As Range, c2 As Range
      
          With ActiveSheet
              Set R1 = .Range(.Range("A2"), .Range("A2").End(xlDown))
          End With
      
          For Each c In R1.Cells
              Tally = ""
              Set R2 = ActiveSheet.Range(c, c.End(xlToRight)) 'not xlRight...
              For Each c2 In R2.Cells
                  If c2.Interior.ColorIndex > 0 Then
                      Col = Split(c2.Address(), "$")(0)
                      Tally = Tally & IIf(Len(Tally) > 0, ";", "") & Col 'Set not required...
                  End If
              Next
              ActiveSheet.Range("DF" & c.Row).Value = Tally
          Next
      
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-10
        • 2015-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多