How to close (unload) a form - ms-access

I have a form that has some buttons, and when user click on a button, the form should be closed (unloaded). I used the following methods, but all generate error:
docmd.close me
unload me
What is the best way to close or unload a form in VBA (from code inside the form)

DoCmd.Close expects ObjectType as its first argument, followed by ObjectName which is a variant string as the object name.
So in the click event of a command button which is intended to close the current form, I use this ...
DoCmd.Close acForm, Me.Name

Related

When click Cancel button on form, do not run On Exit code on a field

On my form, the first field has to be entered, so I have an On Exit command. Since it also checks to see if the value exists in my table, I want it to check right away - is it blank (thus require data to be put into field) OR does it already exist. My question has to do with the first part - is it blank.
On this form, I also have a Cancel button. When the user click Cancel, I want it to close the form without saving any of the data.
Problem - If the user doesn't enter anything in the first field and clicks Cancel, it's running the On Exit code requiring data to be entered into the first field - which they don't have to because they are cancelling. I'm getting a Run-time error '2585'.
Is there anyway to have the Cancel code stop the On Exit code from running? Any other ideas?
Here is my code for Cancel:
Private Sub CancelFormButton_Click()
Me.Undo
DoCmd.OpenForm "fmuMainMenu"
DoCmd.Close acForm, "frmVetNewMainForm"
End Sub
Here is part of my On Exit code for the field:
If IsNull(Me.txtSSN) Then
strMsg = "Social Security Number Must Not Be Left Blank!" & vbCrLf
strMsg = strMsg & "Do you want to add new veteran's record?" & vbCrLf
If MsgBox(strMsg, vbQuestion + vbYesNo, "Go to Record?") = vbYes Then
Me.txtSSN.SetFocus
Exit Sub
Else
Me.Undo
DoCmd.OpenForm "fmuMainMenu"
DoCmd.Close acForm, "frmVetNewMainForm"
End If
Else
'RUNS THE REST OF CODE
End if
OnExit events occur everytime you leave the textbox, even a simple tab or click to go to another combo box or select some text will trigger it.
You may want to try the code in the AfterUpdates.
and try a ,nosave after the close form command...
In addition, any checks to ensure a field is filled/has data is usually encouraged to be performed in the Form_BeforeUpdate section... Or so I have been advised

How to close a spawned VBA Access user form via a close button w/o using DoCmd

I have a main form named Calling. It has a button named Travel. That Travel button does:
Private Sub btnTravel_Click()
On Error GoTo btnTravel_Click_Err
DoCmd.OpenForm "Travel", acNormal, "", "", acFormEdit
'If you can find a cleaner way to open a form I will be thankful.
btnTravel_Click_Exit:
Exit Sub
btnTravel_Click_Err:
MsgBox Error$
Resume btnTravel_Click_Exit
End Sub
The Travel info form performs correctly. That Travel form has a Close button with the code:
Private Sub bntClose_Click()
Unload Me
End Sub
When pressed, the Close code generates "Run-time error '361': Can't load or unload this object.
Your help is much appreciated.
You do not need the commas with the empty strings, nor do you need the acFormEdit as when you open the form you will be able to edit and add new records anyway.
If you leave this argument blank the form will open in the data mode set by the forms AllowEdits, AllowDeletions, AllowAdditions, and DataEntry permissions (in the form properties).
DoCmd.OpenForm "Travel", acNormal
As for the next sub routine, I would use docmd.close instead of unload.
Private Sub bntClose_Click()
Me.Undo
DoCmd.Close acForm, "Travel", acSaveNo
End Sub
The me.undo is optional, if you don't want to save, and if you want to save the form change the acSaveNo to acSaveYes.
EDIT:
I have just re-read your question and noticed in the title you want to do this without docmd.
I have had a think about this and docmd is the standard way of closing forms in access using VBA. I am not sure if you have inherited the unload from using VB, but I would stick to docmd.close when using access.
"Unolad me" just doesn't work in Access Form objects.
Access wants you to use DoCmd.Open/DoCmd.Close but you are clever than that and can use Access Form Object as an object. Access names the Form Classes prefixed the name you give them with "Form_". You create a Form named "YourForm", Access create the Class "Form_YourForm". Use this class as a real object:
'Declare a typed variable
Dim f As Form_YourForm
'Create the object
Set f = New Form_YourForm 'This triggers the Open event
'Use the object
f.SetFocus
f.Resize
'... And eventually, dispose the object
Set f = Nothing
'Remember <<Unload f>> won't work, neither you can use DoCmd.Close
Also, you can use Form_YourForm directly as an object variable because VBA Access just create "implicitly" this object out of the class Form_YourForm when you first use it or when you use DoCmd.Open. (Yes, it's a little bit confusing, but Access was create for users that didn't have necessarily programmer skills).
However, you'll get a different instance of the Form_YourForm Class each time you use a variable object typed as any of the Form Class that exist in your project. This means you can open as many instances of a form as you want ...or while it fits your computer's memory. You can't acomplish it using DoCmd.Open.
The main "disadvantages" are that you have to handle the form object from another module. You can still use the "Forms" collection but since you don't know the given key you can't reach your form instance easily. Also, you can't close the form from its own code, but only disposing the typed variable (Set f=nothing).

Programmatic changes to form won't save

Does anyone have an idea what could prevent either of these commands from actually saving a form? Is there a setting I'm missing that could make the form "read-only"? I'm toggling the control.enabled property on the form on load, but I can't seen to make it stick once I've closed the form.
DoCmd.Close acForm, Me.Name, acSaveYes
DoCmd.Save acForm, Me.Name
Edit:
Some psuedo code to clarify.
This function runs on form load to enable/disable certain controls and works 100% as expected.
Private Sub Form_Load()
If IsNull(TempVars.Item(Me.Name)) Then
TempVars.Add Me.Name,1
If somecondition = true then
Me.Controls.Item("somecontrol").enabled = True
Else
Me.Controls.Item("somecontrol").enabled = False
End If
End If
End Sub
This click event closes the form and opens another form. The problem is, the control.enabled settings I set on form load do not save.
Private Sub button_OnClick()
DoCmd.OpenForm "someotherform", acnormal
DoCmd.Close acForm, Me.Name, acSaveYes
End Sub
The next time I open the first form, the control properties will not be set, and I need to set the conrol.enabled property again.
I've not been able to find any documentation, but it appears that you can not save design changes that are made in Normal mode. I ended up declaring a global collection type variable. I stored concatenated strings in this collection variable of the convention "Form.Name & Control.Name". If the form had never been opened, I ran the long check on which controls should be enabled, and stored them in this collection global. If the form had been opened at least once, I looped through the controls on the form checking to see if they were in my global collection of "authorized" controls. It feels really hackish, but it works pretty well.
The code you have (Close, then Save) fails on my testing because the Me.Name is empty after executing the Close. Although I don't know what other code you may have, I was able to get the Form to close once I switched the order.
I suggest you place the code in the 'Open' event as follows:
Private Sub Form_Open(Cancel As Integer)
DoCmd.Save acForm, Me.Name
DoCmd.Close acForm, Me.Name, acSaveYes
End Sub
Do you want to change the enabled property on a condition? If you just need that control disabled IF the record ... then you'll want to move the enabling the form's Current event, which fires at every record navigation. Load and Open are too early and don't repeat at navigation.
Private Sub Form_Current()
If Me!X = True Then
Me.Controls("somecontrol").Enabled = False
Else
Me.Controls("somecontrol").Enabled = True
End If
End Sub

Passing Form OpenArgs errors as NULL?

I am trying to open a form as a dialog and also pass a string in the OpenArgs property. No matter what I try, I get an Invalid use of null error.
The form is not open. It's not open in design mode either. Can anyone shed some light on this for me?
Here's the calling line:
DoCmd.OpenForm strTmpForm, acNormal, , , , acDialog, "Hi"
Here's the Form Open Sub on the target form
Private Sub Form_Open(Cancel As Integer)
MsgBox Me.OpenArgs
End Sub
Are you sure the form isn't open and hidden? It seems likely, since the usual dialog pattern usually involves hiding the dialog form to allow control to resume in the calling method.
To be certain:
If SysCmd(acSysCmdGetObjectState, acForm, strTmpForm) <> 0 Then
DoCmd.Close acForm, strTmpForm
End If
If that's not the problem then I'd ask if you can post the entire calling method rather than the calling line.

Microsoft Access 2000 Switch Views at Runtime

I'm creating a form programatically that has a ComboBox that is populated with a list of options. On selecting an option, I'd like the form to be populated with various controls.
At the moment I'm achieving it by:
FormName = Screen.ActiveForm.Name
DoCmd.Close acForm, FormName, acSaveYes
DoCmd.OpenForm FormName, acDesign
' Do Work to create controls
DoCmd.Close acForm, FormName, acSaveYes
DoCmd.OpenForm FormName, acNormal
The problem is, I'm going to have many temporary forms saved in my database. So as I see it there are two options for me,
Switch to design view without having to save the form
Be able to delete the form when I'm done with it
I've tried putting
DoCmd.DeleteObject acForm, FormName
in the OnClose, and OnUnload triggers, but it results in a "You can't delete the object 'Form1' while it is open" error
Any suggestions?
Do your options result in a limited number of controls on the form? In other words, would it be possible to have all the controls you need created ahead of time, just not Visible? Then all you would need to do is show and position what is needed without having to re-create everything from scratch.