I'm writing a function that requires input and my data validation looks very awkward. If InputFld isn't "A","B", or "C", then it's an error:
If InputFld <>"A" and InputFld<>"B" and InputFld<>"C" then goto ErrorHandler
This just looks ugly to me. Is there a more elegant solution? I'd like to just write something like:
If InputFld not in ("A","B","C") then goto ErrorHandler
See? Much easier to read and maintain this way. But I don't know how to do it.
How about:
If Instr("ABC",InputFld)=0 Then
At least two ways to do that:
public function IsInSet(byval value as variant, paramarray theset() as variant) as boolean
dim i as long
for i=lbound(theset) to ubound(theset)
if value = theset(i) then
isinset = true
exit function
end if
next
end function
Usage: If not IsInSet(val, "A", "B", "C") then ...
public function IsInSet(byval value as variant, theset as variant) as boolean
dim i as long
for i=lbound(theset) to ubound(theset)
if value = theset(i) then
isinset = true
exit function
end if
next
end function
Usage: If not IsInSet(val, array("A", "B", "C")) then ...
Eval() should allow you to do something similar. This expression returns -1 (True):
Debug.Print Eval("""g"" Not In (""a"",""b"",""c"")")
I wouldn't call that elegant, though.
Consider using the Like operator. This expression returns True:
Debug.Print Not "g" Like "[abc]"
Related
Sorry if this has been posted elsewhere as I could not find the answer.
I'm trying to search for any number followed by the letter "m" using the InStr function. I've got the following code which I thought should have worked however it does not recognise "1m" 1.1m" or any variation and returns 0.
Public Function instrstring(strTest As String) As Long
Dim i As Long
PosOfFirstDigit = 0
For i = 1 To Len(strTest)
If Mid$(strTest, i, 1) Like "#" & "m" Then
PosOfFirstDigit = i
Exit For
End If
Next
End Function
I appreciate your help!
To return the position of the match something like this:
For
"a1.1m"
"testme 1m"
"testme 222"
Returns
2
8
not found
Sub Impeached()
Debug.Print StrOut("a1.1m")
Debug.Print StrOut("testme 1m")
Debug.Print StrOut("testme 222")
End Sub
code
Public Function StrOut(strIn As String) As String
Dim objRegex As Object
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Pattern = "(\d*\.)?\dm"
If .Test(strIn) Then
StrOut = InStr(strIn, .Execute(strIn)(0))
Else
StrOut = "not found"
End If
End With
End Function
As #Tim Williams has mentioned, it's best using regular expressions (Regex) for this if you're having floats as well as integers.
You'll need to setup the reference to Regex to use it. Add VBA reference to "Microsoft VBScript Regular Expressions 5.5"
The regex you'll need is
Dim RE As New RegExp
With RE
.Global = True
.Pattern = "\d*?\.\dm"
End With
If RE.Test(strTest) Then
Msgbox("Found!")
'Insert the function you want to perform here
End If
Is it true that you cannot declare a visual basic array of a size provided by a variable? This seems like a reasonable requirement for any scripting language, and so I expect I am doing something wrong.
In the following example...
Sub TestRoutine()
Dim tVar As Integer: tVar = 5
Dim tArr(tVar) As String
tArr(3) = "SUCCESS"
MsgBox tArr(3)
End Sub
... the execution fails with the message Compile error: Constant expression required
I use a dynamic array instead, but this seems like an ugly workaround. Is there something I am missing here?
That is right. The closest you can get is - as the compiler suggests - to use a constant:
Sub TestRoutine()
Const tVar As Integer = 5
Dim tArr(tVar) As String
tArr(3) = "SUCCESS"
MsgBox tArr(3)
End Sub
Another option which is handy, say, when using Split or Array, is to use a Variant:
Sub TestRoutine()
Dim vArr As Variant
vArr = Array("0", "1", "2", "Yet a SUCCESS")
MsgBox vArr(3)
End Sub
I'm trying to write a function in my Microsoft access application to return a blank string when a "-" or "null" is inputted, and when any other string is inputted it should return the original string.
This is what I have so far:
Public Function cleanOutput(inStr As String)
If inStr = "-" Or inStr = "null" Then
cleanOutput = ""
Else
cleanOutput = inStr
End If
End Function
However this is not working. I'm sure this is a very basic solution, however I have zero experience with VB programming, so I'm not sure what I'm doing wrong here. Any help is greatly appreciated!!
Not quite sure what "not working" means, but if "null" means a true Null, you can use:
Public Function cleanOutput(inStr As Variant) As String
If Nz(inStr, "-") <> "-" Then
cleanOutput = inStr
End If
End Function
I changed the variable name from inStr to something else and everything worked as expected!
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")
Please help.
=Does not work:
Function f()
f = 1
End Function
Private Sub Button1_Click()
k = Eval("f()")
End Sub
=Does not work:
Private Sub Button1_Click()
с=1
k = Eval("с")
End Sub
=Do work:
Function f()
f = 1
End Function
Private Sub Button1_Click()
k = f()
End Sub
=In help:
The following example assumes that you have a series of 50 functions defined as A1, A2, and so on. This example uses the Eval function to call each function in the series.
Sub CallSeries()
Dim intI As Integer
For intI = 1 To 50
Eval("A" & intI & "()")
Next intI
End Sub
How to make variant 1 work?
Thanks in advance.
++++++++++++++++++++++++++++
=UPDATE:
The number of error I get with "Does not work" sections is 2425. "Can not find the name of the function." (or "Can not find the name of the expression." in the second case). Sorry for my English.
=UPDATE:
When I try explicitly name the function in Eval:
k = Eval("[Forms]![Form1].f()")
I get error 31005 - "Access can not calculate expression because there is a reference to "f"". I start to be suspicious of Access prohibiting use of user-defined functions and variables in Eval. Though help states opposite.
=UPDATE:
Do work:
Function f()
f = 1
End Function
Private Sub Button1_Click()
k = Eval("val(""551" & "9" & "6"")")
End Sub
Very strange rules of double-quoting, as for me. But this does not solve my problem.
The Eval function cannot access functions that are in Form modules. Place the function in an ordinary Module.
There is one interesting fact. Eval() does not accept user variables as arguments, but accepts form controls data.