I think the existing answers should got you covered, but I would like to add some useful information that is relevant to your question.
First, the syntax Range(Cells(R1,C1), Cells(R2,C2))
refers to the square range that starts from the cell defined by the intersection of row number R1
and column number C1
, till the cell defined by the intersection of row number R2
and column number C2
(assuming that R1 <= R2
, else it is the other way round).
Therefore, the expressions Range(Cells(LastRowP + 2, 10), Cells(LastRowP + 2, 10))
and Cells(LastRowP+2,10)
are identical: they both refer to the cell that lies in the intersection of row number LastRowP+2
(whatever that is) and column number 10
. This is the reason why your code does not work as you expect.
Having said that, there are two important elements that are considered bad practice (and from your comment to t.thielemans anwer it seems that you already discovered one :) ).
Using Select
The macro recorder uses Select
a lot, and it makes it easy for someone to dive into the word of macros.. however, the macro recorder has no idea of what your intention is, and tries to stupidly replicate any action.
What is wrong with Selection
s? First, a Selection
returns whatever the user selects.. It can be a range, or a chart, or a sheet or whatever else... This makes it slow and error prone. The macro will fail if there is no selection, giving a run-time error. It is also slower, but for the majority of macros this is not a big issue.
In general it is not necessary to select ranges or activate worksheets in order to manipulate data. The only case I have found it necessary to activate a cell is when it is needed to programmatically add a comment to a cell. The link that Sid mentions above shows some good ways to manipulate data without selecting/activating stuff (objects).
Qualifying range objects
I assume that VBA
developers rarely use syntax like
Range(Cells(FirstRowP + 1, 9), Cells(LastRowP + 1, 9))
I myself never use it.. This code is looking for trouble :)
Both Range
and Cells
(and also Columns
or Rows
etc ) are shortcuts. when the above code is placed in a VBA module
, it is interpreted as the Range
and Cells
of whichever sheet happens to be activated at the moment. In other words, the compiler understands Range = ActiveSheet.Range
and Cells = ActiveSheet.Cells
. Code like Range("A1")
will probably work "OK" when called from something attached to a worksheet (such as button), because the ActiveSheet
will be the Sheet
that we refer to.. It will still cause trouble if the macro activates another sheet and then tries to refer to the range of the initial sheet (that is why it will probably work "OK"). And it will cause errors when it is called from a shortcut key, a userform etc.
To add to the confusion, if the exact same piece of code is placed in a worksheet module, then Range
and Cells
are interpreted as belonging to that worksheet.. How cool is that? :)
In order to avoid such problems, I personally qualify all objects.. An exception is when the range is Named
(check here for example), then we can refer to it just fine (unless we are in the case below!).
Now, the qualification subtleties carry over across workbooks.. So Sheet1.Range("A1")
implies ActiveWorkbook.Sheet1.Range("A1")
. If we activate a different workbook, Sheet1.Range("A1")
will refer to the range of that workbook. If two named ranges of different workbooks have the same name, then we need to qualify them as well.
To wrap up, avoiding Select
ions and fully qualifying objects will save you from a lot of errors and trouble.
I hope this helps!