How can I use VBA to restart Microsoft Access 2007 from within the same DB file..??
I'm developing a DB that will eventually be packaged & distributed with the Runtime. For development I'm changing various UI settings, and renaming the file back & forth between *.accdb and *.accdr. But I would like to use a fully programmatic method, which I would then assign to a button or keystroke.
But as anyone who's tried can tell you, one cannot easily use VBA to restart Access from within the same DB. I tried the code here: MS Access: how to compact current database in VBA, but I received the error message "You cannot compact the open database by running a macro or Visual Basic code."
I have various half-baked ideas how to "bounce" the restart off a VBS script, CMD file, or another Accdb file, but I wanted to ask who else may have done this successfully..??
What variety of ways have others done this with success..??
I had the following procedure to copy new version of frontend and then open. Unfortunately, had to abandon when IT tightened security and can no longer programmatically copy files. Don't ask me why it works, it was found code. Previously, I had VBA call a VBScript which would do the copy and reopen.
Private Sub Form_Load()
'Check for updates to the program on start up - if values don't match then there is a later version
If Me.tbxVersion <> Me.lblVersion.Caption Then
'because administrator opens the master development copy, only run this for non-administrator users
If DLookup("Permissions", "Users", "UserNetworkID='" & Environ("UserName") & "'") <> "admin" Then
'copy Access file
CreateObject("Scripting.FileSystemObject").CopyFile _
gstrBasePath & "Program\Install\MaterialsDatabase.accdb", "c:\", True
'allow enough time for file to completely copy before opening
Dim Start As Double
Start = Timer
While Timer < Start + 3
DoEvents
Wend
'load new version - SysCmd function gets the Access executable file path
'Shell function requires literal quote marks in the target filename string argument, apostrophe delimiters fail, hence the quadrupled quote marks
Shell SysCmd(acSysCmdAccessDir) & "MSAccess.exe " & """" & CurrentProject.FullName & """", vbNormalFocus
'close current file
DoCmd.Quit
End If Else
'tbxVersion available only to administrator to update version number in Updates table
Me.tbxVersion.Visible = False
Call UserLogin End If
End Sub
I use the utility provided here: http://blog.nkadesign.com/2008/ms-access-restarting-the-database-programmatically/
In a nutshell, when you run this, Access will quit. However, before it quits it will create a small batch file in the same folder as the database with a couple of commands in. Access then quits, and the batch file will then wait for the removal of the lock file (laccdb file). Once that's removed (as it should be if you're the only user in the database), the batch file then restarts the application.
There is also an option to compact the database on close, too. It works incredibly well for me in my environment, and I have successfully used this for probably somewhere in the region of 5 years.
Related
I am new to Microsoft Access but have been learning as I go this past week. But now I am stuck. I am writing VBA code that checks if the user is using a current database version from their desktop compared to the database version on the server. I have established a table in the back end that holds the numerical value for each user's version and then a table that also stores the numerical value for the newest version on the server(changed by an admin when changes are made). The current code compares the values to determine if the copy that was opened is the newest version. If it is not it opens the version that is on the server and then changes the user's version in the back end table. But I want to change the copy on the desktop so the next time the user opens the copy it is the new version since the code will identify that the version was "updated".
I know that there is the My.Computer.FileSystem.CopyFile() that can be used to copy one file to a new location and write over the file that is there, but if I use this will it be able to write over the file that is open and running the code that is generating the .CopyFile() command? I already have the version on the server being accessed before the .CopyFile() command, but I just don't know if it will actually execute. I'm also not sure if I like the fact that the user will need to reenter their user name and password once the server version opens. Does anyone know of a way to overwrite the file on the desktop without the user even knowing?
I have already done that in a previous database and with some modifications I think you can make it suitable to your needs.
I will start from the point that you have checked the version and found if it is the newest available or an old one.
If Not updated Then
Select Case MsgBox("An update is available for your client!!!" _
+ " You would be able to use this client version but without new features and support!" _
+ " Do you want to update now?", vbYesNo Or vbInformation Or vbDefaultButton1, "Available Update")
Case vbYes
'Call MsgBox("Please contact your administrator to receive your new client version!!!", vbExclamation Or vbDefaultButton1, "Available Update")
Shell "cmd /c ""<whatever path you want>\doupdate.cmd"", vbHide" 'calls a cmd script to do the dirty job of copy -> see below
Application.CloseCurrentDatabase 'closes the current database
Exit Sub
Case vbNo
<whatever you want on no>
End Select
End If
You can remove the select on the above code and it will run everytime the variable updated is False without asking the user.
The cmd script code is the following:
#Echo OFF
SLEEP 3
copy "\\server\groups\<whatever path>\file.accde" "%userprofile%\Desktop\file.accde" /Y
call "%userprofile%\Desktop\file.accde"
exit
The above script is surely not perfect because of a 3sec busy waiting on the begining, but I want to be sure that access has time to close. (The problem will be big enough if acccess hangs on close.
What you can also do is to add the above or the command My.Computer.FileSystem.CopyFile() on the close event of your database, however in that case the update will happen after the user has completed his work with the old version.
Note that in that case I wanted the script that updates to be separate from the database for other reasons. The main principle is the same even if you use vba for the update, you have to close the file before overwriting it.
I have a publicly accessible ms access file - Frontend.accdb for which all tables are linked to another protected ms access database called Data.accdb. An import job is defined in the data.accdb which brings data into the data.accdb which will be updated to Frontend.accdb when opened.
I want to add this import job in my frontend.accdb so that by clicking a button in the frontend.accdb, data.accdb gets refreshed and the tables inside Frontend.accdb is populated with fresh data.
If the back-end tables are linked in the front-end, then you should move the macros to the front-end database to operate on the linked tables.
You can use the shell command as discussed here
How to programatically call a macro in a different (ie. external) Access database using VBA?
but this is likely to complicate matters with regard to making sure that the macro has run correctly and other error trapping.
You could open the backend database from the frontend and run the macro, using an 'Application' object.
Dim appAccess As New Access.Application
'Opening backend database
appAccess.Visible = False 'This can only be here once everyone has trusted the
appAccess.OpenCurrentDatabase "PathtoBackend" & "\data.accdb"
'Time acknowledge the Trust popups if they haven't trusted the db
Do
Sleep 1000 'Assumes you have the Win API Sleep command available.
DoEvents
Loop While Not appAccess.CurrentProject.IsTrusted
appAccess.Run "Import Data Macro Name"
appAccess.CloseCurrentDatabase
appAccess.Quit
OR
Move the entire table update macro to the front end, and push the data from the source to the frontend, to the linked tables in the backend using TransferDatabase.
'Bunch of code that builds the DAO or ADO objects from the source data
Docmd.TransferDatabase acLink, , "PathToBackend" & "\data.accdb", acTable, "FrontEndTableNameContainingSourceData", "BackendTableNameDestination", , )
A week ago, I build a form with a host of buttons to run queries between certain dates in my database, and then export those dates into an excel file. Over the past couple days, I expanded the capability to support custom file locations, sheet names, and source table names. I did all of this so that the tool is useable by whoever comes after me (I'm an intern).
About an hour ago, however, I started getting the error message Run-time error '3275': unexpected error from database driver (1) in a pop-up box. I can't upload pictures directly yet, but here is a picture of the structure of my form. My code is below:
Private Sub SendToExcel_Click()
DoCmd.TransferSpreadsheet acExport, , "TBL_XL_DATA", _
"X:\Confidential\Weekly Intel.xlsx", _ \\The file location is here in the actual code
True, "Input"
End Sub
This is the 'default' export option, which I have not modified in any way over the past few days. The new function is as follows:
Private Sub CustomToExcel_Click()
DoCmd.TransferSpreadsheet acExport, , [Forms]![Date Range]![SourceTable], _
[Forms]![Date Range]![FileDest], _
True, [Forms]![Date Range]![SheetName]
End Sub
I found a similar question, with the same error, and using TransferSpreadsheet, but I don't think my problem is the command running too slowly, expecially considering I ran it (the newer command) an hour ago without trouble.
I am perplexed as to why the command doesn't work now, and why the unchanged command that I haven't dealt with in a while is also now throwing the same error. I am hoping someone understands enough about the error itself to give me a suggestion or two. What should I look for? What should I tinker with to get more information about it?
Found the solution in an obscure forum. My problem is that my path is too long for transferspreadsheet to handle. I am in luck, since my database and excel file are in the same folder. I am sure there is a way to have longer paths be supported, so if anyone knows how to do that, it would be appreciated. For now, I can at least work within the bounds of my constraints.
You haven't supplied the second argument of TransferSpreadsheet which is to specify they type of file that you are exporting to. You should supply this argument explicitly rather than relying on Access to provide it.
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, etc..
for Excel 2007+ (saving as .xlsx).
You might include in your code a check of the file extension that the user has supplied (if any) so that you can use the corresponding spreadsheet-type enumeration.
The error that you received may have been because a file extension wasn't supplied.
Added TransferSpreadsheet accepts a maximum path-length of 64 characters. I would first attempt something simplistic like storing the fullpath in a variable and passing this variable to the method. This is unlikely to get around the limitation though.
Personally, I would transfer the spreadsheet to the temporary, or current, folder, perhaps:
Application.CurrentProject.Path
Then use a simple FileSystem Statement:
FileCopy source, destination
to copy the file, and finally:
Kill source
to delete the temporary version.
This seems a little long-winded but, personally, I like it. It offers me more control over the process. And it is necessary anyway, to get round the 64 character limit.
This error is also being caused by recent Offices Patches:
see https://www.computerworld.com/article/3233260/microsoft-windows/excel-access-external-db-driver-errors-linked-to-this-month-s-patches.html
and ODBC export to Excel fails under Windows 7, Windows 8.x and Windows 10
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".
Our MS Access 2000 developer left the company a year ago. We need to open his app in design mode in order to make modifications. Double-clicking the .mdb file while holding the shift key doesn't work. When I do that the developer toolbar shows for a split second, then all toolbars go away and the app opens as users would see it. No toolbars show and only a basic dashboard is visible to run the app. I tried using the password recovery tool mentioned here but the tool says there is no password. Can someone tell me how I can open this app to make code modifications?
Beth's answer worked for myself and a co-worker. I've copied the solution here from the link in case the link dies.
"...To unlock the Access DB you can use the following if you know the full path to your database.
Copy the following function into a module in ANOTHER database and call the function. You will need to set the strPath to the path of your database."
Public Function ResetExternalDatabaseBypassKey _
(Optional tfAllow As Boolean = True)
'Name: ResetExternalDatabaseBypassKey (Function)
'Purpose: Sets AllowByPassKey to true in another Access Database
'Author: John Spencer UMBC-CHPDM
'Date: May 02, 2000, 12:08:19 PM
'*******************************************
Dim dbs As Database
Dim strPath As String
On Error GoTo ResetExternalDatabaseBypassKey_ERROR
strPath = "C:/MyDatabases/SomeDataBaseName.mdb"
Set dbs = DBEngine.Workspaces(0).OpenDatabase(strPath)
dbs.Properties("AllowByPassKey") = tfAllow
ResetExternalDatabaseBypassKey_ERROR:
Select Case Err.Number
Case 3270 'Property not found
MsgBox "Allow Bypass Key property does not exist " & _
"for the chosen database."
Case Else
MsgBox Err.Number & ": " & Err.Description
End Select
End Function
Make sure there wasn't another copy left around without this code enabled.
This is typical code used to do this sort of thing, SetByPass There are instructions to hit Cntl-G to open VBA Editor and run code to unset this thing.
Have you tried creating a new blank database, and then importing everything?
It sounds like the shift key by-pass has been set, but that's as noted usually only needed for deployment. In fact, for any access developer, this is quite much a standard approach.
So, it not clear if anything at all been locked up here or the person just set things up as most access applications should be when deployed to users.
About the only thing you lose when importing to another application is the tools startup settings and the shift key. If there are custom menus, make sure you check the option to import those also. (However, be careful, as sometimes custom menus can be setup to run a macro on startup, and this was an old security trick). So, if importing once with tool bars and holding down shift key still causes startup code to run, then try creating another blank database and this time import everything except the menu+tools bars from the old application. Holding down shift key will thus then work for you.
Also, if the system not asking your for a password, then what would you expect a password recovery program to do? All you need is basic access developer skills here to deal with this problem and throwing things like password removal when you not being prompted for passwords will not move you forward here.
On the other hand, if after importing all the forms into a new database the design ability is grayed out, then this was in fact a mde file, and you are in a rather difficult situation unless you can find the original mdb file used to create the mde.