vba 在非连续范围内循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2568141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 11:30:13  来源:igfitidea点击:

vba Loop over a non-contiguous range

excelvba

提问by Jeffrey

I have a non-contiguous range on rows (example address of myRange: $2:$2,$4:$205,$214:$214) and I would like to access a specific row and column within the range. I have tried the following:

我有一个不连续的行范围(myRange 的示例地址:$2:$2,$4:$205,$214:$214),我想访问该范围内的特定行和列。我尝试了以下方法:

'Get the value of the 2nd row, 1st column within the range

'获取范围内第二行第一列的值

myRange.rows(2).Cells(, 1).Value

However, this is giving me the value of the 2nd row in the WorkSheet, and NOT in the range - meaning it is giving me address $3$1 - and not $4$1

但是,这给了我工作表中第二行的值,而不是在范围内 - 这意味着它给了我地址 $3$1 - 而不是 $4$1

Can someone please explain how I can access the values within in my range? (It may have to do with different areas)

有人可以解释我如何访问我范围内的值吗?(可能与不同地区有关)

Thank You

谢谢你

回答by Dick Kusleika

Here are my entries - not necessarily better than Irwin's

这是我的条目 - 不一定比欧文的好

Function GetValue(rInput As Range, Row As Long, Column As Long) As Variant

    Dim rArea As Range
    Dim lCumRows As Long
    Dim lActualRow As Long

    For Each rArea In rInput.Areas
        lCumRows = lCumRows + rArea.Rows.Count
        If Row <= lCumRows Then
            lActualRow = rArea.Rows(1).Row + (Row - (lCumRows - rArea.Rows.Count + 1))
            Exit For
        End If
    Next rArea

    If lActualRow > 0 Then
        GetValue = rInput.Parent.Cells(lActualRow, Column).Value
    End If

End Function

Function GetValue2(rInput As Range, Row As Long, Column As Long) As Variant

    Dim rRow As Range
    Dim lRowCnt As Long

    For Each rRow In rInput.Rows
        lRowCnt = lRowCnt + 1
        If lRowCnt = lrow Then
            GetValue2 = rRow.Cells(1, Column).Value
            Exit For
        End If
    Next rRow

End Function

And go read http://www.dailydoseofexcel.com/archives/2004/07/07/the-strange-object/for some insight as to why Excel is behaving that way.

并阅读http://www.dailydoseofexcel.com/archives/2004/07/07/the-strange-object/以了解为什么 Excel 会这样。

And the test proc if you're interested

如果你有兴趣,测试过程

Sub test()

    Dim myRange As Range

    Set myRange = Union(Rows(2), Range("4:205"), Rows(214))

    Debug.Print GetValue(myRange, 1, 2), GetValue(myRange, 1, 2)
    Debug.Print GetValue(myRange, 2, 2), GetValue(myRange, 2, 2)
    Debug.Print GetValue(myRange, 3, 2), GetValue(myRange, 3, 2)
    Debug.Print GetValue(myRange, 200, 2), GetValue(myRange, 200, 2)

End Sub

回答by Irwin M. Fletcher

I think what you are wanting VBA to do is to see your non-contiguous range as a contiguous one. I don't think the approach that you are taking will work. You will have to treat this like multipe contiguous ranges. The following code should get you started. Where rowSelection is the row in your range that you are interested in. If you enter 2, it will select row 4 in the workbook as it is the second row in your range.

我认为您希望 VBA 做的是将非连续范围视为连续范围。我认为您采用的方法行不通。您必须将其视为多个连续范围。以下代码应该可以帮助您入门。其中 rowSelection 是您感兴趣的范围中的行。如果输入 2,它将选择工作簿中的第 4 行,因为它是您范围中的第二行。

Sub Macro1()

    Dim rowCounter As Long
    Dim rowSelection As Long

    rowSelection = 2
    For Each Rng In Range("A2:A2,A4:A205,A214:A214").Areas
         If Rng.Rows.Count >= rowSelection Then
            Rng.Rows(rowSelection - rowCounter).Cells(1, 1).Select
            End
         Else
            rowCounter = rowCounter + Rng.Rows.Count
         End If
    Next Rng

End Sub

回答by will

This code iterates through a named range:

此代码遍历命名范围:

Dim c As Range

x=0

For Each c In Range("MyNamedRange")

    'if x = pick a number and do something here

    MsgBox c.Address & vbTab & c.Value

x=x+1

Next c

回答by Jeffrey

Thank you everyone for their answers -- Before saw these answers I figured it out myself and so far it is working. I wont say it is the most efficent method but seems to work:

谢谢大家的回答——在看到这些答案之前,我自己弄明白了,到目前为止它是有效的。我不会说这是最有效的方法,但似乎有效:

 Public Function NextRow(index As Integer, rows As Range) As Range
    Dim i As Integer, r As Range
    i = 1
    Set NextRow = Nothing
    For Each r In rows.rows
        If i = index Then
            Set NextRow = Range(r.Address)
            Debug.Print "NextRow: " & NextRow.Address
            Exit Function
        End If

        i = i + 1
    Next r

End Function

It seems similar 2nd answer - baically I am advancing to range to index I want to work with and than I return a range set by the address (!important)

这似乎与第二个答案相似 - 基本上我正在推进到我想要使用的索引范围,然后返回由地址设置的范围(!重要)

I than call it like this:

我不是这样称呼它的:

NextRow(2, myRange).Cells(,1).value