Got a simple question. The Array() function in VBA does return a two dimensional array? I'm trying to create a one dimensional array with this function and use it in the filter() function but it says "type mismatch". And if that's the case, how can I force Array() to create a one dimensional array?
Sub tester()
Dim xWorkb As Excel.Workbook
Dim xFiles_target() As String
Dim file_path As String
xFiles_target = Array("Bella.xls", "Fizz.xls", "Milo.xls")
file_path = Dir("C:\Users\hans\Desktop\")
Do While Len(file_path) > 0
Debug.Print file_path
If UBound(Filter(xFiles_target, file_path)) >= 0 Then
Debug.Print "found " & file_path
End If
file_path = Dir
Loop
End Sub
Array function does create a 1D Array. However the function requires the variable you are assigning to, to be of Variant type. It cannot be String/Number.
Dim tmpArr() As String
tmpArr = Array("Hello", "World")
The above is likely to throw Type mismatch error. However,
Dim tmpArr()
tmpArr = Array("Hello", "World")
The above will take it as such. That is no error will be thrown but the tmpArray now has two elements to it.
The Split function will result in a String array. Although Variant type can take in String, a Number array cannot take in the Split function.
More information about this neatly organized here : http://patorjk.com/programming/tutorials/vbarrays.htm
Hope this helps.
Related
I've got a question about using two-dimensional array.
Public twolist(,) As String
For i As Integer = 0 To twolist.length()-1
If Func(twolist(i, )) Then 'this part is hard for me
'doing something
End If
Public Function Func(ByVal CancelInput() As String) As Boolean
What i want to do is Passing two-dimensional array to an array.
I want to read one row in two-dimensional array and pass to function(Func), which is using an array.
Hope You can understand my question... and Thank you!
As an alternative to the For Next Loop, you could use Linq (if you are confortable with it) to perform the same task.
This transforms each element of the source array to a String, groups them in an IEnumerable(Of String) and the result is converted to an unidimensional Array of Strings:
Dim twolist(N, N) As String
Dim CancelInput() As String = twolist.Cast(Of String).Select(Function(str) str).ToArray()
Dim result As Boolean = Func(CancelInput)
I have just used an arbitrary size for your array. You need nested For loops to iterate through a 2 dimensional array. The outer loop goes through the rows and the inner loop adds the value in each field to another array that you are passing to your Function. Each row is passed individually as a single dimension array.
Private Sub TwoDimensionalArray()
Dim twolist(,) As String
ReDim twolist(10, 5)
'First you will need to add data to your array
For x As Integer = 0 To 10
Dim arrayRow(5) As String
For y As Integer = 0 To 5
arrayRow(y) = twolist(x, y)
Next
If Func(arrayRow) Then 'this part is hard for me
'doing something
End If
Next
End Sub
Public Function Func(ByVal CancelInput() As String) As Boolean
Return True
End Function
Mary's answer is good, but assumes you know the length of each dimension.
I have changed it slightly to use the Array.GetLength function:
Private Sub TwoDimensionalArray()
Dim twolist(,) As String
ReDim twolist(10, 5)
'First you will need to add data to your array
For x As Integer = 0 To 10
'Fetch the length of this dimension:
Dim i As Integer = twolist.GetLength(x)
Dim arrayRow(i) As String
For y As Integer = 0 To i - 1
arrayRow(y) = twolist(x, y)
Next
If Func(arrayRow) Then
'do something
End If
Next
End Sub
Public Function Func(ByVal CancelInput() As String) As Boolean
Return True
End Function
Note:
In VB.Net, ReDim twoList(10,5) actually gives you an array of (11,6).
Array.GetLength(0) will return 6 (0,1,2,3,4,5).
In short, Dim specifies the maximum index in each dimension, Length & GetLength return the count of elements.
I want to create a multi-dimensional array where I assign all the values at once instead of going through all the array coordinate values one by one. I believe this is called setting 'array literals'. Anyway, all my variables are string values. The code below doesn't give me a syntax error but when I step through I'm getting a "Compile error: Can't assign to array" message on pkg= line. How do I make this work?
Sub test_array2()
Dim pkg(2, 2) As String
pkg = [{"PRetail","Retail Packaged"};{"PFoodservice","Foodservice
Packaged"}]
Debug.Print pkg(1, 1)
End Sub
You cannot assign directly to an array like that, so you need to use a variant:
Sub test_array2()
Dim pkg As Variant
pkg = [{"PRetail","Retail Packaged";"PFoodservice","FoodservicePackaged "}]
Debug.Print pkg(1, 1)
End Sub
VBA Beginner here.
I am trying to pass an array of strings from a subroutine to a function which will then modify each string in the array. However I get the "Type:array or user-defined type expected" error message.
I have tried redefining different data types for the array so it is aligned with the data type entered in the function but to no avail.
Hope you can help! THank you so much!
Below is the dummy code:
Sub text()
Dim haha() As Variant
haha = Array("Tom", "Mary", "Adam")
testing (haha())
MsgBox Join(haha, " ")
End Sub
Function testing(ByRef check() As String) As String()
Dim track As Long
For track = LBound(check) To UBound(check)
check(track) = check(track) & " OMG"
Next
End Function
In orignial code, a string is not the same variant (I believe they both would need to be variant? someone can verify), you dont need the brackets after testing, only need brackets if you are setting to another value e.g.
haha2 = testing(haha())
Below code should be ok
Sub text()
Dim haha()
haha = Array("Tom", "Mary", "Adam")
testing haha()
MsgBox Join(haha, " ")
End Sub
Function testing(ByRef check()) As String
Dim track As Long
For track = LBound(check) To UBound(check)
check(track) = check(track) & " OMG"
Next
End Function
You have a few errors in your code:
There are two ways of invoking methods:
1) with Call keyword - in this case you must give all the parameters in brackets:
Call testing(haha)
2) without Call keyword - in this case you just give your parameters after the name of function:
testing haha
In your code you combined both of them and this is syntax error.
If you pass an array as a parameter to function you don't need to put brackets like that: testing (haha()).
The proper syntax is:
testing(haha)
Function testing requires as a parameter an array of String type, you cannot pass object of other type instead since it causes compile error Type mismatch. Currently you are trying to pass variable haha which is of Variant type.
You can change the type of haha variable to array of strings (to avoid the error described above):
Dim haha() As String
However, in this case you cannot assign the value of function Array to it, since the result of this function is of Variant type.
You would have to replace this code:
haha = Array("Tom", "Mary", "Adam")
with this:
ReDim haha(1 To 3)
haha(1) = "Tom"
haha(2) = "Mary"
haha(3) = "Adam"
A couple of suggestions to improve your code:
Dim haha() As String
You define the type of the entry in the array, not the array itself. Use the way mentioned by mielk to fill the array.
Function Testing(byref check as variant) As String
This will avoid problems with undefined variables. Not clear why you feel that the function should return a string though. Maybe even convert to a Sub instead.
I have a dynamic array of strings DMAs which I declare globally.
Dim DMAs() As String
I ReDim the array and assign values to it in the CreateArrayOf function which is of type String() that returns an array of type String()
DMAs = CreateArrayOf(Sites, 2, "", False)
Public Function CreateArrayOf( _
ByRef arrayFrom() As String, _
Optional ByVal numOfChars As Integer = 2, _
Optional ByVal filterChar As String = "", _
Optional ByVal filterCharIsInteger As Boolean = False _
) As String()
Dim i As Integer, _
j As Integer, _
strn As Variant, _
switch As Boolean, _
strArray() As String
'numOfChars 2 for DMA with no filterChar
'numOfChars 3 for W with filterChar "W"
'numOfChars 3 for A with filterChar "A"
'numofChars 2 for D with filterChar "D"
ReDim strArray(LBound(arrayFrom) To LBound(arrayFrom)) 'required in order to
'not throw error on first iteration
For i = LBound(arrayFrom) To UBound(arrayFrom) 'iterate through each site
switch = False
For Each strn In strArray 'iterate through the array to find whether the
'current site already exists
If strn = Mid(arrayFrom(i), 1, numOfChars) And Not strn = "" Then
switch = True
End If
Next strn
If switch = False Then 'if it doesn't exist add it to the array
ReDim Preserve strArray(1 To UBound(strArray) + 1)
strArray(UBound(strArray) - 1) = Mid(arrayFrom(i), 1, numOfChars)
End If
Next i
CreateArrayOf = strArray 'return the new array
End Function
When I attempt to pass the DMAs array to another function OutputAnArray
Private Sub OutputAnArray(ByRef arrayToOutput() As String)
Dim i As Variant
Dim x As Integer
x = 1
For Each i In arrayToOutput
Cells(x, 6).Value = i
x = x + 1
Next i
End Sub
I get the "Type mismatch: array or user-defined type expected". Throughout the whole process I only mess with string arrays.
If I take the content of the OutputAnArray function and put it in the parent function where I'm calling it from, everything's fine.
Any help is appreciated.
I changed all String definitions to Variants
Private Sub OutputAnArray(ByRef arrayToOutput() As Variant)
The culprit was still there, so then after a whole lot of attempts to get this to compile, I removed the () from the arrayToOutput parameter and it started working.
Private Sub OutputAnArray(ByRef arrayToOutput As Variant) 'fixed
What is still perplexing is the fact that in the following function definition, the () are needed for arrayFrom.
Public Function CreateArrayOf(ByRef arrayFrom() As Variant, _ ...
I really don't get it, if anyone has any idea of an explanation, I'd love to hear it.
From the documentation:
"Arrays of any type can't be returned, but a Variant containing an array can."
If follows that the function "CreateArrayOf" does not return an array of strings: it returns a variant containing an array of strings.
The variant cannot be passed as a parameter to a function expecting an array of strings:
Private Sub OutputAnArray(ByRef arrayToOutput() As String)
It can only be passed to a function expecting a variant:
Private Sub OutputAnArray(ByRef arrayToOutput as Variant)
Conversely, DMA is an array of strings:
Dim DMAs() As String
DMA can be passed to a function expecting an array of strings:
Public Function CreateArrayOf(ByRef arrayFrom() As String, _ .
And finally, "Type mismatch: array or user-defined type expected" is a generic type mismatch message. When you pass an array of the wrong type, or a variant array, and get the error "array expected", it's not particularly helpful.
There is no problem with returning typed arrays from functions or passing typed arrays to functions as arguments. The following works as expected:
Option Explicit
Sub asdfasf()
Dim DMAs() As String
DMAs = CreateAnArray()
OutputAnArray DMAs
End Sub
Private Function CreateAnArray() As String()
Dim arr() As String
ReDim arr(1 To 5)
Dim i As Long
For i = LBound(arr) To UBound(arr)
arr(i) = i
Next
CreateAnArray = arr
End Function
Private Sub OutputAnArray(ByRef arrayToOutput() As String)
Dim i As Long
For i = LBound(arrayToOutput) To UBound(arrayToOutput)
Debug.Print arrayToOutput(i)
Next
End Sub
Now, you never show how you actually pass the DMAs array to OutputAnArray.
I'm willing to make an educated guess that you are doing
OutputAnArray (DMAs)
which will indeed result in
Type mismatch: array or user-defined type expected
You cannot freely put parentheses in that manner. They have special meaning.
If you want parentheses to be used when calling a sub, you must use Call:
Call OutputAnArray(DMAs)
And if you don't care, omit the parentheses like in the example above:
OutputAnArray DMAs
I had the same error while passing an array (of user defined type) as an argument to a function ByRef.
In my case the problem was solved using the keyword "Call" in front of the function or the sub being called.
I don't really understand it, but to me it seems like VBA is trying to interpret the function/sub a couple of different ways in the absence of "Call" - which leads to the error message.
I personally try to avoid converting anything to a variant as long as possible.
Ultimately I'm trying to write out a range into a text file. When I get the value of the range it returns a 2d variant array. However if I try to pass it to the converting function it gives me a type mismatch error.
The code is:
Dim Data As String
Set ts = fso.CreateTextFile("testfile.txt", True)
Data = ArrayToDelimitedString(wksMyWorkSheet.Range("rngMyRange").Value)
ts.Write (Data)
ts.Close
Public Function ArrayToDelimitedString(variantArray() As Variant) As String
Dim delimitedString As String, index As Integer
For index = 1 To UBound(variantArray(1))
delimitedString = delimitedString & CStr(variantArray(1, index)) & ","
Next
ArrayToDelimitedString = Left(delimitedString, Len(delimitedString) - 1)
End Function
I'm wondering why the .Value returns a 2d array and why is it giving me this mismatch error.
The Range() method returns a Variant of Variant.
In the case you want to use a 2D Array (Variant of Strings), use the Transpose method.
ArrayToDelimitedString(wApplication.WorksheetFunction.Transpose(wksMyWorkSheet.Range("rngMyRange").Value))