I am currently debugging a DB application originally written in VBA 2005 that doesn't work with VBA 2010 and above versions. One of the (many) problems is that it uses the function IsNothing to test if an object variable has an object attached to it. This function seems to have been deprecated in 2010 and 2013. Is there an equivalent to this function in VBA 2013?
As others have indicated, IsNothing has never been a VBA function and was likely written as syntactic sugar for Is Nothing.
VB has an IsNothing function that serves the same purpose. In my experience, defining VBA functions that mirror familiar VB functions is common.
Here is a VBA IsNothing implementation from Tek-Tips that should be what you need - either to make the IsNothing calls work as-is...or provide a basis to inline them with equivalent code and strip the syntactic sugar:
'**********************************************************
'* Function: Returns true if argument evaluates to nothing
'* 1. IsNothing(Nothing) -> True
'* 2. IsNothing(NonObjectVariableOrLiteral) -> False
'* 3. IsNothing(ObjectVariable) -> True if instantiated,
'* otherwise False
'**********************************************************
Public Function IsNothing(pvarToTest As Variant) As Boolean
On Error Resume Next
IsNothing = (pvarToTest Is Nothing)
Err.Clear
On Error GoTo 0
End Function 'IsNothing
In fairness, note that this is essentially what #HansUp suggested already, just sourced elsewhere - and prefaced by a best-guess how the code you're debugging likely got the way it is.
Access VBA does not include an IsNothing function. If you had one in the past, it was a custom function.
If you can't track down the old version, you could create a new one.
Public Function IsNothing(ByRef pObject As Variant) As Boolean
IsNothing = (pObject Is Nothing)
End Function
How about
Dim x as Object
If x is Nothing then
IsNothing itself has never been a VBA function...
If obj Is Nothing Then...
may work for you, but may not yield the same results as the IsNothing function you are expecting. You may need to code more specific checks depending on what you want to determine.
Related
MS Access (2007 - 2016) in Office 365
I'm trying/failing to capture a value passed into Access from the command line using the Command() function in a Macro. THis is the macro that I created with the wizard...
If Command()="Update_Burndown_Metrics" Then
RunSQL
SQL Statement insert .... blah, blah
End If
No error when I save the macro, but when I run...
The expression you entered has a function name that Microsoft Access can't find
If I replace the...
If Command()="Update_Burndown_Metrics"
with
If 1=1
It runs fine. IOW, it's not the SQL. It's the "Command() function that it can't find.
I got the idea to use Command() from Opening Microsoft Access with parameters . Doesn't seem to work for me. But that coding approach is also confirmed here... http://www.utteraccess.com/wiki/Command-Line_Switches . So I think it's something else.
Eventually, I would like to pass the Update_Burndown_Metrics arg using /cmd on the command line.
Why can't it find Command() as a valid function ? Is it a scoping thing? Do I have to give Command() context somehow, maybe with some sort of prefix ?
I can't seem to reproduce the issue that you are describing, though, I am using an earlier version of MS Access, and so there may be some differences in the behaviour of this function.
The Command function should be globally accessible, even outside of VBA (it can be referenced by the ControlSource property of a text box, for example), and so this isn't an issue of scope.
I do observe from the Office 365 documentation, that the Command function is being invoked without the use of parentheses in the sample VBA Sub provided; therefore it may be worth you trying your code without including such parentheses, e.g.:
If Command = "Update_Burndown_Metrics" Then
MsgBox "Test succeeded."
Else
MsgBox "Test failed."
End If
The workaround I created is to create a function in vba that gets and returns the command...
Public Function GetCommand() As String
GetCommand = Command()
End Function
Then...
If GetCommand() = "Update_Burndown_Metrics" Then ...
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 am hoping someone can help me possibly debug the below code, as I am confused as to why it is happening.
I have a fairly simple VBScript that runs when a user logs onto a server/PC, that will create some signatures based on their active directory details. I have decided to move each section of the signature creation into a function, in order to make things a bit easier when creating new signatures.
Here is the function I am having issues with:
'Function to add job title and company
Function AddTitle
objSelection.Font.Name = "Calibri"
objSelection.Font.Bold = False
objSelection.Font.Italic = False
objSelection.Font.Size = "11"
objSelection.Font.Color = RGB(0,0,0)
If(strTitle) Then
objSelection.TypeText strTitle & Chr(11)
End If
objSelection.TypeText strCompany & Chr (11)
End Function
Now, when calling the function later on using:
'Add job title and company
AddTitle
It ignores the section within the If statement. I know that some variables need to be defined globally for them to work in a function, and strTitle is definitely defined at the beginning of my script.
Am I missing something totally obvious, as the section inside the if statement functions correctly if taken out of the if statement. Likewise, If I were to add the if statement to my script inline, and take it out of the function, it works correctly.
It is only when running from the Function.
Apparently you have a global On Error Resume Next somewhere in your script, which suppresses the "Type Mismatch" error that the line If(strTitle) Then normally would raise.
strTitle probably contains a string value, so you can't use it like a boolean value in a conditional. Change the line to something like this:
If Trim(strTitle) <> "" Then
and your code should work as expected.
My function:
Public Function openRpt(strReportName As String, form as ??, subform as ??)
On Error Resume Next
If (Forms![form]![subform].Form.lock = False) Then
DoCmd.RunCommand acCmdSaveRecord
End If
DoCmd.OpenReport strReportName, acViewPreview, "", _
"[num]=Forms![form]![subform].Form.[num]"
End Function
What it does is to save a record from subform if it isn't locked, and then launch a report. I want to switch from and subform with matching variables that will point at the right forms, and will be given as arguments.
What type of variable should I use?
What is the difference between using '!' and '.' to access properties? I understand that '!' is used to access a controller and '.' is used to access a table record, am I right?
for (1):
First, it may be tempting to call variables form and subform, but watch out for possible errors if names you use match or are close to reserved names.
Also, lock is not a valid property of a form or subform. If you are trying to test if a form has been changed, you would test .Dirty
This is how I would code your function:
Option Explicit
Public Function openRpt(strReportName As String, frm as String, sFrm as string)
If (Forms(frm).Form(sFrm).Form.Dirty = True) Then
DoCmd.RunCommand acCmdSaveRecord
End If
DoCmd.OpenReport strReportName, acViewPreview, "", _
"[num]=Forms(""" & frm & """).Forms(""" & sFrm & """).Form.[num]"
End Function
for (2):
from the Microsoft Blog
The dot gives you early binding and is resolved at compile time, the bang is resolved at runtime.
In the case of Forms, both controls and fields in the underlying query can be referenced via a dot since they are all in the type library for the form.
Also in the case of Forms, if you change the underlying query at runtime - dot references to the old query's fields will fail at runtime since update of the Form's type library cannot happen at runtime.
Because the dot is early bound, IntelliSense happens by default with the dot, not with the bang.
The dot (since it is early bound) is faster than the bang, but no one runs enough code that uses these items enough for the performance difference to actually matter.