I am working on a quicker way to cycle through a column in a table in some previously written code. The problem I have is that at some point I need to assign the subject of the With statement (a single cell range) to an array of ranges, depending on the value of the range and nearby cells.
I have trimmed the code and taken only those bits which are necessary to the problem. See below:
Dim wb As Workbook Dim wsFit As Worksheet Dim fittingsTable As ListObject ReDim fittings(0) As Range Dim x As Integer Dim y As Integer Set wb = ActiveWorkbook Set wsFit = wb.Worksheets("Fittings") Set fittingsTable = wsFit.ListObjects("FittingsTable") For x = 1 To fittingsTable.DataBodyRange.Rows.Count With fittingsTable.DataBodyRange(x, 15) If .Value <> vbNullString And .Value <> "0" Then If .Offset(0, -2).Value <> "TBC" Then 'Do some stuff Set fittings(y) = 'PROBLEM HERE Else 'Do other stuff here End If End If End With Next
I want to assign fittingsTable.DataBodyRange(x, 15) to fittings(y), but I have no idea how to access the range that is the subject of the With statement.
I know that I could assign the desired range to another variable before the With statement begins, and then assign that variable to fittings(y) instead, but I feel like there must be a simple way to access the initial subject of the With statement so that I don’t end up clogging my code with yet more variables. I could also use the .Address property to assign the range using the worksheet, but at this point I’m genuinely curious about finding a more direct way.
With block is holding a
Range object reference.
You can use the
.Cells (parameterless) property to retrieve a reference to that
Set fittings(y) = .Cells
Or, to make it more explicit that it’s a single-cell range:
Set fittings(y) = .Cells(1, 1)
This makes an implicit default member call that ultimately ends up being equivalent to:
Set fittings(y) = .Item(1, 1)
That works for a
Range. For a lot of other classes, there is no property that returns a reference to the object. For example, a
With New Collection .Add 42 Set foo = ???? ' can't get a reference to the Collection object! End With
The general solution is to extract the
With block variable into a local variable, and now that variable is accessible just like any other local:
Dim c As Collection Set c = New Collection With c .Add 42 Set foo = c End With
For a custom class that you control, you can have a property getter that returns
Public Property Get Self() As Class1 Set Self = Me End Property
And now the
With block variable is accessible through that property:
With New Class1 .Something = 42 Set foo = .Self End With