28

I am having a few problems with some VERY simple lines of code. Let me detail the facts and see if anyone else can replicate this behavior. If any one can replicate I would like to get an explanation of why it is happening.

So lets me start with a very simple line of code THAT WORKS:

Dim arr() As Variant
arr = Range("A1:A10")

this does as expected, arr is assigned the Values of A1:A10

now why won't the following line of code work?

Dim arr() As Variant
arr = WorkSheets("Sheet1").Range("A1:A10")

I get a Run-Time Error '13' Type mismatch, even though the same range was successfully assigned to the array, just without the Worksheet value.

But

Dim arr As Variant
arr = Worksheets("Sheet1").Range("A1:A10")

And

Dim arr() As Variant
arr = Application.Transpose(Application.Transpose(Worksheets("Sheet1").Range("A1:A10")))

DOES WORK

Now before you answer please let me give you some more facts.

Dim arr() As Variant
arr = Worksheets(1).Range("A1:A10")

Does Not Work

and using Sheets in place of Worksheets also all give the same error.

I have made sure it is the same sheet as the active referenced sheet by using Range("A1:A10").Worksheet.Name Following the working code and it indeed says Sheet1 in the output.

No other workbooks are open so it can't be referencing another workbook either.

Now this last bit of code only adds to my confusion as it totally works!

Dim arr() As Variant
Dim SampleRange As Range

Set SampleRange = Worksheets("Sheet1").Range("A1:A10")
arr = SampleRange

So using the SAME RANGE defined the same way on the same sheet now works when I assign it to a Range Variable. and use that! And as expected this works with both the WorkSheets and Sheets function regardless of how I define the sheet (I can use the index or the Name of the worksheet and all work fine)

If it helps anyone, I am testing this with Excel 2007 on a Windows XP machine. I have not yet tested it on any other machines but I plan to test on 2003 and 2010 on Windows 7 and 8, just haven't had the chance yet.

UPDATE: Not 100% sure if this is the same exact issue as with the array but from a shallow view it seems to be:

 Range("B1:B3") = Range("A1:A3") 

The above code will not work, even if A1:A3 is populated, dates, numeric values, strings, formula anything, it will write blanks into B1:B3

But

Range("B1:B3").Value = Range("A1:A3").Value

And

Range("B1") = Range("A1")

does work!

Also working is:

Range("B1:B3") = Application.Transpose(Application.Transpose(Range("A1:A3")))
pnuts
  • 58,317
  • 11
  • 87
  • 139
user2140261
  • 7,855
  • 7
  • 32
  • 45
  • `arr = Worksheets(1).Range("A1:A10").Value` works – Dmitry Pavliv Jan 27 '14 at 16:59
  • @simoco It does not for me, I did also test that along with `Value2`, nothing works all was tested, just forgot I tested that, I still get the same error. Type Mismatch, what OS and versino of excel are you using? – user2140261 Jan 27 '14 at 17:03
  • Excel 2003 / Excel 2013, win 8.1. – Dmitry Pavliv Jan 27 '14 at 17:05
  • 1
    I'm thinking this has something to do with the default behavior of referring to `Range`. Often `Range(X)` can be used to refer to the contents of the range `X`. If we instantiate it as the Range property of a Worksheet, I'm thinking we refer to that hardcoded "Range-ness" of it. However, this does not explain why setting it to a variable bypasses it. Hopefully, someone can come along and explain it. `Value` solves it for me either way, though. Win7, XL2010. – WGS Jan 27 '14 at 17:09
  • @simoco That is interesting, when you simply used `arr = Worksheets(1).Range("A1:A10")` did it work? as the `Value` property is typically the default property used in VBA when a property is not specified? And even if not why would the variable take a different property then the array? – user2140261 Jan 27 '14 at 17:09
  • And just to be clear... I experience your original issues the same EXCEPT when I add `.Value` at the end. If I do, no errors in any of the tests above. – WGS Jan 27 '14 at 17:11
  • 5
    I have no idea why the second method doesn't work when the first does. This is not typically how you'd assign a range directly to an array though: usually you'd declare `arr` as `Variant`, and not as an array of variants, which is what you have here. Using just a regular Variant you will not see this behavior. Adding `.Value` to the end of your second method also fixes the problem, so must be something related to relying on the default property being different between the two approaches. – Tim Williams Jan 27 '14 at 17:11
  • @user2140261, `arr = Worksheets(1).Range("A1:A10")` doesn't work. `arr = ActiveSheet.Range("A1:A10")` doesn't work as well. But ``arr = ActiveSheet.Range("A1:A10").Value` works without any problems..I'm confused, because `.Value` should be the default property of `Range` object – Dmitry Pavliv Jan 27 '14 at 17:12
  • 1
    @user2140261, changing `Dim arr() As Variant` to `Dim arr As Variant` fixes problem for me and `arr = Worksheets(1).Range("A1:A10")` works fine! – Dmitry Pavliv Jan 27 '14 at 17:14
  • @TimWilliams I've assigned MANY MANY arrays in the past, just never noticed this bug as I typically always Dim and Assign all my variable at the begining of all code just for the ease of updating in the future, but just something I was playing with and noticed, I think I originally learned to dim the arrays a yer or two ago based on an article from Chip Pearson. I'll try and link the article if I can find it again though. – user2140261 Jan 27 '14 at 17:15
  • 2
    @simoco is correct. Removing `()` and just leaving `Dim arr As Variant` will correct the issue on the `Worksheets...` part. Now, how to understand all of this. :D – WGS Jan 27 '14 at 17:17
  • 1
    @simoco Yeah dimming it in that manner also fixes it for me, for the record the article I was speaking of was [Here](http://www.cpearson.com/excel/ArraysAndRanges.aspx) – user2140261 Jan 27 '14 at 17:17
  • ANOTHER STRANGE THING: `Dim arr() As Variant: arr = Sheet1.Range("A1:A10")` work well. Note that I've used `arr()` with brackets – Dmitry Pavliv Jan 27 '14 at 17:20
  • @simoco Might be something completly unrelated but when using you EXACT code it worked fine but when using a sheet with a different name, in my testin I used *Sample* (first renamed the sheet then ran your code and changed only Sheet1 to Sample, and got a compile error. – user2140261 Jan 27 '14 at 17:23
  • @user2140261 - I see that page: I guess I've never used that notation, but you are correct that's how Chip does it... – Tim Williams Jan 27 '14 at 17:28
  • @user2140261 ..look at this [picture](http://www.globaliconnect.com/excel/images/ExcelVBA/VBE/vbe_4.gif). Your sheet has two names: for VBA variable and for tab name (in brackets). I.e. if your sheets has name "VBE_intro" (as in picture) you should use `Sheet1.Range("a1")` in VBA code. Is it true for you? I mean that you should use `Sheeti` corresponding to name "Sample" in brackets for using it as VBA variable – Dmitry Pavliv Jan 27 '14 at 17:29
  • 1
    Probably related to the binding of the Worksheet reference as late binding (`Dim arr() As Variant: Dim sheet As Worksheet: Set sheet = Worksheets("Sheet1"): arr = sheet.Range("A1:A10")`) works fine. Using VarPtr to read the return address of `Range("A1:A10")` (and late binding) they return object references whereas `Worksheets("Sheet1").Range("A1:A10")` returns an object within a variant (offset 1==9) which is probably preventing the Range->Variant() conversion. – Alex K. Jan 27 '14 at 18:16
  • @AlexK. Working off what you said I think that is because `Range` is not a member of the `Worksheets` class, but instead the `Worksheet` class, So in order to get the `Range` variable from the worksheets class, excel already has to convert the Entered parameters into the `Worksheets `class to convert that object into the `Worksheet` object it needs to get the `Range` memeber of that object. But I don't understand is that If I use the `VarType` or `TypeName` function on both representations they all return the same `Range` type, so along with what you are saying it seems – user2140261 Jan 27 '14 at 18:43
  • 1
    that both methods return `Range` type variables, where one further returns the `Value` property while the other does not, the same reasoning explains why when explicitly stating the `Value` Property worked for pretty much everyone. I suppose I am just not at a level of programming where I can understand the WHY of this, and that is exactly why I asked the question. I am looking for a deeper level of knowledge here. @simoco tag you also as you seemed interested as I. – user2140261 Jan 27 '14 at 18:44
  • 1
    @AlexK. That's all Ok, but I don't understand why this works `Dim arr As Variant: arr = Worksheets("Sheet1").Range("A1:A10")` but this doesen't `Dim arr() As Variant: arr = Worksheets("Sheet1").Range("A1:A10")`? Note at the brackets after `arr()` – Dmitry Pavliv Jan 27 '14 at 18:51
  • @simoco Dang Nab-bit, that contradicts everything I ***Thought*** I just *Figured Out*. Because clearly it *IS* returning the Value property of the Range Class in both situations. – user2140261 Jan 27 '14 at 18:54
  • @user2140261, ok, why this doesn't work `Dim arr() As Variant: arr = Worksheets("Sheet1").Range("A1:A10")`, but this works `Dim arr() As Variant: arr = Worksheets("Sheet1").Range("A1:A10").Value` (for me and for BK201)? It's make me confused, because `.Value` is default property.. – Dmitry Pavliv Jan 27 '14 at 18:58
  • @simoco That ***I THINK*** is explained in my double comment, that without explicitly stating the you want the `Value` Property of the `Range` class, that after excel does all the work of converting `Worksheets("Sheet1")` to the `Worksheet` function (note the lack of `S`, because according to the Toolbox in VBA `Range` ***IS NOT*** a member of `WorkSheets`) that you are then asking for the `Range` Property of the `Worksheet` class and that is EXACTLY what it is returning, not a Property of the `Range` class but the `Range` Object itself. But then that thought process gets thrown out – user2140261 Jan 27 '14 at 19:28
  • When you take into account this works `Dim arr As Variant: arr = Worksheets("Sheet1").Range("A1:A10")` – user2140261 Jan 27 '14 at 19:28
  • @user2140261 i think Tim already pointed it out. there's a difference between `arr As Variant` and `arr() as Variant`. `arr As Variant` may contain objects. `arr() As Variant` cannot and therefore may not be assigned with Objects. following that logic, excel cannot assume the default property `Value` during assigning `arr = Worsheets("Sheet1").Range("A1:A10")` it already fails. – L42 Jan 28 '14 at 02:24
  • @L42 Thats 100% false and is proven to be false by the fact that `Dim arr() As Variant : arr = Range("A1:A10")` works without issues, `arr() as Variant` ***IS*** assigned with objects, and excel DOES assume the default property `Value` during assigning... – user2140261 Jan 28 '14 at 03:43
  • @user2140261 i posted an answer to help you get to see my point. sorry it's long to fit in comment so i posted it as answer. – L42 Jan 28 '14 at 05:05

3 Answers3

35

No it is not a bug.

The point is that Value is the default property of the Range Object, so why isn't it implicitly used? Did you have a look at the question I linked? (FROM CHAT)

The experts posting previous answers have already explained very well in details. I will keep the explanation to minimal and hence let me know if you still have any questions.

Let's understand our objects first. I created this small table which clearly shows what are we handling so that there is no confusion.

enter image description here

You could also add a Watch to see the Type for a particular object as shown in the pic below.

enter image description here

So when you say

arr = Range("A1:A10")

Excel knows that the default property is .Value. However in other case, it doesn't know because Excel is not a mind reader or let's say intelligent enough to understand whether you want to use Worksheets("Sheet1").Range("A1:A10") as a Range or a Variant

Once you explicitly specify your object as a Range then Excel knows what you want. For example this works.

Dim arr() As Variant
Dim Rng As Range  
Set Rng = Worksheets("Sheet1").Range("A1:A10")
arr = Rng
Community
  • 1
  • 1
Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
4

Let me clarify my comment.
It can't fit to comment to i post it as answer just to at least clear my point.

Dim arr As Variant '~~> you declare arr as Variant as what Tim said

what does it mean?
It means that arr can take on any form (eg. integer, string, array, object and all the other Variable Type)

Dim arr() as Variant '~~> you declare arr() as array which may contain Varying `Data Type`

what does it mean?
It means that arr() array variable can store different Data types.
That excludes Objects or Collection of Objects.

Now, why the following works:

1. Dim arr() As Variant: arr = Range("A1:A10")
2. Dim arr() As Variant: arr = Sheet1.Range("A1:A10")
3. Dim arr() As Variant: arr = Sheets("Sheet1").Range("A1:A10").Value

This also works:

4. Dim arr() as Variant
   Dim rng as Range

   Set rng = Sheets("Sheet1").Range("A1:A10")
   arr = rng

Above works because you are not trying to assign Collections of Objects into an array.
Instead, you are assigning a specific entity or value.
Range is an object but not a Collection of Objects.
No.1 example is direct without accessing Sheets Collection Object.
Same is true with
No.2 since you work with Sheet1 which is a Sheet Object but not Collection of Sheet Objects.
No.3 is self explanatory, you assign .Value to an arr array.
No.4 works because rng is already a Range object by Set which again is not a Collection of Objects.

So this:

Dim arr() As Variant

arr = Sheets("Sheet1").Range("A1:A10")

doesn't work because Excel will read this as trying to assign Object from Sheets Collection of Objects and thus error occurs.
I hope this makes sense a bit.

L42
  • 19,427
  • 11
  • 44
  • 68
  • Both `Range("A1:A3")` and `Sheets("Sheet1").Range("A1:A3")` are `Range Objects` regardless of what you say this is a fact. You can type cast them in many ways and every way that you test both versions they will return a `Range` type. And because of that ***BOTH*** should either implicitly work or fail. Also, you are wrong by stating that `Sheets("Sheet1")` returns a Collection of Sheet Objects. `Sheets` itself *IS* a collection of sheets and when passing the parameter of a sheet name the Sheets Class returns a `Sheet` object not its entire collection. Like Mehow I think its just a bug. – user2140261 Jan 28 '14 at 13:44
  • I think @Siddharth Rout already clear this in his post. Sorry i was sloppy in the way i explain things. :) But i'm glad somehow we cleared our confusion. – L42 Jan 29 '14 at 00:41
2

I would say an Array of Something is not the same as a Something, since this Something can be an Array of some other things. If you define something as an Array, what you assign to it has to be an Array, be it an Array of Number, Text, Range, Chart objects, etc.

When things work that we don't expect, I believe it's the built-in data type conversion that makes things easy for us most of the time. This conversion may have to be a direct object, not properties of an object.

For example, Rows and Cols are of type Long, but you can throw the Byte/Double type at it:

Cells(1,1.5) gives value of Cells(1,2)

You don't have to convert 1.5 to Long; Excel does it all in background for you.

When you define an array of something and assign things to it, Excel does type matching behind the scene and set values when possible.

Check with these in the Immediate window:

?typename(Range("A1:A10").Value) gives you Variant() <-- this is why it works on Dim arr() As Variant without any issues

?typename(Range("A1:A10")) gives you Range. But when you assign it to arr where Dim arr() As Variant, Excel converts the Range to an Array using the values of that Range.

However, Excel seems to fail converting if it doesn't have direct access to the object, unless you created memory for it. For example:

Dim arr() As Variant, oRng As Range
Set oRng = Range("A1:A10")
arr = oRng
Set oRng = Worksheets("Sheet1").Range("A1:A10")
arr = oRng

The above code is all fine, but it cannot convert and assign arr = ThisWorkbook.Worksheets("Sheet1").Range("A1:A10") in one go, unless you throw an array to it (ThisWorkbook.Worksheets("Sheet1").Range("A1:A10").Value is of type Variant()).

TylerH
  • 20,799
  • 66
  • 75
  • 101
PatricK
  • 6,375
  • 1
  • 21
  • 25
  • Plus one. Again it boils down to @Tim Williams statement that declaring a variable as variant is different from declaring an array variable of variant type. – L42 Jan 28 '14 at 06:42
  • 1
    THIS IS FALSE! I don't get why you can't understand that. Because `?typename(Worksheets("Sheet1").Range("A1:A10"))` ***ALSO*** gives you Range yet it does ***NOT*** work with `Dim arr() As Variant`, it's kidn of annoying how many people can take information with no actual proof of facts to back up the statement, besides saying it is what it is. Then use a statement thinking it is a factual statement. – user2140261 Jan 28 '14 at 12:36