How to close a form onclick in Access - ms-access

In Access 2007, I have a button that opens up a form in dialog mode (modal and popup set to true). I'm trying to save the data from that form and then close that form like so:
Private Sub Close_Click()
DoCmd.Close acForm, Me.Form, acSaveYes
End Sub
The purpose is to add a new record to a table. It accomplishes this, new data is added to the database based on the inputs. However, the form still stay visible. I have also tried this not using dialog mode, and the result has been the same.

You need to pass DoCmd.Close the form name, not the actual form object.
Private Sub Close_Click()
DoCmd.Close acForm, Me.Name, acSaveYes
End Sub
Also, while you're making changes, add Option Explicit add the top of your module. This would've made it way easier to spot the bug. Read here why having Option Explicit on is a good idea.

Related

Access one form open at a time

What can i do for this?
I want make MS access open only one form at a time. This means i have landing form as main form and when i open another form from button in main form, the main form should close and keep only the form i open. Likewise, when i close this form with close button, it should return back to home form.How can this be done? I have tried using Macro, but macro only allows to open main form but does not close main form when i open another form. Any help would be much appreciated.
You can open the form in dialog mode, which will allow the user to only work in that form until it is closed. Any other forms will remain on the screen behind it though, but the user can not bring them into focus until the dialog form is closed.
So on your main form, you have a button to open the form. In the property sheet, click the event tab. Select the ... and choose "Code Builder". Then edit the on click procedure to look something like:
Private Sub btnOpenMyForm_Click()
On Error GoTo Err_btnOpenMyForm_Click
Dim stDocName As String
Dim stLinkCriteria As String
stDocName = "frmMyForm"
DoCmd.OpenForm stDocName, acNormal, , , , acDialog
Exit_btnOpenMyForm_Click:
Exit Sub
Err_btnOpenMyForm_Click:
MsgBox Err.Description
Resume Exit_btnOpenMyForm_Click
End Sub
if you use the button wizard, it will create code very similar to this... you just need to add the acDialog constant to the parameter of the OpenForm method.

How can I set focus to a split form?

I am simply attempting to switch focus to a split form using a button located on another form. This can be broken down to code a simple as this.
Private Sub Command0_Click()
Forms.Form1.SetFocus
End Sub
This code will work so long as Form1 is in open "Single Form" view. The moment that you change Form1 to "Split Form" view, it no longer changes to Form1 and no error messages pop up.
How can I accomplish setting focus to a split form since obviously the normal way doesn't appear to work.
Edit: I would like to avoid the docmd.Runcommand OpenForm solution or the toggling visible false then true method of solving this problem.
just use docmd.openform frm_name,acNormal will open the form, if already opened will bring it to front (modal forms still stay on top)

Access 2010 VBA: Why can't I reopen a previously closed form?

I have a form "Form1" that opens another form "Form2" when button "Command1" in Form1 is clicked. As shown in the code below, control passes to Form2, and once the user does some stuff with Form2, Form2 either hides or closes itself and then returns control to Form1. Regardless of whether Form2 is hidden or closed, Form1 then does some stuff and closes Form2.
Private Sub Command1_Click()
DoCmd.OpenForm "Form2", , , , , acDialog
If CurrentProject.AllForms("Form2").IsLoaded Then
'Do stuff
End If
DoCmd.Close acDialog, "Form2"
End Sub
This seems to work fine first time that Form1 is opened. However, when I close and reopen Form1 and then repeat the above steps, Form2 does not appear and control passes directly to the If statement in the subroutine above. What's wrong? One clue is that CurrentProject.AllForms("Form2").IsLoaded seems to be permanently set to True after Form2 is opened the first time.
What's going on? How can I fix this? Thanks for any help.
Have you tried?:
DoCmd.Close acForm, "Form2"
The constant acDialog resolves to 3, while acForm resovles to 2. The code is actually telling Access to close a report named Form2. The form is never being unloaded properly, probably, because the wrong constant is going through.

Event not Firing in MS Access VBA

I have a form in MS Access which has an image. The image has an Click event which opens a modal form. The modal form has an OK and Cancel button. When you click the OK button, an event is supposed to fire which tells the main form which button was clicked. (This is to simulate the DialogResult functionality in C#). However, the code in the event handler never runs.
The modal form has the following in the general declarations:
Public Event OnDialogBoxClose(NewRecordID As Long, DialogResult As DialogResults)
and the following code where the OK button is clicked:
RaiseEvent OnDialogBoxClose(NewHardwareBaseItemID, dlgresBtnOKClicked)
The main form has the following in the general declarations:
Dim WithEvents RespondQuickAddClose As Form_qckfrmHardwareBaseItemCreate
and the following event handler:
Private Sub RespondQuickAddClose_OnDialogBoxClose(NewRecordID As Long, DialogResult As DialogResults)
MsgBox "Responding to closing of the dialog box" 'Never happens
Me.Requery
End Sub
Can someone explain why the event handler is never called?
Thanks!
Background:
The purpose of all this is to allow a modal dialog box to add an entry, then return the ID of the entry back to the main form to set the value of controls. For instance, imagine you are filling out an insurance form, and you need to select a brand of car this is not there. You click on an icon which pops up with the modal dialog box to allow you to add the car brand. Then when you click OK, it takes you back to the insurance form and selects the brand of car you just created.
This follows an example I found here:
http://database.itags.org/ms-access-database/80292/
You're making your life way too complicated by applying concepts from a different development environment to Access VBA. While VBA does support WithEvents/RaiseEvent, there's no reason to get that complicated here.
The usual way to work with dialogs in Access is that instead of closing them, you hide them. This allows the code after the form was open to run while leaving the values in the form available for use in that code.
Sample code in the OnOpen event of a report that opens a form for collecting values to filter the report:
Private Sub Report_Open(Cancel As Integer)
DoCmd.OpenForm "dlgDateRange", , , , , acDialog, "ThisYear"
If IsLoaded("dlgDateRange") Then
With Forms!dlgDateRange
If .Tag = "Cancel" Then
Cancel = True
Else
Me.Filter = "[InvoiceDate] Between #" & !txtStart & "# AND #" & !txtEnd & "#"
Me.FilterOn = True
Me!lblDateRange.Caption = StrConv(Trim(("from " + varZLStoNull(Format(!txtStart, "mm/dd/yyyy"))) _
& (" to " + varZLStoNull(Format(!txtEnd, "mm/dd/yyyy")))), vbProperCase)
End If
End With
DoCmd.Close acForm, "dlgDateRange"
End If
End Sub
The dialog form has two command buttons, CONTINUE>> and CANCEL. The CANCEL button sets the form's tag to "Cancel" and sets the form's .Visible property to False. The CONTINUE>> button does nothing but set the form's .Visible property to False. Clicking either of those buttons allows the code to continue on the line after the form is open with the acDialog switch.
My philosophy is to make the dialogs as stupid as possible. The calling code has to know what it's looking for in the forms (i.e., you need to know the names of the controls you're reading data out of), but that could be gotten around by adding customer properties to the form. But then you have to know the property names, so you've just moved the ball.
I have also implemented this kind of thing by wrapping the dailog form in a class module, and then the calling context simply initializes an instance of the class and then pulls the values out of it at the appropriate time. But that's actually more complicated that the approach above.
well I don't agree to
"While VBA does support WithEvents/RaiseEvent, there's no reason to
get that complicated here."
I have worked on various VB6 and VBA project. Recently I coded VBA in excel where I raised an event from winform. Few things to be considered when doing so.
If you are calling non-modal winform in VBA with
withevents/raiseevent. It should work normally as expected. No major
workaround is needed
If you are calling modal winform in VBA. Withevents/raiseevents may
not function as per requirement. A quick workaround is to transfer data using public variables declared in the module file.
You will need to use the workaround and I believe it will work absolutely fine.

MS Access Print Report using VBA

I have a very VBA intensive report. When I preview it everything is great but when I print it after previewing things go wacky. I have spent many hours narrowing down the possibilities and I have conclude with a certain level of confidence that it is a bug in MS Access.
Up to this point my method for printing reports was to open the report using docmd.openreport "report". I then use the docmd.printout command so that I can set the page range, collation etc.
Is there a way to print a report directly and still be able to set options like page rage, collate etc without doing a preview first?
Thanks,
Jeff
There is unfortunately no way to do it entirely neatly in code, but it can still be done since the introduction of the WindowMode parameter of the DoCmd.OpenReport method. This makes it possible to open a report in print preview mode and have it be hidden. You can then set properties of the report's Printer object (such as the output printer and orientation), and then use DoCmd.PrintOut to print a page range.
One thing to note:
You can't do this in the report's OnOpen event, because changing anything that has an effect on the layout will not give you correct results. For instance, if in the OnOpen event, you changed from Portrait to Landscape orientation, you won't have an accurate count of how many pages there are in the report, because the report hasn't been formated at the time the OnOpen event fires. For everything but pages, though, it's OK.
The way I would implement this is with a public function and a dialog form. The function would look something like this:
Public Function PrintReport(strReport As String) As Boolean
' open report in PREVIEW mode but HIDDEN
DoCmd.OpenReport strReport, acViewPreview, , , acHidden
' open the dialog form to let the user choose printing options
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
With Forms!dlgPrinter
If .Tag <> "Cancel" Then
Set Reports(strReport).Printer = Application.Printers((!cmbPrinter))
Reports(strReport).Printer.Orientation = !optLayout
Application.Echo False
DoCmd.SelectObject acReport, strReport
DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo
PrintReport = True
End If
End With
DoCmd.Close acForm, "dlgPrinter"
DoCmd.Close acReport, strReport
Application.Echo True
End Function
The dialog form would look something like this:
(source: dfenton.com)
As you can see above, I open this dialog with an OpenArg parameter, which is the name of the report. In the dialog's OnLoad event, I initialize the controls on the form:
Dim varPrinter As Printer
Dim strRowsource As String
Dim strReport As String
If Len(Me.OpenArgs) > 0 Then
strReport = Me.OpenArgs
Me.Tag = strReport
For Each varPrinter In Application.Printers
strRowsource = strRowsource & "; " & varPrinter.DeviceName
Next varPrinter
Me!cmbPrinter.RowSource = Mid(strRowsource, 3)
' first check to see that the report is still open
If (1 = SysCmd(acSysCmdGetObjectState, acReport, strReport)) Then
With Reports(strReport).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Me!txtPageTo = Reports(strReport).Pages
End If
End If
I use the form's .Tag property for the report name, and then do everything based on that, including making changes to report properties on the fly, which is possible because the report is open in preview mode, but not visible.
For instance, I have this AfterUpdate event behind the Layout option group:
With Reports(Me.Tag)
.Printer.Orientation = Me!optLayout
Me!txtPageTo = .Pages
End With
The reason I change the page range numbers is because changing the orientation will most likely change the number of pages. Unlike in the OnOpen event, changes to a the format properties of a report open invisibly in Print Preview mode happen immediately.
I use my standard methods for dialog forms, which is to have the Cancel and Continue buttons set the form's .Visible property to False, which allows the calling code to continue. For the Cancel button, I set the form's .Tag property to "Cancel" and check the .Tag property when the code continues in the calling context (see above).
So, this isn't as great as it would be to be able to set the page range on the Printer object directly, but it gets the job done.
One thing that would need to be changed in production code is making sure there was an error handler in the PrintReport function so that if something went wrong, Application.Echo can be turned back on (otherwise, the user might be stuck with a blank screen and unable to work). The alternative would be to just let the report appear onscreen when the DoCmd.SelectObject method is invoked. But if I'm hiding the report preview from the user, I would want to go all the way.
For more information on this, you should investigate the .Printer object in the Object Browser (F2 in the VBE), and MS Knowledge Base article 290293 is helpful in explaining the interactions between the Application.Printers collection and Application.Printer object and the ones associated with a particular report. I also found a little tutorial on the Office site that clarified a few things.
long ago, i had a very difficult case. i had to do some field creations, and moving and formatting and this could only be done one way. i took a bold approach and it turned to be the only way: i opened the report hidden and in design mode, had vba do it's stuff, and when done, the report was changed to normal and visible for display and printing.
One solution is to set the printer options in the design of the report, save those changes and the print it. The downside is that this will tie the report to a specific printer unless you go into the design and change it.
DoCmd.OpenReport "ReportName", acViewDesign, Null, Null, acHidden
Dim oRpt As Report
Set oRpt = Reports(0)
oRpt.UseDefaultPrinter = False
oRpt.Printer = Application.Printers("printer name")
With oRpt.Printer
.PaperBin = acPRBNAuto
.PaperSize = acPRPSLetter
.Copies = 1
.PrintQuality = acPRPQMedium
End With
DoCmd.Close acReport, "ReportName", acSaveYes
DoCmd.OpenReport "ReportName", acViewNormal
Set oRpt = Nothing