MSACCESS.EXE does not close when using POP-UP forms - ms-access

Others have had issues with the MSACCESS.EXE process not closing (from Task Manager) when exiting their databases. Each of the posts I've read have had something to do with not properly closing recordset variables.
When I exit the database I'm working on, I notice the MSACCESS.EXE process moves from the "Apps" section to "Background Processes" in Win 10 Task Manager. This hung process continues to utilize RAM. I'm certain that I'm closing all recordset variables properly.
Through a lot of debugging, I figured out a simple way to replicate the problem:
Create two forms in a new Access database. Set the PopUp property to True for one of them and False for the other. Save the forms "PopUp" and "NoPopUp" and close the database.
Open Task Manager to view the processes running on your screen.
Open your Access database and open the NoPopUp form. Note the MSACCESS.EXE process under Apps.
Close your database. Note that MSACCESS.EXE is removed from your list of Processes (both under "Apps" and "Background Processes").
Now reopen your Access database and open form PopUp. Then close the database.
Note that the MSACCESS.EXE process moves from the "Apps" section to "Background Processes" and is still utilizing system memory.
Additional MSACCESS.EXE processes hang in Task Manager each time the database is closed after opening a form with its Pop-up property set to True.
My database uses a ton of Pop-up forms. How should I be closing my database so that these hung processes aren't stacking up? (I'm using Access 2013 in Windows 10.)
Thanks,
Sam

How are you closing your database now?
Can you change the command to call a function.
Then in that function call a routine that closes all open forms
You may have to add parameter to close without saving - depending on your results.
Function CloseAllOpenFrms()
On Error GoTo Error_Handler
Dim DbF As Access.Form
Dim DbO As Object
Set DbO = Application.Forms 'Collection of all the open forms
For Each DbF In DbO 'Loop all the forms
DoCmd.Close acForm, DbF.Name, acSaveNo
Next DbF
Error_Handler_Exit:
On Error Resume Next
Set DbF = Nothing
Set DbO = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occured." & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: CloseAllOpenFrms" & vbCrLf & _
"Error Description: " & Err.Description, _
vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Function
From http://www.devhut.net/2015/02/17/ms-access-vba-close-all-open-forms/

Try this very basic example in a new sample database.
EDIT: Add a Sleep and DoEvents after every close form in case of caching/fast cpu getting ahead of code? Last attempt to fix weird issue.
In Module 1
Option Compare Database
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Function CloseAllOpenFrms()
On Error GoTo Error_Handler
Dim DbF As Access.Form
Dim DbO As Object
Set DbO = Application.Forms 'Collection of all the open forms
' Close all popups first
For Each DbF In DbO 'Loop all the forms
If DbF.PopUp Then
DoCmd.Close acForm, DbF.Name, acSaveNo
DoEvents
Sleep 1000
End If
Next DbF
' Close remaining forms
For Each DbF In DbO 'Loop all the forms
DoCmd.Close acForm, DbF.Name, acSaveNo
DoEvents
Sleep 1000
Next DbF
Application.Quit acQuitSaveNone
Error_Handler_Exit:
On Error Resume Next
Set DbF = Nothing
Set DbO = Nothing
Exit Function
Error_Handler:
MsgBox "Error closing : " & DbF.Name & vbCrLf & _
"Error Description: " & Err.Description, _
vbCritical, "Error closing form"
Resume Error_Handler_Exit
End Function
Create basic Form1 with two command buttons:
Command button Command1 (Caption= Open Popup Form)
Command button Command0 (Caption = Exit DB)
In Form1's form module paste text
'------------------------------------------------------------
' Command1_Click
'
'------------------------------------------------------------
Private Sub Command1_Click()
On Error GoTo Command1_Click_Err
CloseAllOpenFrms
Command1_Click_Exit:
Exit Sub
Command1_Click_Err:
MsgBox Error$
Resume Command1_Click_Exit
End Sub
'------------------------------------------------------------
' Command0_Click
'
'------------------------------------------------------------
Private Sub Command0_Click()
On Error GoTo Command0_Click_Err
DoCmd.OpenForm "Form2-popup", acNormal, "", "", , acWindowNormal
Command0_Click_Exit:
Exit Sub
Command0_Click_Err:
MsgBox Error$
Resume Command0_Click_Exit
End Sub
Create another form Form2-popup and set Popup property to true
Add command button Command1 with caption "Exit Form"
'------------------------------------------------------------
' Command1_Click
'
'------------------------------------------------------------
Private Sub Command1_Click()
On Error GoTo Command1_Click_Err
DoCmd.Close , ""
Command1_Click_Exit:
Exit Sub
Command1_Click_Err:
MsgBox Error$
Resume Command1_Click_Exit
End Sub

Related

Check if DSN exist in excel vba

I have a excel workbook connected to a MySQL server. I placed a refresh button that refresh the data and it holds unprotect and protect statements for the sheet.
My problem is when open the excel file and click on refresh in a computer that is not in the network, I get a get a DSN creating wizard and also If I press cancel in the wizard the sheet becomes unprotected.
I want to place a IF condition that checks if the DSN is available and if not it should exit sub.
Any ideas?
This is my code with error handler, but I still get the DSN creation wizard and after the msgbox is closed the sheet is unprotected
On Error GoTo handler
Application.ScreenUpdating = False
Sheets("DEC-2015").Unprotect Password:="password"
ActiveWorkbook.Connections("Query from Sample").Refresh
Sheets("DEC-2015").Protect _
Password:="password", _
UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
handler:
MsgBox "Server Connection Lost...", vbOKOnly + vbCritical, "Warning"
Exit Sub
Turn alerts off by altering your code to the following:
Public Sub DoSomething()
On Error GoTo handler
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
With ThisWorkbook
.Sheets("DEC-2015").Unprotect Password:="password"
.Connections("Query from Sample").Refresh
.Sheets("DEC-2015").Protect _
Password:="password", _
UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
End With
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
Exit Sub
handler:
ThisWorkbookSheets("DEC-2015").Protect _
Password:="password", _
UserInterfaceOnly:=True, _
AllowFiltering:=True, _
AllowSorting:=True, _
AllowUsingPivotTables:=True
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
MsgBox "Server Connection Lost...", vbOKOnly + vbCritical, "Warning"
End Sub

Access: Load and apply Custom Ribbon via VBA

I need to set some buttons for RunTime users.
I was created USysRibbon table, inserted XML and tested via Database options. All works fine.
But I need load Custom ribbon via VBA custom function. This function will be executed via AutoExec macro (after user login and user id as temp variable is set).
Please help me to create simple VBA to call LoadCustomUI function and get XML from table (in that table is ID, RibbonName and RibbonXML) and apply to user interface.
Thank you.
I assume that you have created your ribbon table like this : http://www.accessribbon.de/en/?Access_-_Ribbons:Load_Ribbons_Into_The_Database:..._Using_The_System_Table_USysRibbons
Let's say:
your AutoExec macro execute the function Start_App()
You have in your table a record with RibbonName="MyRibbon1"
Create a module with the following code
' This variable handle your ribbon name, so if you have several Ribbons in your table, you adapt this constant to match the current Ribbon
Public Const APP_RIBBON As String = "MyRibbon1"
Public Function Start_app()
On Error GoTo Err_Handler
LoadRibbons
' do anything else you need in the Start_app
Exit_Sub:
Exit Function
Err_Handler:
If Err.Number > 0 Then
MsgBox Err.DESCRIPTION, vbExclamation, "An error " & Err.Number & " occured !"
Debug.Print Err.Number
Resume Exit_Sub
End If
End Function
Private Function LoadRibbons()
On Error GoTo Error1
Dim RS As dao.Recordset
Set RS = CurrentDB.OpenRecordset("SELECT * FROM USysRibbon ")
Do Until RS.EOF
If RS("RibbonName").value = APP_RIBBON Then
' Ribbon found: Load it and exit
Application.LoadCustomUI APP_RIBBON, RS("RibbonXML").value
Exit Do
End If
RS.MoveNext
Loop
Error1_Exit:
On Error Resume Next
RS.Close
Set RS = Nothing
Exit Function
Error1:
Select Case Err
Case 32609
' Ribbon already loaded, do nothing and exit
Case Else
MsgBox "Error: " & Err.Number & vbCrLf & Err.DESCRIPTION, vbCritical, "Error", Err.HelpFile, Err.HelpContext
End Select
Resume Error1_Exit
End Function
Note that you have an additional thing to do: the first time you run the code, the Ribbon will not show. You have to go in the options / current database and in the combo box Ribbon Name: select the ribbon. If you have run the code once, your MyRibbon1 should appear in the combo box

VBA Code Error 2450 After changing to ACCDE

I have a function that has been in use for a number of months that checks to see if the form that is going to be opened will actually have records to be viewed before opening it. Recently I decided to change from ACCDB to ACCDE for security purposes. After making the change over the function started throwing error 2450 "Microsoft Access cannot find the referenced form..." I can't seem to find anything of use online that could tell me what the cause of this error is and why it only happens with ACCDE.
On a side note I realize the inefficiency of the logic in this function, it's on my list.
Public Function ValidateFormToOpen(strFormName As String, strFilter As String, strFieldName As String) As Boolean
On Error GoTo Err_Handler
Dim intNumberOfRecords As Integer
'If the form is currently open count how many results will be shown
If CheckFormState(strFormName) Then
intNumberOfRecords = DCount(strFieldName, Access.Forms(strFormName).RecordSource, strFilter)
'If it is closed open it in a hidden state and then count how many records would be shown
Else
DoCmd.OpenForm strFormName, acDesign, "", strFilter, , acHidden
intNumberOfRecords = DCount(strFieldName, Access.Forms(strFormName).RecordSource, strFilter)
DoCmd.Close acForm, strFormName
End If
'If there were records that will be shown return true
If intNumberOfRecords > 0 Then
ValidateFormToOpen = True
Else
ValidateFormToOpen = False
End If
Exit_Handler:
Exit Function
Err_Handler:
Call LogError(Err.Number, Err.Description, strMODULE_NAME & ".ValidateFormToOpen on " & strFormName)
Resume Exit_Handler
End Function
This is the CheckFormState Code
Public Function CheckFormState(sFormName As String) As Boolean
On Error GoTo Err_Handler
If Access.Forms(sFormName).Visible = True Then
CheckFormState = True
End If
Exit_Handler:
Exit Function
Err_Handler:
CheckFormState = False
Resume Exit_Handler
End Function
An ACCDE format database restricts design capabilities in general. I think that may be why you get an error with this line:
DoCmd.OpenForm strFormName, acDesign, "", strFilter, , acHidden
However I'm not positive that is the complete explanation because when I attempt to open a form in Design View (DoCmd.OpenForm "Form1", acDesign) in my ACCDE database, Access gives me a different error message:
"The command you specified is not available in an .mde, .accde, or .ade database."
So I don't know what the solution is for your goal, but I believe it can not be based on opening a form in Design View.

How do I secure the backends in MS Access?

If I am using MS Access for a frontend, to link to some databases in the backend, how do I prevent people from browsing to the relevant folders and copying/deleting the databases themselves?
There are several options. Please refer to this link:
http://www.techrepublic.com/blog/10-things/10-tips-for-securing-a-microsoft-access-database/552/
The best options are hiding the db browsing options, and password-protecting the database.
You can't secure the backends in MS Access against people who have permission to use them. You can only hide them. Windows does have support for secure authorisation only for signed applications, but Access has never implemented those methods.
You prevent users from browsing to the relevant folders by
(1) (As discussed in other answers) Hiding the name of the folders, so that people don't know where they are.
(2) Hiding the folders, so that people can't see them unless they have permission to see hidden folders.
(3) Removing "List Folder Contents" permission from a top-level folder, so that people don't have permission to browse to the relevent folder.
You can also prevent people from accidently deleting a database by removing the delete permission from the file.
This is what I do. Code is not mine, I just put it toghether based on two months of research I did. Don't get a false sense of security, however, because passwords are in the connection string, so they can be easily hacked, and you have to find the way to control who links to the db from another db, or else they can still dig into the data:
Disable Object menu
Disable Ribbon. Use AutoExec to run: HideTheRibbon()
Function HideTheRibbon()
DoCmd.ShowToolbar "Ribbon", acToolbarNo
End Function
Disable Shift Key Entering, by putting code in an OnClick even of a form "frmByPassOption" for example. Make sure to change the pasword to something you can remember because once this is in place, no one, including Jesus, will be able to get in ther and change the code.
Disallow F11 key whith the KeyPreview options
'***************** Code Start ***************
'Assign this to the OnClick event of a command button (or double-click event
'of a label or graphic) named "bDisableBypassKey"
'Change the "TypeYourBypassPasswordHere" default password to your password
Private Sub bDisableBypassKey_Click()
On Error GoTo Err_bDisableBypassKey_Click
'This ensures the user is the programmer needing to disable the Bypass Key
Dim strInput As String
Dim strMsg As String
Beep
strMsg = "Do you want to enable the Bypass Key?" & vbCrLf & vbLf & "Key password to enable Bypass Key."
strInput = InputBox(Prompt:=strMsg, title:="Disable Bypass Key Password")
If strInput = "carlo12a" Then
SetProperties "AllowBypassKey", dbBoolean, True
Beep
MsgBox "Bypass Key has been enabled." & vbCrLf & vbLf & "Shift key will allow users to bypass startup" & _
"options next time database is opened.", _
vbInformation, "Set Startup Properties"
Else
Beep
SetProperties "AllowBypassKey", dbBoolean, False
MsgBox "Incorrect ''AllowBypassKey'' Password!" & vbCrLf & vbLf & "The Bypass Key was disabled." & vbCrLf & vbLf & _
"The Shift key will NOT allow the users to bypass the startup options the next time the database is opened.", _
vbCritical, "Invalid Password"
Exit Sub
End If
Exit_bDisableBypassKey_Click:
Exit Sub
Err_bDisableBypassKey_Click:
MsgBox "bDisableBypassKey_Click", Err.Number, Err.Description
Resume Exit_bDisableBypassKey_Click
End Sub
'***************** Code End ***************
Put this code under public module:
'***************** Code Start ***************
'Copy this function into a new public module.
Option Compare Database
Option Explicit
Public Function SetProperties(strPropName As String, varPropType As Variant, varPropValue As Variant) As Integer
On Error GoTo Error_Handler
Dim db As DAO.Database, prp As DAO.Property
Set db = CurrentDb
db.Properties(strPropName) = varPropValue
SetProperties = True
Set db = Nothing
Exit_SetProperties:
Exit Function
Error_Handler:
If Err.Number = 3270 Then 'Property not found
Set prp = db.CreateProperty(strPropName, varPropType, varPropValue)
db.Properties.Append prp
Resume Next
Else
SetProperties = False
MsgBox "SetProperties", Err.Number, Err.Description
Resume Exit_SetProperties
End If
End Function
'***************** Code End ***************

Handling an output error in Access

I'm generating a query and report through VBA. I have an option of asking the user if they want to output the report as a snapshot. I first ask them if they want to make a snap shot. If they say no, nothing happens. If they say yes, they get a prompt asking where they want to save it.
Everything works great except if they say yes and then click Cancel on the prompt, it raises a runtime error 2501 saying the report action was cancelled. Here is the code.
DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you wish to create a snapshot of this report?", vbQuestion + vbYesNo) = vbYes Then
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If
This is also the end of my procedure so I don't really care if an error happens here since all the important stuff happened already. I just know some monkey somewhere will flip if they ever see it. Is there a way to handle this error? On Error Resume Next is not an option because that would make debugging a nightmare in the future. It sounds like I'm looking for something like a Try/Catch but I don't think VBA supports that.
On Error GoTo errHandler
....
Exit Sub
errHandler:
If (Err.Number = 2501) Then
Resume Next
End If
End Sub
All you need is to handle the error ie:
On Error Goto HandleErr
DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you wish to create a snapshot of this report?" _
, vbQuestion + vbYesNo) = vbYes Then
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If
ExitHere:
Exit Sub 'or Function
HandleError:
Select Case Err.Number
Case 2501 'Report Was Cancelled
If MsgBox ("Did you really want to cancel saving the report?", _
vbYesNo + vbDefaultButton2 ,"Please Confirm") = vbNo then
Resume
Else
Resume ExitHere
End if
Case Else
Msgbox "An Unexpected error Occurred " & Err.Description, _
vbExclamation,"Error"
Resume ExitHere
End Select
This will give the user the option to undo the cancel and let them know what they did.
There are (at least) two ways to handle this.
1> get the filename and handle possible cancellation in a step before sending the report snapshot. I haven't done this recently but there's another way to generate the snapshot report than the DoCmd.OutputTo command, or some variation that doesn't require the command itself to use a file dialog. I generated report snapshots in an old application and didn't have to ask the user for a filename. I'll try to find the code and show an example.
2> use On Error Resume Next, but only right before the DoCmd.OutputTo routine, then see if there's an error, then turn it back off:
If MsgBox("Do you wish to create a snapshot of this report?", _
vbQuestion + vbYesNo) = vbYes Then
On Error Resume Next
DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
if Err.Number = 2501 Then
'' log or ignore error
Else
'' log or warn other unexpected errors
End If
On Error Goto 0
End If