I have a function that takes ranges from a worksheet and stores them in an array:
Function test()
Dim resultArray(1 To 3, 1 To 2) As Range
Set resultArray(1, 1) = ThisWorkbook.Worksheets("setup").Range("A1:A1000")
Set resultArray(2, 1) = ThisWorkbook.Worksheets("setup").Range("B1:B1000")
Set resultArray(3, 1) = ThisWorkbook.Worksheets("setup").Range("C1:C1000")
Set resultArray(1, 2) = ThisWorkbook.Worksheets("setup").Range("D1:D1000")
Set resultArray(2, 2) = ThisWorkbook.Worksheets("setup").Range("E1:E1000")
Set resultArray(3, 2) = ThisWorkbook.Worksheets("setup").Range("F1:F1000")
test=resultArray
End Function
However, I'm not sure what is the right way of declaring the array. If I declare it As Range
how are the values stored inside? The numbers are huge and even Long can't store them. Are numbers stored As Variant
if I declare the array As Range
or as something else? How should I declare the array given my situation?
What should I choose - declare As Range
or As Variant
?
Try like this:
Option Explicit
Public Sub TestMe()
Dim myArr As Variant
myArr = Application.Transpose(Range("A1:A3"))
Debug.Print LBound(myArr)
Debug.Print UBound(myArr)
Debug.Print myArr(1)
Debug.Print myArr(2)
End Sub
Note - just be careful, in this example the array will start with 1
, not with 0
. And this is how to do it with a function:
Option Explicit
Public Sub TestMe()
Debug.Print ReturnArray(1)
Debug.Print ReturnArray(2)
Debug.Print LBound(ReturnArray); UBound(ReturnArray)
End Sub
Public Function ReturnArray() As Variant
ReturnArray = Application.Transpose(Range("A1:A3"))
End Function
If you have your data in one row, to make it 1 dimensional array, you could transpose it twice.
Like this:
Option Explicit
Public Sub TestMe()
Dim myArr As Variant
myArr = ReturnArrayHorizontal
Debug.Print myArr(1)
Debug.Print UBound(myArr)
Debug.Print LBound(myArr)
End Sub
Public Function ReturnArrayHorizontal() As Variant
With Application
ReturnArrayHorizontal = .Transpose(.Transpose(Range("A1:E1")))
End With
End Function
Edit: To get a multidimensional array from range with many columns and rows, imagine you have the following:
Then try playing with this:
Public Sub Testing()
Dim resultArray As Variant
resultArray = Range("A1:F10")
Debug.Print resultArray(1, 1)
Debug.Print resultArray(10, 6)
End Sub
not sure what you try to achieve but here is a way to define your array
Function test() ' returns an array
Dim resultArray
resultArray = ThisWorkbook.Worksheets("setup").Range("A1:A1000")
'resultarray is now an array (1 to 1000,1 to 1)
test = resultArray
End Function
If you use SET then you are effectively storing a pointer to the range object rather than the values that the range contains. You can use SET with a variant, which will then contains a range object pointer, or more directly you can use SET with a range variable.
To retrieve the data the most efficient way is to assign range.value2 to a variant. You don't need to dimension the variant or use Transpose - the variant will contain a 2-dimensional array of variants.
Not sure about usage of your data, which normally may turn this approach more or less advisable.
About data types: all numerical values in Excel are stored as Double
. Carefull, sometimes numbers are stored as text, and so, are not handled as numbers. But...
You can't declare your array as Double
, because you are not building a plain array, but nested arrays. Even if was a plain array, you wouldn't be able to assign all range at once because Range.Value
returns a Variant()
and VBA can't cast between different array types. This way, your only option is use Variant
. You could also use Range
, but this way you will not cache values, just get range references in an array!
So your only solution is:
Function test()
Dim resultArray(1 To 3, 1 To 2) 'As Variant <- implict
resultArray(1, 1) = ThisWorkbook.Worksheets("setup").Range("A1:A1000")
resultArray(2, 1) = ThisWorkbook.Worksheets("setup").Range("B1:B1000")
resultArray(3, 1) = ThisWorkbook.Worksheets("setup").Range("C1:C1000")
resultArray(1, 2) = ThisWorkbook.Worksheets("setup").Range("D1:D1000")
resultArray(2, 2) = ThisWorkbook.Worksheets("setup").Range("E1:E1000")
resultArray(3, 2) = ThisWorkbook.Worksheets("setup").Range("F1:F1000")
test = resultArray
End Function
But, in my opinion, best option is cache all data at once:
Function test()
test = ThisWorkbook.Worksheets("setup").Range("A1:F1000")
End Function
Appendix - About object/value assignment:
To make an object assignment you will have always to use Set
. Using Let
(which is usually omitted) you assign values. When you try to assign a object to a value, default member is called and if it is a value, it is assigned. If object doesn't have a default member or default member is not a value, you will get runtime error 438 - Object doesn't support this property or method. In following example, obj
will be assigned a Range
object instance, while val
will receive range values (all four syntax are exactly the same). At last nop
will cause error because Worksheet
do not have a default property.
Set obj = Range(...)
Let val = Range(...).Value
val = Range(...).Value
Let val = Range(...)
val = Range(...)
nop = ActiveSheet
At last, VBA treats arrays as values so you may copy entire arrays with single assignment:
arr1 = Array(...)
arr2 = arr1 'arr2 will turn a copy of arr1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.