Open another instance of Access using VBA - ms-access

I am using a form in Access to open other access databases that perform various different queries that publish reports. As the databases I am opening use a multitude of tables, queries, and reports that have nothing to do with each other it would be awkward and time consuming to link to them all and tedious to make changes inside the original database.
I am using Dim appAccess As Access.Application to open each one. It creates a 2nd instance of the new accdb which will not become visible. However, if I go into view code in the original database and then go back to the form it opens the new instance perfectly visible and will continue to do so as long as I keep the original database open. If I close the original database and reopen it I have the same issue which can only be resolved by viewing the code again.
As an example of what I am using
Option Compare Database
Dim APP As Access.Application
Sub TEST()
Set APP = New Access.Application
APP.Visible = True
APP.OpenCurrentDatabase "C:\Users\Documents\Database1.accdb"
End Sub
Does anyone know why this is happening?

Add line:
APP.UserControl = True
For more info review https://www.devhut.net/2018/01/21/ms-access-VBA-open-another-database/#:~:text=MS%20Access%20VBA%20%E2%80%93%20Open%20Another%20Database%201,to%20truly%20appreciate%20the%20power%20of%20automation.%20

Related

How to present a MS Access Form to the end user?

I created a form in MS Access. Unfortunately I cannot publish to access services or make a package solution
I am looking for a user friendly way to present this form to the user. So far the user will open the ms access file , click on the form and fill it out.
I would like to have a way to provide the form ONLY. I do not want the user to see all the tables and the structure . . Is there any way i can separate the form from the tables, queries etc. list ?
I split the database, and gave a fe copy to the user, but it still sucks! All those panels and stuff. Does MS Access has anything to address this issue ?
The issue(s) of splitting the database, and the issues of creating a compiled accDE are NOT ONE BIT RELATED to hiding the Access interface.
100% separate question and issue.
Now, without question the above should be done for any access application, but THE ABOVE HAS ZERO TO DO WITH hiding the access interface.
Once you get the access UI hidden, then you can consider the idea of compile to accDE a good idea to PREVENT users from getting into the access UI parts.
Same goes for splitting. You really need to split. However, AGAIN the splitting has NOTHING to do with hiding the accsss interface.
So now, lets get on to hiding the access interface.
To hide all of the access interface and ONLY show the form, you need to add ONE LINE to your start up code (the forms on-load event is fine).
So, specify the form you want to display in the options.
Add this ONE LINE of VBA code to the forms on-load event.
DoCmd.ShowToolbar "Ribbon", acToolbarNo
The additional settings you require are:
[x] Display Navigation Pane <-- uncheck this box.
[x] Use Access Special Keys <-- uncheck this box
Set access to use tabbed interface, and un-check the box to display tabs.
The form MUST NOT be popup. It can be model, but NOT popup.
The result is you will ONLY see the form. This shows the result:
Now keep in mind to get back to "developer" mode, you have to exit, and then hold down the shift key during startup. When you get all of this working, then you want to compile to an accDE, and search out some answers on how to disable the shift key during startup to prevent your users from seeing the access UI.
So you ONLY need one line of code to achieve this goal. The rest is just choosing the correct settings in your application, and that one line of code on startup.
Steps for publishing the compiled accde file and making it ready for end user:
BackUp: Take backup of your accdb/mdb file
Uncheck following elements from Database Options
(Office Button=>Access Options=>Current Database) :
Display Navigation Pane
Allow Full Menus
Allow Default Shortcut Menus
Security: To prevent anyone bypassing the start-up by using the Shift key and access the table use below code :
Public Function DisableByPass()
On Error GoTo err_proc
'Disable By Pass Key in mde/accde db
Dim dbs As DAO.Database
Dim prp As Property
Dim strMDE As String
Set dbs = CurrentDb
With dbs
On Error Resume Next
strMDE = .Properties("MDE") 'If this is an MDE or ACCDE database, disable bypass key
If Err = 0 And strMDE = "T" Then
.Properties("AllowByPassKey") = 0
If Err.Number = 3270 Then
On Error GoTo err_proc
Set prp = .CreateProperty("AllowBypassKey", dbBoolean, False)
.Properties.Append prp
.Properties.Refresh
End If
End If
End With
exit_proc:
On Error Resume Next
dbs.Close
Set dbs = Nothing
Exit Function
err_proc:
MsgBox Err.Description
Resume exit_proc
End Function

Opening Access from Excel VBA

Edit: The answer to this question can be found within the comments of the accepted answer.
I am attempting to open an Access database from a button click within my excel file. I currently have this code:
Private Sub bttnToAccess_Click()
Dim db As Access.Application
Set db = New Access.Application
db.Application.Visible = True
db.OpenCurrentDatabase "C:\Users\wcarrico\Desktop\wcarrico-CapstoneFinalSubmission.accdb"
End Sub
This seems to work briefly and then Access shuts down almost immediately. If it matters, the Access file has an AutoExec macro that runs through a few tests itself on open.
Don't try to open the Access application then; just create a connection object using one of the Data Access technologies:
- OLE-DB or
- ODBC.
Google "ODBC Connection strings" or "OLE-DB Connection Strings" to get details depending on your particular configuration (and Access filetype).
Probably ADODB is the easiest current library to use for your data access.
Update:
Try Importing the data from Access then using the Data -> From Access wizard. Yu can always use the Macro recoding facility to automatically generate some VBA code for you, that will create some infrastructure for you; I use this regularly when exploring new portions of the VBA object model.
Update - Final resolution of problem, from comments below
That may be because the variable goes out of scope; move the declaration of db outside the function, to module level
The code started Access by creating an application instance assigned to an object variable. At the end of the procedure, the variable went out of scope so Access shut down.
You accepted an answer to use a module-level variable for the Access application instance. In that case, Access remains running after the procedure ends. However if the user exits Excel, Access will close down too.
If the goal is to start Access and leave it running until the user decides to close it, just start Access directly without assigning the application instance to an object variable (Set db = New Access.Application). That db variable would be useful if your Excel code needed it for other purposes. However, it's actually only used to open the db file.
You can use the Run method of WScript.Shell to open your db file in an Access session.
Private Sub bttnToAccess_Click()
Const cstrDbFile As String = "C:\Users\wcarrico\Desktop\wcarrico-CapstoneFinalSubmission.accdb"
Dim objShell As Object
Set objShell = CreateObject("WScript.Shell")
objShell.Run cstrDbFile
Set objShell = Nothing
End Sub
I know this is an old thread, but you will get this error in Excel VBA if you are trying to open an Access database, but you do not have two specific References clicked. (Tools, References on the VBA Editor screen). You need to click 'Microsoft Access 15.0 Object Library' and 'Microsoft ActiveX Data Objects 6.1 Library'.
Remove the New declaration then it works
Actually it is pretty straightforward:
Private Sub bttnToAccess_Click()
db = DBEngine.OpenDatabase("C:\Users\wcarrico\Desktop\wcarrico-CapstoneFinalSubmission.accdb")
End Sub
For this to work you need to declare db as Database at the Module level.
Dim db As Database 'Requires reference to the Microsoft
'Access Database Engine Object Library

Disabling Design View in MS Access

I'm trying to input some code that hides "Design View" as an option for our internal application unless a certain permission requirement is met.
The following code works with one exception:
On Error Resume Next
If Not GetUserInfo("ADMIN_PERMIS") = 1 Then
Dim cb As CommandBar
Dim cbCtl As CommandBarControl
For Each cb In CommandBars
If cb.type = msoBarTypePopup Then
For Each cbCtl In cb.Controls
If cbCtl.Caption = "&Design View" Then
cbCtl.enabled = True
cbCtl.visible = False
Else
cbCtl.visible = True
End If
Next
End If
Next
Set cb = Nothing: Set cbCtl = Nothing
End If
The one problem with this is that it disables Design View not only for the current database, but also for any other access database that is launched. I'm looking for a way to try and apply this code in such a way that it only affects the Access database I have the code in and not in every single instance of it.
I recommend converting the database into a compiled, executable only .accde file (File --> Save & Publish --> Make ACCDE). Doing this will prevent any design or code changes in the application. Keep a development version in the normal .accdb format. Make your changes there and then compile into the .accde version for each update.
Since your team updates the database often, you could benefit from using Peter De Baets' database starter. The database starter makes a local copy of the front end of the database, allowing uses to continue to work while design changes are being made. After the production accde front end file is updated, the users will automatically copy the new file the next time they open the database. In my office I have found that I can push out a quick fix and simply email everyone saying "Close and reopen the database guys!".
All these answers are great. If you are interested in the simplest method, I found the form holds the key, albeit in a strange spot.
In the forms properties->Other Tab->Shortcut Menu =No

What is this Access bug? You do not have exclusive access to the database at this time

Tested on Access 2003 Pro (build 11.8321.8324) SP3.
Steps to reproduce:
create a new database.
create a new form.
put a button on the form.
paste the following code in the button's Click event procedure:
Debug.Print Workspaces.Count
Debug.Print CurrentDb.Name
close the code editor and form, saving changes.
do not skip this step: close Access.
re-open Access and your database.
open the form
click the button
click the toolbar button to switch the form to design mode.
You should see the following error dialog:
You do not have exclusive access to the database at this time. If you proceed to make changes, you may not be able to save them later.
Does anyone know what is going on here?
The simple workaround is to call CurrentDb prior to calling Workspaces for the first time:
Debug.Print CurrentDb.Name
Debug.Print Workspaces.Count
Debug.Print CurrentDb.Name
I'll take a shot at demystifying what's going on, but this is just my theory.
The relevant bits of the Access help file are as follows (for CurrentDb):
Note In previous versions of
Microsoft Access, you may have used
the syntax
DBEngine.Workspaces(0).Databases(0) or
DBEngine(0)(0) to return a pointer to
the current database. In Microsoft
Access 2000, you should use the
CurrentDb method instead. The
CurrentDb method creates another
instance of the current database,
while the DBEngine(0)(0) syntax refers
to the open copy of the current
database. The CurrentDb method enables
you to create more than one variable
of type Database that refers to the
current database. Microsoft Access
still supports the DBEngine(0)(0)
syntax, but you should consider making
this modification to your code in
order to avoid possible conflicts in a
multiuser database.
And for the Workspaces collection:
When you first refer to or use a
Workspace object, you automatically
create the default workspace,
DBEngine.Workspaces(0).
It would seem that by creating the default workspace prior to the first call to CurrentDb, you are somehow causing CurrentDb to forget how it should work. It seems that instead of creating a new instance of the current database it just uses the one that's already lying around in the default Workspace.
Of course, this is all conjecture and I'm as curious as you to know the "real answer".

VBA File Open is slow

I'm trying to open a series of Excel spreadsheets using an instance of Excel created inside of a module in an Access database. I can get the files to open properly; however, the actual call to make Excel start takes quite a while, and to open the files takes even longer. The location of the files doesn't matter (same time to open on a local HDD as a network drive).
In an attempt to figure out what was taking so long, I added a timer to the logging module. Opening the files takes approximately 2m30s, during which the host application (Access) is entirely unresponsive to user input); the rest of the script executes in less than 10 seconds.
I'm using the standard Excel.Workbooks.Open call as follows
Set OpenSpreadsheet = Excel.Workbooks.Open(Name, 2, False)
Using Debug.Print methods around this line says it can take up to 2 1/2 minutes for this one line to execute.
Is there anything I can do to make the Excel files open quicker?
EDIT: When opening, UpdateLinks is False and ReadOnly is True; all other options are left to their defaults.
First idea: Can you use a jet driver with an ODBC connection to Excel, instead of opening it in an Excel object? Might be much faster.
Second idea: Make sure to create and instantiate the Excel application object just once at the beginning of the routine, then use the Excel.Workbooks.Open() and Excel.ActiveWorkbook.Close() for each spreadsheet. That way you're not "re-launching" the MS Excel application each time.
To draw out the second of #BradC's well-advised recommendations, if you need to use Excel in more than one procedure, create a self-initializing global function. I always use late binding for automating Office apps.
Public Function Excel(Optional bolCleanup As Boolean = False) As Object
Static objExcel As Object
If bolCleanup Then
If Not objExcel Is Nothing Then
Set objExcel = Nothing
Exit Function
End If
End If
If objExcel Is Nothing Then
Set objExcel = CreateObject("Excel.Application")
End If
Set Excel = objExcel
End Function
Then you can use it in code without needing to initialize it, and the single instance will remain available to any code that needs to use Excel.
And when you shut down your app, you'd call Excel(True) to clean up.
I do this with Outlook and Word all the time. However, there are some COM apps that it works poorly with, such as PDF Creator, which doesn't take kindly to this kind of treatment (you end up in an endless loop with it shutting down and re-initializing itself if you try to destroy the instance this way).
Another approach depends on your setup and process.
In my case I need read-only access to a set of Excel documents stored on SharePoint. My code is currently like:
For each path in paths
set wb = Workbooks.open(path,false)
next
In this case, each workbook is individually downloaded each time a workbook is opened. It would be significantly more efficient if the files were downloaded asyncronously and after the download is complete, the rest of the process executes on the local disk.
My idea is to use CopyFileEx() and pass a callback function. Excel will then download the Excel documents to disk asynchronously and call a VBA function regarding progress. When all files are completed, we can launch the next part of the process, which opens the local workbooks, scans them and then removes them from the local drive.
I'll post code later if I manage to implement it.