It's complicated :)
As all of these access the same object in the end
True. Keywords "in the end". The difference is how many steps it takes to get there...
Unqualified Cells
(or Range
, Rows
, Columns
, Names
, etc.) aren't magic, they're member calls (Property Get
) against a hidden, global-scope object cleverly named Global
:

You can validate that this hidden object is involved, by blowing up in a standard module:
Sub GoesBoom()
'throws error 1004 "Method 'Range' of object '_Global' failed"
Debug.Print Range(Sheet2.Cells(1, 1), Sheet3.Cells(1, 1))
End Sub
_Global
and Global
are closely related - without diving deep into COM, you can consider Global
the class, and _Global
its interface (it's not really quite like that though - look into "COM coClasses" for more information).
But Cells
is a property of the Range
class:

I think it's reasonable to presume that Global
calls are pretty much all redirected to Application
, which exposes all members of Global
, and then some.
Now as you noted, Application
also have a Cells
property - but Cells
belong on a Worksheet
, so no matter what we do, we need to end up with a Worksheet
qualifier... and then any worksheet belongs in a Worksheets
collection, which belongs in a Workbook
object - so we can infer that an unqualified Cells
call would be, in fully-explicit notation, equivalent to... (drumroll):
Application.ActiveWorkbook.ActiveSheet.Cells
But you don't need to be that explicit, because ActiveSheet
has a Parent
that is always going to be the ActiveWorkbook
, so this is also explicit, without going overboard:
ActiveSheet.Cells
But that's all assuming global context. This answer explains everything about it - the gist of it, is that if you're in a worksheet's code-behind, then an unqualified Cells
member call isn't Global.Cells
, but Me.Cells
.
Now, note that Cells
returns a Range
. Thus, whenever you invoke it against a Range
without providing parameters, you're making a redundant member call:
ActiveSheet.Range("A1:B10").Cells ' parameterless Range.Cells is redundant