Access VBA: Passing Form/Subform name to a Function? - ms-access

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)

Related

DoCmd.DeleteObject acTable - The record ... specified on this form or report does not exist

Let me start by saying I am not at all familiar with Access or VBA. However, I am the IT guy and at some point someone created an MS Access database that does a thing and now I have to support it.
We have a database that upon opening deletes any old data and re-runs the external query that makes this application work. Occasionally whatever state the program exited out in that table already does not exist. This causes MS Access to hang on the delete line and I have to run the debugger, comment out the DoCmd.DeleteObject line, re run, and then un-comment the line to let the user continue with their day.
I want to add in some sort of conditional statement, but anything I've been able to google in terms of If...Then statements or 'TableExist' type functions always causes an error to be thrown that I haven't defined the function. My best guess is I'm nesting this incorrectly or I'm not calling some sort of external function correctly, but as I said my VBA knowledge is extremely limited.
This code executes on startup:
Public Function Startup() As Integer
DoCmd.Close acForm, "soLookup"
DoCmd.DeleteObject acTable, "sales_order"
DoCmd.RunSavedImportExport "Import-sales_order"
DoCmd.OpenForm "soLookup"
End Function
Its the
DoCmd.DeleteObject acTable, "sales_order"
Line that causes things to fail.
I've attempted to restructure this several times based on several examples I had found, but I'll only bother with one below
Public Function Startup() As Integer
DoCmd.Close acForm, "soLookup"
If TableExists("sales_orders") Then
DoCmd.DeleteObject acTable, "sales_orders"
Else
'Do nothing
End If
DoCmd.RunSavedImportExport "Import-sales_order"
DoCmd.OpenForm "soLookup"
End Function
Nothing I seem to try seems to give me any result other than an error of some sort. All I want to do is add a conditional statement to this 'Startup' bit that checks if the "sales_order" table even if exists, and if it doesn't, then to just move on to the next comment and forget the DoCmd.DeleteObject. How can I achieve this functionality?! Thanks!
The TableExists function is not a standard function in Access. You need to define it yourself.
There are two main ways to define such a function, by trying and error trapping, or by iterating through all tables and checking names.
Way 1 (error trapping):
Public Function TableExists(TableName As String) As Boolean
On Error Resume Next
TableExists = CurrentDb.TableDefs(TableName).Name = TableName
End Function
Way 2 (iterating collection):
Public Function TableExists(TableName As String) As Boolean
Dim td As DAO.TableDef
For Each td In CurrentDb.TableDefs
If td.Name = TableName Then
TableExists = True
Exit Function
End If
Next
End Function
Define either of these functions in a public module, and your last approach should work
I will instead modify the query to import the source data into a new table (sales_orders), which will overwrite existing data when the query runs and so I don't have to delete the table and have additional check for TableExists

Receiving Invalid Qualifier error when attempting to access a form and subform using variable names?

I am trying perform a RecordsetClone but I keep getting a
Invalid Qualifier
compile error.
Currently I have a form, and within it I have a subform that contains a Datasheet. I created a function to pass in the name of the form as well as name of the subform:
Public Sub testModel(nameOfForm As String, nameOfSubform As String)
Dim myForm As Access.Form
Dim mySubForm As Access.SubForm
If formIsOpen(nameOfForm) = False Then
DoCmd.OpenForm nameOfForm, acNormal
End If
Set myForm = Forms(nameOfForm)
Set mySubForm = myForm.Controls(nameOfSubform )
With Forms!myForm.name.mySubForm.name.Form.RecordsetClone
...
End With
End Sub
The reason for using a variable for the form and subform is because different forms and subforms will be using this function.
The error is definitely involved with the syntax Forms!myForm.name.mySubForm .name.Form.RecordsetClone, and I'm pretty confident it is incorrect.
I've also tried:
Forms!myForm.name.mySubForm.Form.RecordsetClone
If I replaced it, directly using the name of the form and subform name, there is no issue, i.e.:
Forms!frmParentForm.frmChildSubForm.Form.RecordsetClone
I have printed out the name of myForm and mySubForm via its .name property and it appears to display the correct name for each.
Can someone point me in the right direction on how exactly I can use variable names in place of the actual names of my form and subform? What should the correct syntax be?
Thanks!
Remove those .name things. They're not supposed to be there:
With Forms!myForm.mySubForm.Form.RecordsetClone
...
End With
If you're going to use that declared subform variable, it's even more simple:
With mySubForm.Form.RecordsetClone
...
End With

VBA - Why do I get a compile error expected function or variable

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).

Calling sub from another module

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

pass TextBox value to variable within SUB

I have a form (named DateForm) that contains a textbox (named txt_AsOfDate), which displays a date value.
I have a separate SUB which has the following code:
Sub Test()
Dim AsOfDate As String
AsOfDate = txt_AsOfDate.Text
MsgBox (AsOfDate)
End Sub
When running it, I get the following error:
Run-time error '424': Object required
What is going on? I tried loading the DateForm at the beginning of the SUB, and also tried assigning the value by further defining the object schema like below, but no luck. What am I doing wrong?
AsOfDate = DateForm.txt_AsOfDate.Value
Try replacing txt_AsOfDate.Text with Form_DateForm.txt_AsOfDate.Text. Referring to a control directly in code by its name only works in the form, whereas I'm guessing this code is in a separate module.
In order to catch things like this, add Option Explicit to the top of your code modules. This forces the compiler to notify you if there is a variable being used which wasn't first declared with Dim.