简体   繁体   中英

Excel vba: Array of Ranges of huge numbers, how to delcare

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM