I have a number of arrays that have different strings in them like
array1() = Array("one","two","three")
array2() = Array("siz","help")
I combine the strings into an array of the string arrays
bigArray() = Array(array1(),array2(),...)
For k = 0 To # in bigArray
reason = causes(xValue, bigArray(k))
Next
however I get an error at bigArray(k) when I try to pass it to the function
Public Function causes(xValue As String, keyWords() As Variant) As String
The empty parentheses on the left-hand-side of the assignment are redundant and confusing, remove them.
I presume bigArray is declared as such, if at all:
Dim bigArray [As Variant]
If it's not declared, specify Option Explicit at the top of your module (always do this!), and declare every variable you're using - otherwise you allow VBA to happily compile & run typos, and that inevitably turns into embarrassing, hard-to-find bugs, and possibly duplicate questions on Stack Overflow.
A Variant can hold anything, including an array, or a jagged array (i.e. array of arrays).
The keywords parameter though...
Public Function causes(xValue As String, keyWords() As Variant) As String
Is declared as an array where each element is a variant. While the variant element can indeed be an array, when you're passing arrays around as parameters there's no way to say "where each element is an array of variant elements", so you'll have a much easier time if you just wrap it in a Variant (and then assert that you're looking at an array):
Public Function causes(xValue As String, keyWords As Variant) As String
Debug.Assert IsArray(keyWords)
Debug.Assert IsArray(keyWords(LBound(keyWords))
Your For loop is assuming what the lower boundary is:
For k = 0 To # in bigArray
A loop that's not making any assumptions would be:
For k = LBound(bigArray) To UBound(bigArray)
I am working at rewriting C code to Visual Basic now. And I got some problems with this syntaxes:
C code:
typedef uint8_t state_t[4][4];
static state_t* state;
void myFunc (uint8_t* output)
{
state = (state_t*)output;
// some actions
}
My Visual Basic code:
Dim state(3, 3) As Byte
Sub myVBFunc(ByRef output() As Byte)
state = output ' does not work: Cannot convert Byte() to Byte(*,*)'
'state = CType(output, Byte(,)) ''also does not work'
' some actions'
End Sub
I can do it in C, because array name is a pointer to the first element. And C can automatically converts this types. So VB cannot. I'm stacked here.
How to convert this array to matrix?
Or how to avoid using of this in VB?
P.S. Actually I work in Visual Basic 6.0. (try to modify old project).
If the question is about VB6, then you have three options:
a. Change everything to use dynamic arrays:
Dim state() As Byte
Sub myVBFunc(ByRef output() As Byte)
state = output
End Sub
You can set up the array to call myVBFunc by redimensioning e.g.:
Dim myarray() as Byte
ReDim myarray(3,3)
myVBFunc(myarray)
b. Embed the fixed size array in a user defined type and pass that around instead:
Type type_state
state(3, 3) As Byte
End Type
Dim state As type_state
Sub test()
Dim something As type_state
myVBFunc something
End Sub
Sub myVBFunc(ByRef output As type_state)
state = output
End Sub
c. Use objects. Set up a class to hold your fixed sized array and set up getters and setters to access it. A short answer would be to long for me to show in this post.
(You will need extra code to set up the array itself)
I used simple way: just assign it trough the loop using index multiplication.
For k = 0 To 3
For j = 0 To 3
state(k, j) = temp(4 * k + j)
Next j
Next k
Why I didn't use Guillermo Phillips's answer:
a. I can't replace state(3,3) from my question just as
Dim state() As Byte
because there is some specific math here which is really simple for matrices.
I found useful ReDim option. Especially when use it in this way:
ReDim Preserve input(15)
It saves previous values of input array or put zeros in new positions!
But we can convert array to matrix using ReDim:
ReDim cannot change the number of dimensions
b. Idea of using of user defined type is really interesting but I stall can't figure out how to assign then Byte() to my
Type type_state
state(3, 3) As Byte
End Type
c. Agree! This way is useful. I just avoid it because of it's complicity (much easier to create function with inbuilt loop). But maybe using object is more safety?..
Is it possible to either:
Declare an array as a constant
OR
Use a workaround to declare an array that is protected from adding, deleting or changing elements, and therefore functionally constant during the life of a macro?
Of course I could do this:
Const myConstant1 As Integer = 2
Const myConstant2 As Integer = 13
Const myConstant3 As Integer = 17
Const myConstant4 ...and so on
...but it loses the elegance of working with arrays. I could also load the constants into an array, and reload them each time I use them, but any failure to reload the array with those constant values before use could expose the code to a "constant" value that has changed.
Any workable answer is welcome but the ideal answer is one that can be setup once and not require any changes/maintenance when other code is modified.
You could use a function to return the array and use the function as an array.
Function ContantArray()
ContantArray = Array(2, 13, 17)
End Function
How about making it a function? Such as:
Public Function myConstant(ByVal idx As Integer) As Integer
myConstant = Array(2, 13, 17, 23)(idx - 1)
End Function
Sub Test()
Debug.Print myConstant(1)
Debug.Print myConstant(2)
Debug.Print myConstant(3)
Debug.Print myConstant(4)
End Sub
Nobody can change it, resize it, or edit its content... Moreover, you can define your constants on just one line!
I declared a String constant of "1,2,3,4,5" and then used Split to create a new array, like so:
Public Const myArray = "1,2,3,4,5"
Public Sub createArray()
Dim i As Integer
A = Split(myArray, ",")
For i = LBound(A) To UBound(A)
Debug.Print A(i)
Next i
End Sub
When I tried to use ReDim or ReDim Preserve on A it did not let me. The downfall of this method is that you can still edit the values of the array, even if you can't change the size.
If the specific VBA environment is Excel-VBA then a nice syntax is available from the Excel Application's Evaluate method which can be shortened to just square brackets.
Look at this
Sub XlSerialization1()
Dim v
v = [{1,2;"foo",4.5}]
Debug.Assert v(1, 1) = 1
Debug.Assert v(1, 2) = 2
Debug.Assert v(2, 1) = "foo"
Debug.Assert v(2, 2) = 4.5
'* write all cells in one line
Sheet1.Cells(1, 1).Resize(2, 2).Value2 = v
End Sub
If you don't need a new instance each time you can use a Static local variable to avoid multiple objects creation and initialization:
Private Function MyConstants()
Static constants As Variant
If IsEmpty(constants) Then
constants = Array(2, 13, 17)
End If
MyConstants = constants
End Function
Can an array be declared as a constant? No.
Workarounds - Simplest one I can think of is to define a constant with delim and then use Split function to create an array.
Const myConstant = "2,13,17"
Sub Test()
i = Split(myConstant, ",")
For j = LBound(i) To UBound(i)
Debug.Print i(j)
Next
End Sub
Is this too simplistic?
PUBLIC CONST MyArray = "1,2,3,4"
then later in a module:
Dim Arr as Variant
SET Arr = split(MyArray,",")
I know this is an old question, but these archives are often scanned for many years after being posted, so I don't see a problem with adding things long after the origin date.
How about creating a class, with a read-only property returning the 'array' value? You can specify a parameter using the same syntax as an array index, and defining only a GET property effectively makes it read-only. Define the constant values inside the class and it will work just like a constant array, even though the actual construction is different.
No - arrays can't be declared as constant but you can use a workaround.
You can create a function that returns the array you want
http://www.vbaexpress.com/forum/showthread.php?1233-Solved-Declare-a-Constant-Array
Using above information, I came to following working solution for comparing short text information of a month, independent from Excel using German language:
Const MONATE = ",Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez"
.. and later in the code:
If StringToCompare = Split(MONATE, ",")(Month(dt)) Then
NOTE: as the Split-Array starts with index 0 I added the comma in the beginning.
Don't know when this changed, but in Excel 365, this works (or, at least, does not generate a compiler error):
Const table1Defs As Variant = Array("value 1", 42, Range("A1:D20"))
I am trying to use a function to return a 1D array for my subroutine and am running into error's. Below is a simplified version of the code I am using:
Sub test()
Dim testArry(1 To 3) As Double
testArry = arryFunction(1.2) 'I get a compile error here "cant assign to array"
End Sub
Function arryFunction(cs As Double) As Double()
Dim anotherArry(1 To 3) As Double
anotherArry(1) = cs
anotherArry(2) = cs + 1
anotherArry(3) = cs + 3
arryFunction = anotherArry
End Function
I have tried searching for this online and can not find a solution, at least one that I understand therefore, would appreciate some help with this.
While I havent yet found documentation to support this it looks like you error is due to you cannot assign an array to another of fixed size. Possibly since the array needs to be ReDim'ed during the copy but that is just speculation. This does work however
Sub test()
Dim testArry() As Double
testArry = arryFunction(1.2) 'I get a compile error here "cant assign to array"
End Sub
Can anyone help me?
I have been getting a compile error (...: "Expected Array") when dealing with arrays in my Excel workbook.
Basically, I have one 'mother' array (2D, Variant type) and four 'baby' arrays (1D, Double type). The called subroutine creates the publicly declared arrays which my main macro ends up using for display purposes. Unfortunately, the final of the baby arrays craps out (giving the "Compile Error: Expected Array"). Strangely, if I remove this final baby array ('final' - as in the order of declaration/definition) the 2nd to last baby array starts crapping out.
Here is my code:
Public Mother_Array() as Variant, BabyOne_Array(), BabyTwo_Array(), BabyThree_Array(), BabyFour_Array() as Double 'declare may other variables and arrays, too
Sub MainMacro()
'do stuff
Call SunRaySubRoutine(x, y)
'do stuff
Range("blah") = BabyOne_Array: Range("blahblah") = BabyTwo_Array
Range("blahbloh" = BabyThree_Array: Range("blahblue") = BabyFour_Array
End Sub
Sub SunRaySubRoutine(x,y)
n = x * Sheets("ABC").Range("A1").Value + 1
ReDim Mother_Array(18, n) as Variant, BabyOne_Array(n), BabyTwo_Array(n) as Double
ReDim BabyThree_Array(n), BabyFour_Array(n) as Double
'do stuff
For i = 0 to n
BabyOne_Array(i) = Mother_Array(0,i)
BabyTwo_Array(i) = Mother_Array(2,i)
BabyThree_Array(i) = Mother_Array(4,i)
BabyFour_Array(i) = Mother_Array(6,i)
Next
End Sub
I have tried to declare all arrays as the Variant type, but to no avail. I have tried to give BabyFour_Array() a different name, but to no avail.
What's really strange is that even if I comment out the part which makes the BabyFour_Array(), the array still has zero values for each element.
What's also a bit strange is that the first baby array never craps out (although, the 2nd one crapped out once (one time out of maybe 30).
BANDAID: As a temporary fix, I just publicly declared a fifth dummy array (which doesn't get filled or Re-Dimensioned). This fifth array has no actual use besides tricking the system out of having the "Compile Error: Expected Array".
Does anyone know what's causing this "Compile Error: Expected Array" problem with Excel VBA?
Thanks,
Elias
In your global declarations you are only declaring the last baby array as Double. You're declaring the first three as arrays of Variants. But in the subroutine you are Redimming babies one and three as Variants, and two and four as Doubles.
See this Chip Pearson page and scroll down to "Pay Attention To Variables Declared With One Dim Statement."
In VBA when you declare something like:
Dim x, y, z as Long
only z is a Long, the rest are Variants. The correct form is:
Dim x as Long, Y as Long, Z as Long (or Double arrays in your case.)
You can see how this would cause the behavior you describe, i.e., the last one errors, but the others don't.