I have a click event on a form in Access 2010 that looks like so:
Private Sub SaveRecord_Click()
checkDataIntegrity(Me)
End Sub
Where checkDataIntegrity is defined as follows:
Function checkDataIntegrity(ByVal fForm As form) As Boolean
This works fine and dandy. However, I have another click event:
Private Sub LFS_Flashed_Successfully_Fail_Click()
preventSimultaneousPassAndFail (Me)
End Sub
Where preventSimultaneousPassAndFail is defined as follows:
Function preventSimultaneousPassAndFail(ByVal fForm As form) As Boolean
When I invoke this click event I get the following error:
Run-time error '13':
Type mismatch
What am I doing wrong here? Both event calls are invoked in the same form and call functions in the same module.
You don't seem to be doing anything with the functions' return values, so don't enclose the arguments in parentheses.
'preventSimultaneousPassAndFail (Me)
preventSimultaneousPassAndFail Me
That is standard VBA practice. Unfortunately, I can't explain why it triggered an error in one case but not the other. So this issue may not contribute to the problem, but I still suggest you make that change to rule it out.
Although we don't know any details about those functions, I suggest you consider passing the form objects ByRef instead of ByVal.
The reason why you get the error is that in the case of
preventSimultaneousPassAndFail (Me)
the parenthesis expression tries to invoke the default member of the object. In case of an Access.Form this is the Name property being of type String. That's the reason for the type mismatch error.
In case of
preventSimultaneousPassAndFail Me
the reference to the form itself is passed to the method.
Related
I have a function that works fine when called within VBA regardless of what arguments I pass values to or do not pass values to.
The function also works when called from the control source of a text box on a continuous form so long as I pass values to all arguments.
The error occurs when changing the control source of the text box so that a value is not passed to the first optional argument. Specifically when trying to click out of either of those fields. So in other words it won't let me save the control source change as it thinks the syntax is wrong.The error occurs whether I change the control source using the property sheet or by typing within the text box.
I have tried specifying ByVal for the arguments and not using default values for the optional arguments but that did not work. I verified that the function is public and that there are no misspellings or data type mismatches. It definitely has something to do with the syntax when not passing a value to the first optional argument. (the two commas next to each other)
Control source that works:
=GetProfile(Nz([FieldName],0),"",Forms("FormName"))
Control source that causes error:
=GetProfile(Nz([FieldName],0),,Forms("FormName"))
The error is:
"The expression you entered contains invalid syntax. You may have entered a comma without a preceding value or identifier."
The function is listed below and it is within a module, not a class module. I simplified the guts of the function for brevity:
Public Function GetProfile(varPerson as Variant, Optional strLName as string = "", Optional frm as Access.Form = Nothing) as string
GetProfile = "Test"
End Function
I am pretty sure this is a bug. Can someone confirm or point out my mistake? If it is a bug, is there a work around?
I'm trying to call a Sub from another Form, but I get:
Error 2465: Application defined error or object defined error
I already know that to call a procedure from another form I can use the syntax:
Form(Name).Procedure
But, in this case I want to refer to this form from a variable (Type Form).
Code from form Parametro_Cadastro:
Dim formCaller As Form
Set formCaller = Application.Forms("Cadastro_Aluno").Form
If (Not formCaller Is Nothing) Then
'
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado
Set formCaller = Nothing
End If
Code from form Cadastro_Aluno:
Sub SetDadosParametroCadastro(ByVal KeyValue As String, ByVal DataValue As String)
'
'...
End Sub
The code in Parametro_Cadastro gives Error 2465 on the line:
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado`
...even before the Sub SetDadosParametroCadastroin the form Cadastro_Alunos to be called.
In the Immediate Window, the variable formCaller is already signed as Form\Form_Cadastro_Alunos as expected.
What can I do in this case?
EDIT
The only way it worked was to assign the variable formCaller to Access.Forms(formName) and not through Application.Forms(formName) or simply Forms(formName), so the code now is like below:
Code from form Parametro_Cadastro:
Dim formCaller As Form
Set formCaller = Access.Forms("Cadastro_Aluno")
If (Not formCaller Is Nothing) Then
'
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado
Set formCaller = Nothing
End If
When I check the variable formCaller in the Imediate Window, I also get (as before) Forms\Form_Cadastro_Alunos.
The interesting thing is this only change make the code work as expected. Maybe the Forms member to be called is from Access Object instead of Applications?
Although you can call a procedure from a form, it's generally avoided and is considered bad practice.
Any Sub or Function that need to be shared should be placed in a separate, shared module.
Some excellent advice from Stewart # Bytes.com:
Form code modules are essentially 'private' in scope. Functions and subroutines defined in them are normally unavailable outside of the form concerned - although it is actually possible to call the functions and subroutines defined as Public in scope within a form code module from outside of that module.
Use of the keyword Public is not just a matter of suddenly adding one as a change of style. It reflects that you wish the subroutine, function or variable to be available outside of the scope of the code module concerned...
The code modules which can be created or opened from the Modules tab are the usual locations of public subroutines and functions. Named modules provide a means of grouping tasks by logical function, and if used consistently can be an aid to maintainability.
I use many several named modules in my applications, separating custom linked table maintenance from username parsing, e-mail handling and so on. I also include a "General" module which contains general bespoke functions that I find useful and re-use across multiple databases (for example, to return the current financial year or the current quarter within it).
All subroutines and functions defined using the Public keyword in the publicly-accessible code modules are available outside of the module concerned, whereas those defined as Private cannot be used outside of the scope of the code module in which they reside.
"If you must..."
If, for some reason, you must call a public sub from a form, the syntax is:
Call Forms!FormName.SubName
Note that the sub being called must have the Public keyword specified.
More Information:
MSDN : Understanding Scope and Visibility
Bytes.com : How and where to use Private or Public sub or function?
I am attempting to pass a form/subform name to a function without success. The function steps thru each .Control on the subform and performs a simple set of look-ups & actions. My code works as expected with the Form/Subform name hard coded; I am looking for a more generic approach.
Getting a type mismatch error on the function call, with and without quotes.
Example:
'Function Call
call AuditChanges("forms![someForm]![someSubForm]")
'Audit Function
Sub AuditChanges(thisForm as form)
Dim ctl As Control
Dim strTest as string
For each ctl in thisForm.controls
strTest = ctl.Value
'do some stuff
Next ctl
end sub
Any suggestions for proper syntax to pass the form/subform info?
Thanks!
Your sub call is all kinds of weird:
The likely cause of your error is the quotes. You're currently passing a string to your function containing "forms![someForm]![someSubForm]"
Furthermore, you shouldn't use parentheses when you're not receiving a return value (so never when calling a sub).
Also, the Call keyword has been deprecated a long time ago.
And you likely want to pass the form object, and not the subform control object
Try calling your sub like this:
AuditChanges forms![someForm]![someSubForm].Form
(Never had this many comments on one line of code before)
I am curious to understand why the following throws and compile error stating it is expecting a function or variable
Dim frm as Form
set frm = DoCmd.OpenForm(FormName:=mstr_FORM_NAME, View:=acDesign, WindowMode:=acHidden)
but I can do this
DoCmd.OpenForm FormName:=mstr_FORM_NAME, View:=acDesign, WindowMode:=acHidden
set frm=Forms(mstr_FORM_NAME)
I have no issue with doing what works, I just want to understand what is going on with the former statement.
Thank you,
Fred
DoCmd.OpenForm is a method which doesn't return a value. In the second code snippet you are accessing the Forms Collection, which contains the form, after it has been opened by DoCmd.OpenForm. When you call a method, you must not specify braces.
The OpenForm method (doc) is not returning anything, just opening the form (not returning it).
So, you're trying to cast Nothing into a variable defined As Form.
Instead, frm (having the Set frm = statement) is expecting to "become something", it is expecting a function or variable - a value, to be clear).
I have a simple Function Test() in Module1 and a Sub SubName() in Module2. I'm trying to call SubName() from Function Test(). When I type:
Call Module2.SubName
and exit the raw, I'm getting an error:
Compile Error: Expected: identifier
When I just type Module2 and put Stop, it offers me the name of the SubName in Module2. So it sees it, but looks like is missing something in syntax. I can't figure out what.
Some related links :
MSDN-Calling Sub and Function Procedures
SO-Calling a Sub in VBA
SO-What does the Call keyword do in VB6?
Solution to your question :
Either use Call SubName or just SubName.
Testing:
After some testing, I've been able to break the code. The error is NOT the same you get, but maybe this will bring us closer to solution.
Picture from VBA:
The solution is simple: just use the statement
SubName
and it'll be called.
Few clarifying remarks:
No need to use the Call statement. If you do however, you need to use Call SubName()
If you call any sub with parameters, use SubName Param1 - or call Call SubName(Param1). Don't use Subname(Param1)- if param1 is an object, this will pass it's default property to the sub, not the object (e.g. Subname (Range("A1")) will pass the value of the cell to the sub - but not the Range object - Subname Range("A1") will pass the Range object.
You can also use Module2.SubName - however this is only required, if you have multiple SubName sub in different modules