A1:B2 type Application.Range referencing don’t quite work like U might think..
Hello
I sort of figured out what I was having a problem with whilst preparing this post to ask for help..
So I thought I would post anyway, for future reference .
I got some strange results whilst trying to explain to someone all about VBA Range Referencing, in particular about Application.Range(“ “) type range referencing.
The crux of the problem was I have ( wrongly as it turns out ) thought for a long time, that I was being very explicit when using this sort of Range Referencing.
Application.Range("='C:\Folder\[Book1.xlsm]Sht2'!A2:B2")
In fact, I was fooling myself, as mostly that works. But actually, as I just realised, it does not always work, and to do it properly, you need to do this sort of thing:
Application.Range("='C:\Folder\[Book1.xlsm]Sht2'!A2:'C:\Folder\[Book1.xlsm]Sht2'!B2")
In other words , don’t be fooled as I was, into thinking you are being very explicit with this
Application.Range("='C:\Folder\[Book1.xlsm]Sht2'!A2:B2")
But it is very easy to make the mistake of thinking you are being very explicit, as I will try to explain…..
There is a demo code below, but in words the summary conclusions are
_ (i) when I , ( and probably a lot of other people ) , thought they were being very explicit in their range referencing, then in fact, I ( and they ) weren’t quite doing it right, and by chance they did not notice…
and
_ something in Range referencing for a contiguous area via a
Range("Top left:Bottom right")
cell pair type reference is a bit quirky, … and I doubt anyone can really explain what is going on.. _
_.. in words this is what happens
‘ _ .. If you do not want Application Range to rely on taking the active worksheet, then the top left must be explicitly referenced. – this first bit is what most people would think. .. the next bits are not all as you might expect..
_ (ii) .. If Top left is not a named range, then you can be un explicit with the Bottom right , and the worksheet referenced by Top left will be taken also for the bottom right – this second bit you probably never thought about. The next bit is the strange bit, which caught me out, and made me realise that up until now, I had not quite been doing it as explicitly as I had thought…
_ (iii) .. If Top left is a named range , then you must be explicit with the bottom right
I don’t find either ' _ (ii) or ' _ (iii) taken on their own strange. What I do find strange is that the behaviour should be different in the two cases, in terms of what you need to do with the bottom right reference.
Excel VBA is defaulting differently in the two cases. I doubt anyone can explain why that should be. I doubt many people ever noticed.. ( I doubt many people care either :) )
_._______________
The demo macro below can be put in any code module. The results will be the same . The important part is section Rem 4 , which demos the points _ (ii) and _ (iii)
I get similar results in Excel 2003, 2007, and 2010 – ( there is a small anomaly whereby I must be a bit more explicit in Excel 2003. I have not quite figured out why yet… )
Code: Select all
Option Explicit
Sub ApplicationRangeReferrencingTopLeftColonBottomRight() ' like Range("A1:B2") type referencing
Rem 1 worksheets info
Dim Ws1 As Worksheet, Ws2 As Worksheet
Set Ws1 = ThisWorkbook.Worksheets.Item(1): Set Ws2 = ThisWorkbook.Worksheets.Item(2)
Let Ws1.Name = "Sht1": Let Ws2.Name = "Sht2"
Ws2.Cells.Clear: Ws1.Cells.Clear
Rem 2 Assign a named range object to the worksheets Names collection object of second worksheet
If Ws2.Names.Count = 0 Then Ws2.Names.Add Name:="NameWkSht2Scoped", RefersTo:=Ws2.Range("A2")
Rem 3 Assign a named range object to the workbooks Names collection object of this workbook
If ThisWorkbook.Names.Count < 2 Then ThisWorkbook.Names.Add Name:="NameWkBkScoped", RefersTo:=Ws2.Range("A2")
Rem 4 use Application Range object to refer to ranges '
'4a) These variations will always work to referrence the second worksheet, regardless of what worksheet is active
Ws1.Activate
Ws2.Cells.Clear
Let Application.Range("=Sht2!A2:Sht2!B2").Value = "A2 - B2" ' _ (i) Truly very explicit
Ws2.Cells.Clear
Let Application.Range("='" & ThisWorkbook.Path & "\[" & ThisWorkbook.Name & "]" & "Sht2'!A2:'" & ThisWorkbook.Path & "\[" & ThisWorkbook.Name & "]" & "Sht2'!B2").Value = "A2 - B2" ' _ (i) Truly very very explicit
Ws2.Cells.Clear
Let Application.Range("=Sht2!A2:B2").Value = "A2 - B2" ' _ (ii) ' This does NOT rely on Sht2 being active. -----*****
Ws2.Cells.Clear
Let Application.Range("=Sht2!NameWkSht2Scoped:Sht2!B2").Value = "A2 - B2" ' _ (iii)a For Excel 2007 and 2010
' Let Application.Range("=[ApplicationRangeBugFeature.xls]Sht2!NameWkSht2Scoped:[ApplicationRangeBugFeature.xls]Sht2!B2").Value = "A2 - B2" ' _ (iii)a For Excel 2003
Ws2.Cells.Clear
Let Application.Range("=Sht2!NameWkBkScoped:Sht2!B2").Value = "A2 - B2" ' _ (iii)b
'4b) These variations will only work to referrence the second worksheet if the second worksheet is active
Ws2.Activate ' _ - If you remove this code line, then _ (i) will reference Sht1 , and the other 3 range referrencing code lines will error.
Ws2.Cells.Clear
Let Application.Range("=A2:B2").Value = "A2 - B2" ' _ (i) very unexplicit - as we expect it is re3ferrencing the active worksheet
Ws2.Cells.Clear
Let Application.Range("=A2:Sht2!B2").Value = "A2 - B2" ' ' This DOES rely on Sht2 being active. -----*****
Ws2.Cells.Clear
Let Application.Range("=Sht2!NameWkSht2Scoped:B2").Value = "A2 - B2" ' _ (iii)a
Ws2.Cells.Clear
Let Application.Range("=NameWkBkScoped:B2").Value = "A2 - B2" ' _ (iii)b
End Sub