How to wait for Compact Repair - Access VBA - ms-access

Have a VBA Module in Access 2007 which performs similar actions in a For loop.
At the end of every loop I wish to compact and repair the current database before proceeding to the next iteration.
Reason : In every iteration I create , use for calculation and delete a table.
The size should remain under control.
Using SendKeys , I cannot compact and repair - if calling the module from a Form Button.
Any trick to ensure that the SendKey works fine and the Module continues onto the next iteration flawlessly. Some idea to control Form loading / Module execution / Checking Status etc.
End Purpose being to wait just long enough till the Compacting is done and then move on. Also how to safely ensure that SendKeys / (suggest alternate) for compacting works fine.
Thanks

"... in a For loop. At the end of every loop I wish to compact and repair the current database before proceeding to the next iteration."
Consider what actually happens when you compact the current database. Access first creates a compacted version of the current database as a new db file. Then it deletes the old db file, renames the new file to the old name, and finally opens the new db file.
So if your code attempted compact each cycle through a For loop ... when Access then opens the compacted db file ... how would it know you wanted it to continue in that For loop?
If you truly want to do something like that, you will have to store a value to record which was the last iteration of the For loop. Then create an autoexec macro to retrieve that value at database open, and enter the For loop at the appropriate cycle. And then decide whether you really want that all to happen every time the database is opened.
However that seems like too much effort to me. It should be simpler to use another db file to hold your volatile data. Then from code in the current database you can use DBEngine.CompactDatabase to compact the external db file.

If you're doing that much compact & repair, then I would split the DB into a front-end and a back-end. All your tables will be on the back-end. Splitting the DB is pretty standard for any regular Access programmer anyway.
Then when you want, use the Shell command to open the back-end DB with the /compact switch. This will open it, do a compact & repair, and then close it.
So, your code will be something like this:
Ret = Shell("C:\Program Files\Microsoft Office\Office12\MSACCESS.EXE /compact c:\MyFolder\MyDB.accdb")
If you need to wait for it to finish, then use the WScript.Shell command instead.
Good Luck

You cannot compact and repair the current database in a loop of any kind. You could compact and repair an external database in a loop, or you could compact the current database on close.

I've already answered your other question (which is quite similar), but for the sake of helping others I have published a simple utility function that helps you restart and compact the current database:
Restarting and compacting an MSAccess database programmatically
To ensure that you continue the proper iteration after you restart:
save the state of your operation (for instance the loop count) in a LocalSettings table (for instance) in your database.
Restart.
Use an autoexec macro to launch the function that does your work: it should load the operation/loop count from the LocalSettings table and carry-on.
Another solution is to modify the restart function to pass a custom command line argument to the Access application that you can check when the app restarts.
You can easily check for command line arguments, see the VBA Command function.

Related

Why can't access keep up with my VBA code in regards to building tables in access from existing xml files using vba?

The situation more in depth:
I am dealing with around one million existing xml files and I have created a program in VBA, within Access 2016 that converts these files to a different type of xml with a new file name, and then saves them to the new file name in a different folder.
As the program builds these new files it also adds entries to about 15 access tables within the database in which the VBA code for the program exists.
The only issue that I am having is that as my code increments the new file name and attempts to add it to the main access table, access "hangs up" and repeats several random increment numbers, a random amount of times which ruins the talbe output and does not allow repeated new file names to save (or they save over the original).
Each time I run the program the result is different, but when I put a stop in my code after the completion of each file conversion and creation and manually cycle through each files by hitting play and refreshing the table with the increment problem, the increment in my talbe works perfect and the results are consistent.
I guess what I am asking is, is it normal for when using VBA code to build tables from existing files, for access to "hang up" when adding a new record to a table using an incrementor?
If not, could I add a refresh of the table after I add a new record entry or before I save the new file to alleviate the issue, and how do I code that refesh of a table? (I already use .Update upon the completion of .AddNew)
Or, could I add a pause in similiar locations to allow access to catch up before VBA continues its calculations and processing?
Don't ask me how I figured it out but through your answers, talking to colleagues, searching for related questions, and redefining the meaning of life, I found the answer!
The problem was not with my code but with how fast my system executed the code compared to how fast Access executed the .Update function. My program was getting ahead of the completion of Access's .Update table function to a point where my incrementor would "hang up" and not see the new table entry because it was not there yet.
I added a few millisecond pause after the .Update and poof, perfectly working incrementor and table updating combo. I will be narrowing the delay time down to the minimum needed shortly, but my question is answered; Access program processing is slower than VBA code calculations by a lot. Thanks Everyone!

How do I prevent the access database from modifying and saving itself upon open?

When working with an Access .accdb, every time I open the file, I see that the 'date modified' in the filesystem changes to now. This makes me nervous. I want it to stop.
I can't be the only person who has ever saved a working db, and opened it a few weeks or months later to an error. Sure, I probably have backups, and backups to my backups, and table data saved separately from my code, and version history taking up multiple gigabytes of the filesystem or in emails or where ever... but it still makes my heart jump a little whenever I see the date modified update on open, when I haven't touched the DB in some time.
Have I flipped a switch somewhere that makes it do this? Is this expected behavior? How can I stop it?
To replicate this, create a new accdb, save and close. Put something in it, nothing, or close it only a second after creating it. Open an windows explorer for the directory the accdb is saved in, and note the date modified value. Open the file at least a minute after the displayed date modified file. alt-tab back to the explorer window, and you see the date modified has changed.
That's the default behaviour, even with a native Access MDB file. They don't work like a normal file that you have to explicitly modify to update the date - it does some things when you open it up, whether you want it to or not.
Just did a quick test - if you set the database file to read-only, it doesn't update itself.
I construct my MS Access Applications into front end and a back end. The Front end database is made up of all the the application objects like the Queries, Forms, Reports, and Modules. The back end database is made up of the tables and links to other data sources.
Many people consider this a Microsoft Access Generally Accepted Best Practice.
So much so that Microsoft includes a Wizard to do the split for you. Shown here
10 Reasons to Split an Access Database
Once the database has been split, It makes is a whole lot more manageable. The Front End can be marked read-only. The Back End remains writable.

compact ms access database in vb.net without copy of the database

I have searched the net on this topic and found, that if an ms access database should be compacted, then I should give the database itself and a new path.
Why is this necessary? If I check in ms access, that it should compact the database after closing, it don't creates a compacted database and deletes the old one, but it compacts only the one database. Or it is so fast, that I can't see it?
Access creates the compacted db as a new file, deletes the old (uncompacted) db file, and renames the new file to the old name.
It always works that way regardless of whether you compact from external code, from within an active Access session, or with compact on close at the end of an Access session.
With a small enough db file, the entire process can complete so quickly that you might not notice the transitional new db file. But with a large enough db file --- 1 GB should do it --- you can watch in Windows Explorer as the new db file is created and grows to it final (compacted) size.
Incidentally, be cautious about compact on close. Many experienced Access developers recommend against that option. The reason is that if anything goes wrong during compact, the new db can be corrupted and your original uncompacted version will be gone ... so no hope of recovery.

DoCmd.Quit hangs in Microsoft Access

I am debugging a Microsoft Access program that occasionally hangs when users click on the quit button after been using the program for a long time. This program is just a lean Access front end with a SQL database back end.
One thing that puzzles me is that the quit button does nothing except for the following command:
DoCmd.Quit
Right now I'm suspecting this could be caused by the antivirus. MS Access will try to write (compacting) the database file on exit and the antivirus probably doesn't like that.
However, I'm just wondering anyone else had this problem before? Anything else that could cause this issue?
The DB probably has automatic compaction..and docmd.quit exercises that option. A compaction of a largish db, even if it is sql backed, can take enough time to look like a hang.
Try this...
Application.Quit acQuitSaveNone will close faster but will not compact.
I have experienced this kind of behaviour and it was casused by code that used a static DAO Recordset that failed to close it.
Static rs As DAO.Recordset
'Missing code
rs.Close
Bit obscure but you never know...
This was when closing the application by any means though.
If you have COMPACT ON CLOSE turned on,
TURN IT OFF.
It is a worthless "feature" that never should have been added to Access in the form that it was implemented.
there is no Access application but the most trivial that should not be split into front end (forms/reports/queries/modules) and back end (tables only). A properly-designed front end will never bloat beyond a certain percentage and does not need to be compacted. It's only the data tables that need compacting. COMPACT ON CLOSE will thus not be compacting the data at all, just the front end, so it's worthless.
if you have it turned on in your back end, you can lose data, with no recourse. This is because some forms of corruption in Jet/ACE allow you to use the data without problems, but as soon as you compact, data is lost. Thus, before compact, a table might have 100 records, and after a compact, 98, because the corrupted records were lost in the compact operation. Since this generally happens without it being noticed, COMPACT ON CLOSE puts you in the very dangerous position of compacting without being able to cancel it so that if your file is corrupt, you can lose data.
Don't use COMPACT ON CLOSE. It is both valueless and dangerous.
Try closing all your forms and running docmd.quit from the command window to see if you get the same behavior.
If not, it might be some teardown code in one of your forms that executes when the form is closed. I have seen it before where this type of code gets in an infinite loop or there is a teardown problem in objects that have cyclical dependencies.
If this turns out to be the issue, repeat the above step with each form that is typically open when you press your "Quit" button until it happens again and then inspect the code that runs when that form is destroyed.
In my case it was the use of 'CurrentDb' which seems to be preventing Access to quit. The problem went away once I replaced it with a global variable at the start of the application like...
Set goDbs = CurrentDb
And thereafter using 'goDbs' whereever I needed CurrentDb...don't know why but that solved my problem.
I've encountered the same problem those days, when quitting Microsoft Access 2019, it quits the Database, but keeping a background process running, so not cleanly quitted the applciation.
I've tried Decompile, Repair and Compacting , no any success.
Windows 10 21H1 updating solved my problem.

Don't have exclusive access to database and so cannot save changes

I'm working on a MS Access database. I've made some changes to one of the modules. I want to go out for lunch, but when I try closing the database, I get the following message:
"You do not have exclusive access to the database. Your design changes cannot be saved at this time. Do you want to close without saving your changes?"
I'm pretty sure nobody else on the network has the database file open, and I don't have any other Access databases open. I'm probably missing something obvious, but would really appreciated some help!
Update:
In the end I copied all the code, closed the database without saving, re-opened it and pasted the code back in. I was then able to save the database. I'm not sure if this was a one off, but I'll report back if it happens again.
If you're sure no one else is in the db but you, it's an additional connection to your db from your own pc. You can verify this with the LDB viewer, downloadable in the free JetUtils.exe download from Microsoft:
http://support.microsoft.com/kb/176670
Look through your code and check if you have two separate database objects in the default workspace or another database object in a separate workspace. That will cause this problem.
To fix it, make sure the database objects are set to nothing before they go out of scope, and if you opened the database object in code, you also need to close it before setting the database object to nothing.
=============================================
Update in August 2022:
The MS link above no longer works. The document remains available on Archive.org, but is outdated. A document that appears to provide the current version of its information is at:
https://learn.microsoft.com/en-us/office/troubleshoot/access/determine-who-is-logged-on-to-database
This provides VBA code for a sub to obtain a list of users. The writer of this update has tested that code successfully in Access 2019.
If you close the database and are sure nobody else has it opened, check to see if there is a .ldb file (it will have the same name as your database file). If the file is there, then there is a good chance it is still in use.
Is it being access by a service, like a website?
You could copy the database to another sub-directory and make your changes. If that doesn't work, I will have to look that up. Of course there is always the database tool, "repair and compress database..."
Is the file located on a file server? If so check to see if any users have a file handle to it.
If it still doesn't work, update your post with your new information and we'll go further.
UPDATE (9/26):
Another thing I do when having strange issues with access databases with contain vba code is decompile. I don't know if this is documented yet, I haven't looked in years, but it's was (at least) an undocumented switch to msaccess.
From a cmd line:
change directory to where msaccess.exe is located.
Run the following command
msaccess \path to access file\databasefile.mdb /decompile
usually runs very quick then opens the database. Open any module and compile.
Doesn't always work, but sometimes can remove strange happenings.
Did you ever trying to copy the database to another directory and making your edits? That should of worked; you could then rename the original and copy the file back.
Anyway, I am glad you are working again.
If even a word mail merge is linked to the access database, that counts as an access connection.
Very simple.
Close all of your MSaccess files.
Open task manager (by right click on task bar).
Select Processes tab in that.
If the list has a msaccess*32 process close that by clicking on End Process.
This worked for me. I think it closes all the recordset which we have not closed in the codes or which is closed forcefully.