Reputation: 5303
I have the following code:
Dim lRow As Long
Dim c As Variant
lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
c = Application.Transpose(ws.Range("A2:A" & lRow).Value2)
As long as lRow
is > 2 then c
becomes a Variant/Variant(1 to x)
i.e. an array of Variant/String
with values from column A - this is what I need!
However, sometimes the lRow
is 2 - this means that c
becomes just a string (instead of an array with one entry) - this messes up code further down the sub.
Is there a way I can use Application.Transpose(ws.Range("A2:A" & lRow).Value2)
to produce an actual array instead of a Variant? Or somehow force c
to always be the array?
Or do I just need to do if
checks on the type and build more logic into the whole thing?
I tried Dim c() As String
but that's not what Transpose
produces...
Upvotes: 0
Views: 433
Reputation: 4558
You should read the range first into a Range variable and then transpose only if it has at least 2 cells:
Dim lRow As Long
Dim c() As Variant
Dim rng As Range
lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set rng = ws.Range("A2:A" & lRow)
If rng.Count > 1 Then
c = Application.Transpose(rng.Value2)
Else
ReDim c(1 To 1, 1 To 1)
c(1, 1) = rng.Value2
End If
Alternatively, you could use a separate function to get the values from a range into an array:
Private Function RangeToArray(ByVal rng As Range) As Variant()
If rng Is Nothing Then Err.Raise 91, "RangeToArray", "Range not set"
If rng.Areas.Count > 1 Then Err.Raise 5, "RangeToArray", "Multi-area range"
If rng.Count > 1 Then
RangeToArray = rng.Value2
Else
Dim arr(1 To 1, 1 To 1) As Variant
arr(1, 1) = rng.Value2
RangeToArray = arr
End If
End Function
But note that when applying Transpose to a 2-dimensional array of 1 value it actually converts it to a 1-dimensional array:
Dim lRow As Long
Dim c() As Variant
lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
c = Application.Transpose(RangeToArray(ws.Range("A2:A" & lRow))) 'c is 1-D if range has only 1 cell
So, the first choice is probably better.
Finally, you could use your own version of Transpose. See my array repository
EDIT 1
Use the following method if you only need 1D Arrays. It works with rows and columns.
Private Function OneDRangeTo1DArray(ByVal rng As Range) As Variant()
Const methodName As String = "OneDRangeTo1DArray"
If rng Is Nothing Then
Err.Raise 91, methodName, "Range not set"
ElseIf rng.Areas.Count > 1 Then
Err.Raise 5, methodName, "Multi-area range"
ElseIf rng.Rows.Count > 1 And rng.Columns.Count > 1 Then
Err.Raise 5, methodName, "Expected 1-row or 1-column range"
End If
Dim arr() As Variant
If rng.Count = 1 Then
ReDim arr(1 To 1)
arr(1) = rng.Value2
Else
Dim v As Variant
Dim i As Long
ReDim arr(1 To rng.Count)
i = 0
For Each v In rng.Value2
i = i + 1
arr(i) = v
Next v
End If
OneDRangeTo1DArray = arr
End Function
Upvotes: 2
Reputation: 5303
Because I was only after a 1D array, I ended up just creating a function to reuse based on Christian Buse's answer:
Public Function GetArrayFromVerticalRange(rng As Range) As Variant
If rng.Count > 1 Then
GetArrayFromVerticalRange = Application.Transpose(rng.Value2)
Else
Dim c(0) As Variant: c(0) = rng.Value2
GetArrayFromVerticalRange = c
End If
End Function
Used "Vertical" term to remind me to only pass in single column ranges! And could create a "Horizontal" version to use the transpose
of the transpose
Upvotes: 0
Reputation: 9907
A Variant IS a TYPE (similar to String
, Long
, Integer
, Byte
, Double
). However, I am guessing you are trying to force a VARIABLE to be a DIFFERENT type (string?) and as part of an ARRAY?
If so, I think this should work for you. It creates an array starting at 0 with a maximum of the last row less two cells. If you wanted to transpose it, or make it multidimensional, just add another layer.
lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
ReDim c(lRow - 2) As String
'if you need two dimensioanl you could experiment with this:
'ReDim c(lRow - 2, 0) As String
Dim i As Long
For i = 0 To (lRow - 2)
c(i) = ws.Range("A2").Offset(i, 0).Value2
'OR if two dimenssional
'C(i,0) =
Next i
Upvotes: 1
Reputation: 3498
another possibilty
c = Application.Index(ws.Range("A2:A" & lRow).Value2, Application.Evaluate("transpose(row(1:" & lRow - 1 & "))"), 1)
Upvotes: 1