Passing parameters in VBA events - ms-access

I am relatively new to Access though I do have some experience in VB, my question is probably very simple though I don't seem to know the terminology to search in order to find an answer I can use.
I am in the process of creating an "OnChange" event for a tab control I am using, I would like to pass an undetermined amount of integers to the function. IE:
=myFunction(1,4,6) OR =myFunction(ArrayList[1,2,4])
I would either create an overloaded function to work with these numbers, or if possible I would like to pass them as an array of integers. Though for the life of me I cannot figure out exactly how to do this. The reason I have taken this path is to make my function as universal as possible, basically just having to change what numbers I send to the function to change its behaviour.
This is some rough coding of what I am try to do, though I have no idea how to pass anything besides something like =myFunction([Form])
Public Function Refresh(tabsToCheck As ArrayList)
For Each o In tabsToCheck
If Me.DevForm.Value = o Then
RefreshAllForms
End If
Next o
End Function
Public Function RefreshAllForms()
Dim f As Form
For Each f In Access.Forms
f.Refresh
Next
End Function
Update
I thought I would update with my finalized code in case anyone needs this in the future thanks for your help!
Public Function RefreshControlTab(ctrl As Access.Control, ParamArray TabsToRefresh())
Dim i As Long
Dim lngUBound As Long
If UBound(TabsToRefresh) >= 0 Then
lngUBound = UBound(TabsToRefresh)
For i = 0 To lngUBound
If ctrl.Value = (TabsToRefresh(i) - 1) Then
RefreshAllForms
End If
Next
End If
End Function
Public Function RefreshAllForms()
Dim f As Form
For Each f In Access.Forms
f.Refresh
Next
End Function
So one change you would say '=RefreshControlTab([DevForm],3,4)' and when the 3rd or 4th tab is selected a refresh will be performed.

"I would like to pass some an undetermined amount of integers to the function."
That sounds like a ParamArray to me. See the simple function below. It will return the sum of a set of numbers.
Public Function AddThem(ParamArray MyNumbers()) As Long
Dim i As Long
Dim lngReturn As Long
Dim lngUBound As Long
If UBound(MyNumbers) >= 0 Then
lngUBound = UBound(MyNumbers)
For i = 0 To lngUBound
lngReturn = lngReturn + MyNumbers(i)
Next
End If
AddThem = lngReturn
End Function
Note the ParamArray is an array of Variant values. So within the function you would need to verify the values are numbers to avoid trouble ... one example of trouble would be a "type mismatch" error when calling the function with string values: AddThem("a", "b")

Related

VBA - Compile error: Expected: If or Select or Sub or Function or Property or Type or With or Enum or end of statement

Forgive me for the noob question. Working in VBA is not my normal job.
I get the error listed in the title. The offending code is this:
While index <= 10
index = index + 1
End While
I can't imagine what could be wrong with that, seeing that it is copied directly from the documentation: https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/while-end-while-statement
Seeing that the code can't be the problem, I'm supposing the problem must be something in the context, but before I put this block in, it was working fine.
This block of code is part of a simple, private subroutine which declares a variable, assign a value to it, and then writes it into a file, like so:
Private Sub btnExpAll_Click()
Dim sFldr As String
sFldr = BrowseFolder("Where do you want to export the files?")
If sFldr = "" Then Exit Sub
DoCmd.Hourglass True
Dim sListLocal As String
Dim index As Integer
Dim strInputFileNameLocal As String
sListLocal = ""
index = 0
While index <= 10
index = index + 1
End While
strInputFileNameLocal = sFldr & "\list-local.html"
Open strInputFileNameLocal For Output As #1
Print #1, sListLocal
Close #1
DoCmd.Hourglass False
End Sub
The idea is to add more text to the file as we go through the while loop based on certain conditions - but since I can't even get the while loop to compile...
Link referenced in question is VB.net example, which has similarities to VBA and in some simple examples, easily confused. Replace End While with Wend or use Do … Loop structure.
Review: https://excelmacromastery.com/vba-while-loop/

VBA - How Can I Get Randomize String Array To Work?

Overview: I am pasting many words on separate lines into text box: txtWordRandomizer. Then, move each line into the string array. I need to shuffle/randomize the array, but can't seem to get it to work.
I got the bottom Sub, ShuffleArray(), here: http://www.cpearson.com/excel/ShuffleArray.aspx
...and it seems to be what everyone references when talking about shuffling/randomizing an array.
I get Error: Type Mismatch: array or user-defined type expected on calling ShuffleArrayInPlace(), but thought this was for randomizing a string array. Do I somehow need to translate the string array into a variant array?
Or, any other suggestion on how I can get this to work?
Private Sub btnRandomize_Click()
Dim strRandoms() As String
strRandoms() = Split(Me.txtWordRandomizer.Value, vbCrLf)
strRandoms() = ShuffleArray(strRandoms())
End Sub
Function ShuffleArray(InArray() As Variant) As Variant()
' This function returns the values of InArray in random order. The original
' InArray is not modified.
Dim N As Long
Dim Temp As Variant
Dim J As Long
Dim Arr() As Variant
Randomize
L = UBound(InArray) - LBound(InArray) + 1
ReDim Arr(LBound(InArray) To UBound(InArray))
For N = LBound(InArray) To UBound(InArray)
Arr(N) = InArray(N)
Next N
For N = LBound(InArray) To UBound(InArray)
J = CLng(((UBound(InArray) - N) * Rnd) + N)
Temp = InArray(N)
InArray(N) = InArray(J)
InArray(J) = Temp
Next N
ShuffleArray = Arr
End Function
Based on some quick testing, the ShuffleArray function in the posted link doesn't actually return a randomized array. Since you're keeping your array in the strRandoms variable, you can use the in-place function anyways (the in-place function will also be more efficient, since it doesn't have to create and populate an entirely new array when called).
When calling the function and passing your array as an argument, don't include parentheses after your array. So do this:
ShuffleArrayInPlace a
' Or this:
Call ShuffleArrayInPlace(a)
However, in order to do this successfully, you have to slightly change the method signature of ShuffleArrayInPlace from this (as it is now):
Sub ShuffleArrayInPlace(InArray() As Variant)
to this:
Sub ShuffleArrayInPlace(InArray As Variant)
Note that the parentheses after the InArray are gone. Why do this?
Originally, with the parentheses, the function is expecting an array of Variant values. However, the split function returns an array of string values. By changing the method signature to remove the parentheses, you're basically saying you can pass anything to the function (a string array, a variant array, or even something that's not an array at all). Because of this, you could update ShuffleArrayInPlace to raise an error if the argument is not an array (using the IsArray function).
Speaking of refactoring: While the algorithm the ShuffleArrayInPlace uses to shuffle an array is clear, it's not necessarily the best one. I would review the Fisher-Yates shuffle, and try implementing it yourself in VBA as an exercise.
So, in summary...
When calling a function that takes an array as an argument, don't put parentheses after the array: `Call ShuffleArrayInPlace(strRandoms)
Use ShuffleArrayInPlace, not ShuffleArray.
Change the ShuffleArrayInPlace function so that InArray is a Variant, not Variant().
This works for me:
Private Sub btnRandomize_Click()
Dim strRandoms() As String
strRandoms = Split("A|B|C|D|E", "|")
strRandoms = ShuffleArray(strRandoms)
Debug.Print Join(strRandoms, ", ")
End Sub
Function ShuffleArray(InArray() As String) As String()
Dim N As Long, Temp As Variant
Dim J As Long, Arr() As String
Randomize
'make a copy of the array
ReDim Arr(LBound(InArray) To UBound(InArray))
For N = LBound(InArray) To UBound(InArray)
Arr(N) = InArray(N)
Next N
'shuffle the copy
For N = LBound(Arr) To UBound(Arr)
J = CLng(((UBound(Arr) - N) * Rnd) + N)
Temp = Arr(N)
Arr(N) = Arr(J)
Arr(J) = Temp
Next N
ShuffleArray = Arr 'return the shuffled copy
End Function

Issue writing visual basic program dealing with mathematical functions and IF logic

First time posting on this website; mainly because I'm running into a huge issue with a question on my visual basic class that we were assigned. The full question can be seen here.
Basically, I'm running into issues where I THINK I am correctly executing the Buckling Load function as instructed, but I don't know how to get each different True or False value into the lstOut box.
Public Class Form1
Private Sub btnCompute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCompute.Click
Dim area As Double
Dim length As Double
Dim width As Double
Dim load As Double
Dim buckling1 As String
Dim buckling2 As String
Dim buckling3 As String
length = CDbl(txtIn.Text)
load = CDbl(txtLbs.Text)
buckling1 = Test1(load, length, 2, area)
buckling2 = Test1(load, length, 4, area)
buckling3 = Test1(load, length, 6, area)
End Sub
Private Function Test1(ByVal load As Double, ByVal length As Double, ByVal width As Double, ByVal area As Double) As Boolean
If ((0.3 * 1700000 * (length * width)) / (length / width) ^ 2) > load Then
Return True
Else
Return False
End If
End Function
End Class
And that's only the first part...I'm really struggling with this question. I'm somewhat new to programming, and the concept of functions are pretty frightening. Does anyone have any tips or advice they could give me?
Note that I'm not asking for the whole question to be completed, I'm just trying to figure out how I'm going to put all of output from the Test1, Test2, and Test3 functions into the lstOut box. I hope I'm making at least some sense.
You can set the buckling variables to Boolean as Suggested by Mark Hall, or pass the words "True" or "False" instead as string so that your Buckling variables accept them
IE simply add Double Quote(s) to True (turning it to "True") and False (turning it to "False")

returning a two dimensional array from a function in vbscript

im having an issue with a program im working on.
what im trying to do is have a function accept input from a user and store that data in an array
for small testing purposes it is a 3 x 3 array
i have gotten the array within the function to work as tested by echoing out all values stored.
however when i attempt to return the array to the sub from which it is called i get mismatch errors, im not sure what i am doing wrong.
Sub SubroutineA()
Dim Array(2,2)
Array = GetInfo()
End Sub
Function GetInfo()
Dim FunctionArray(2,2)
{input all data into array}
GetInfo = FunctionArray()
End Function
Any Help i could get would be great as this is new to me.
Cheran Shunmugavel points to the right direction, but his explanation contains an ambiguety. To make it clear:
Sub SubroutineA()
Dim Arr ' <<<--- do not use parenthesis here and do not use
' the reserved keyword "Array"
Arr = GetInfo()
End Sub
Function GetInfo()
Dim FunctionArray(2,2)
' {input all data into array}
GetInfo = FunctionArray ' <<<--- do not use parenthesis here
End Function

Returning Multiple Values from a Custom Function

So, I've got a ValidateForm function that loops through a form to validate each control. I have a collection set up called ValData to capture different bits of info to be passed out of the function. This is working great.
However, I don't know how to access each item in ValData after the function returns. I can get one at a time like: ValidateForm().IsValid, but in order to get each item, I have to run the function again. I want to avoid this.
Is there a way to run the function once, but access the values of each item returned?
Depending upon your requirements (which are NOT clear in your question! ;-) ), you might consider using a Collection as the return from your function:
Private Function MyResultsFunction() As Collection
Dim output As Collection
Set output = New Collection
'Hydrate your collection with data by whatever means necessary:
With output
'Stupid example code:
.Add "Item1"
.Add "Item2"
.Add "Item3"
.Add "Item4"
End With
'Return a reference to the collection as the function output:
Set MyResultsFunction = output
End Function
As a simple, retarded test of the above:
Private Sub Form_Load()
'A variable to receive the results from your function:
Dim Results As Collection
'An iterator to loop through the results contained in the collection:
Dim CurrentItem As Variant
'For this example, a string to toss the results into to display in the
'MsgBox:
Dim output As String
'Use the local Collection defined above to access the reference returned by
'your function:
Set Results = MyResultsFunction
'Iterate through the collection and do something with the results
'per your project requirements:
For Each CurrentItem In Results
'This is stupid example code:
output = output & CurrentItem & vbCrLf
Next
'I am just displayng the results to show that it worked:
MsgBox output
'Clean up:
Set Results = Nothing
End Sub
Hope that heps!
Without seeing your code it's hard to say what exactly you are tyring to do, but here is one of several ways you can store results to query later.
Declare a public variable at the top of your module to represent the items from your ValData function. After you populate the array, you can access the items through a normal function.
You obviously could do more sophisticated things, especially if you use a collection object. You could even store a counter and create a GetNext() function. I hope this gives you a heads start.
Public Results(1 To 2) As String
Sub CreateTestArray()
Results(1) = "Foo"
Results(2) = "Bar"
End Sub
Function GetResult(ByVal i As Long) As String
If i <= UBound(Results) Then
GetResult = Results(i)
End If
End Function
Sub ProofOfConcept()
MsgBox GetResult(2) ' will show "Bar"
End Sub