views:

71

answers:

3

Let's say I have the following code:

Sub TestRangeLoop()
    Dim rng As Range
    Set rng = Range("A1:A6")

    ''//Insert code to loop through rng here
End Sub

I want to be able to itereate through a collection of Range objects for each cell specified in rng. Conceptually, I'd like to do it like so:

For Each rngCell As Range in rng
     ''//Do something with rngCell
Next

I know I could solve this by parsing rng.Address and building Range objects manually, but I'm hoping there is a more direct way that doesn't involve string parsing.

+1  A: 

You could use Range.Rows, Range.Columns or Range.Cells. Each of these collections contain Range objects.

Here's how you could modify Dick's example so as to work with Rows:

Sub LoopRange()

    Dim rCell As Range
    Dim rRng As Range

    Set rRng = Sheet1.Range("A1:A6")

    For Each rCell In rRng.Rows
        Debug.Print rCell.Address, rCell.Value
    Next rCell

End Sub

And Columns:

Sub LoopRange()

    Dim rCell As Range
    Dim rRng As Range

    Set rRng = Sheet1.Range("A1:A6")

    For Each rCol In rRng.Columns
        For Each rCell In rCol.Rows
            Debug.Print rCell.Address, rCell.Value
        Next rCell
    Next rCol

End Sub
code4life
How would you use those properties to create a loop. I've been playing around with properties of `Range` such as the ones you mentioned and I can't seem to figure out how to use them to give me the information I need.
Ben McCormack
+3  A: 
Sub LoopRange()

    Dim rCell As Range
    Dim rRng As Range

    Set rRng = Sheet1.Range("A1:A6")

    For Each rCell In rRng.Cells
        Debug.Print rCell.Address, rCell.Value
    Next rCell

End Sub
Dick Kusleika
This worked perfectly, but I'm surpised as to why it worked since `Cells` is just a `Range` object. In fact, I removed `.Cells` from `rRng` in the `For Each` line and it still worked. What about `Range` makes it look like a collection of `Range`s? Thanks so much for your help!
Ben McCormack
http://www.dailydoseofexcel.com/archives/2004/07/07/the-strange-object/The Cells property is the default property in this context, so that's why it works without it. In other contexts, the Value property is the default property. All Range objects are really collection objects that contain Range objects - to infinity I guess. The Range is a decidedly strange object and breaks the object/object collection paradigm at every turn. But in most cases, it just works. :)
Dick Kusleika
@Dick thanks for the additional insight. I wish that I had learned that "it just works" with `Range` about 4 years ago when I started doing VBA programming :-).
Ben McCormack
A: 

To make a note on Dick's answer, this is correct, but I would not recommend using a For Each loop. For Each creates a temporary reference to the COM Cell behind the scenes that you do not have access to (that you would need in order to dispose of it).

See the following for more discussion:

http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c

To illustrate the issue, try the For Each example, close your application, and look at Task Manager. You should see that an instance of Excel is still running (because all objects were not disposed of properly).

A cleaner way to handle this is to query the spreadsheet using ADO:

http://technet.microsoft.com/en-us/library/ee692882.aspx

Mark Avenius
I don't think these warnings apply to this question, though. Ben is using VBA, presumably within the same instance of Excel as the Ranges he is working with.
jtolle
I am just using VBA. I appreciate the word of caution, but this particular solution is of the throw-away I-just-need-to-loop-through-some-cells-to-generate-some-SQL-code-so-I-can-finish-my-script-and-move-with-my-life variety.
Ben McCormack
Whoops; you are right :-) I assumed you were working with VB.Net and was completely led astray by my own mind. Sorry about that.
Mark Avenius