VBA very slow after splitting Access DB (local PC, not network) - vba

After splitting my Access DB I have found that VBA code run in MS Project (called from within Access) has slowed down significantly (by a factor of about 6).
I am using MS Access 2016 and Project 2016, both on my local PC with no network traffic.
The VBA code in MS Project does a series of lookups against the Access database and it is these procedures that are running slowly. I would have expected a slowdown if my Access Backend was on a corporate network, but am surprised to see a slowdown when both back end and front end and MS Project are all local.
Any suggestions?
Thanks
Eric

Most likely, the slowdown you are experiencing is the backend file repeatedly opening and closing when it is being accessed by the frontend. The accepted solution is to open a persistent link between the frontend and the backend. This way the backend file will stay open for as long as a frontend is open.
To set this up, you will need to create an empty table in the backend that isn't used anywhere else in the project. I'll call it tblKeepOpen
Sample code: (called in the AutoExec macro)
Public Sub KeepBackendLinkOpen()
Static rsOpen As DAO.Recordset ' Static makes the Recordset reference persist
Set rsOpen = CurrentDb.OpenRecordSet("SELECT * FROM tblKeepOpen", dbOpenSnapshot)
End Sub
This reference will persist until the VBA interpreter crashes or loses state. You can reload the link by running KeepBackendLinkOpen from the Immediate window, or running AutoExec again.
Some people like to manage persistent links in a hidden form. Your choice.
PS -- there are lots of examples on the internet on how to do this, but I couldn't find any with a nice simple example.

Related

Running a WinForms application using Excel VBA

I have written a WinForms application in vb.NET using vs 2017. The application opens an excel Workbook which contains a document register, and updates the files as necessary.
I am very happy with the application, however one possible improvement I would like to pursue would be to attach the application to a macro in the Excel worksheet that the application updates, as the users of the application tend to open this worksheet by habit as it is.
I have the following code, which opens the application from the document register:
Sub AppMacro_Click()
Dim AppOpen
AppOpen = Shell("C:\Document Updater.exe", 1)
End Sub
The user can then run the application.
The problem with this method is that the application checks that no user has the workbook open, so that it can open the original copy (workbook is on a network drive), so if the user runs the macro, they will then have to close down the workbook before clicking the run button on the application. I would prefer if this didn't have to be the case.
What I would like to achieve is the following:
1) If the user runs the application using the macro, the application adapts and updates the opened workbook (as long as it isn't read-only)
2) If the user runs the application as usual, it still detects that no other user has the workbook open
What would be the best way to achieve this?
In general storing a workbook on a shared folder to be accessed/modified by multiple users is usually asking for trouble, you are better off using an Access DB if your users pool is fairly small or use full grown SQL (mySQL, SQL Server). Also since you have a working application in .NET where the user is very dependent on Excel, I would recommend you transition to an Excel Add-in. It is really easy and your solution would be more integrated with Excel

How to prevent local replication of a company database

I have a big Lotus Notes company database containing sensitive data and I want to prevent normal users to replicate this database locally.
Explanation of the main problems :
sensitive data on laptop
server deleted documents reappear if the purge interval is more frequent than local replications
server deleted documents reappear if users modify them locally
These solutions are NOT working in my context :
uncheck the "replicate or copy documents" in the ACL for users. If done, users cannot copy/paste content in form fields.
check "temporary disable replication" cause the application is replicated accross multiple servers
prevent local disk writing
You've ruled out all the features that are designed to help you with this, so you can't prevent local replication. All you can do is track it. There are third party products that can help you do the tracking. One of them is called SecurTrac, by a company called ExtraComm. You could write your own tracking, too, using the C API's extension manager routines, or if you don't want to write in C you could ues the Trigger Happy project on OpenNTF, which gives you some boilerplate C code that you can use to trap accesses and which allows you to call Java code to do the rest of the work of actually logging and tracking.
This does not prevent replication, but it prevents opening the database as local replica file. I have created a test database and added this code to postopen event of the database script. Just quick and dirty:
Sub Postopen(Source As Notesuidatabase)
Dim db As NotesDatabase
Dim server As String
Set db = source.Database
server = db.Server
If server = "" Then
MsgBox "you are not authorized to use this database as local replica file, it will close after click on ok button"
source.Close
Else
'opening allowed, do whatever you want
End If
End Sub

MS Access / Sharepoint Online link to Database to allow multiple users / VBA?

Ok, our current problem is the classical "trying to allow multiple users access onto one fe file (this is in runtime currently)" - This cannot be handled (at least in AC2007) and is best solved by installing a FE on each computer that is using it.
This poses another problem for us, we have many employees who we want to be able to have access to it, yet the program probably doesn't warrent our techs to push out updates of this file to each computer with their "patches" (plus there may be added costs to doing such for us).
We would really prefer the ability for users to open a link from our internal portal to the file as can be currently achieved. We are mulling over the possibility of pushing out 4 or 5 copies of the FE application on a shared folder and creating an Access program that would essentially check to see if a FE app is open say FE1 and if so it would open FE2 (and so on) then close the sharepoint linked database that did the checking so a new user could open that. This would allow multiple users access to the same BE information using the same FE program.... would this work? Any ideas of how to go about it?
Yes it works, the idea is to create a function that checks for the open file, if it finds its open it replies with an error, on the error you can move to the following database. Here is a sample code:
Option Explicit
Function FileLocked(strFileName As String) As Boolean
On Error Resume Next
Open strFileName For Binary Access Read Write Lock Read Write As #1
Close #1
If Err.Number = 0 Then
Application.FollowHyperlink "c:\MasterMAX.accdr"
DoCmd.CloseDatabase
End If
If Err.Number <> 0 Then
Application.FollowHyperlink "c:\MasterMAX2.accdr"
End If
End Function
Disclaimer: I don't know anything about SharePoint, so I can't say if my proposed solution is still viable when SharePoint is involved.
If your problem is just how to distribute the file to all machines, why don't you let your users start a batch file that copies the Access frontend from a network share to each machine and starts it?
We are doing something similar at work (without SharePoint, though), and I described our setup here:
How to automatically update MS-Access 2007 application
We have put the batch file on a network share as well. The users have just shortcuts on their desktops to the batch file on the network share, so it's easy to update the batch file as well.
Maybe you can do something similar (let the users run the batch file from SharePoint, which copies and starts the Access frontend).

Microsoft Access can't save design changes because another user has the file open... but I am the only user?

Just a little background: I am using Access 2010 to create forms and VBA code in an Access 2003 format database. For some reason, Access 2007 format databases always corrupt on me when I make changes and save them with a particular group of objects, but that's for another discussion.
When writing VBA code in this Access 2003 database, any time my code breaks (via breakpoint or an unhandled error) and I make a correction, Access tells me that it can't save back to the database because another user has it open. However, I am the only user working on the database; this is a local copy of the database and it's sitting on my desktop.
The LDB file can't be deleted because Access is using it. When I first load the database, I see my machine name and "Admin" when opening the LDB in a text or hex editor. After a break, I see that plus a duplicate entry, but this time around "admin" has a lower-case "A."
Closing the database and reopening it fixes the problem but makes it needlessly cumbersome to debug my code. Anyone else encounter this issue and/or have a fix for it?
It might be helpful to know what your code is doing when this happens. Certainly that's not normal behavior. For instance, are you opening another database with New Access.Application? Are you using ADO or DAO to access records in the database with a connection string?
There are no external connections to the database at all.
It may not matter if there are external connections to the database if you are using a connection string to connect to the open database; not sure but that may be seen as an external connection... you may want to use CurrentDB for DAO, or CurrentProject.Connection as your ActiveConnection for any ADO queries.
I am assuming that this problem persists through reboots; but for the sake of argument, try closing out Access and going to the task manager to make sure you have no other instances of MSAccess.exe running. You might even try closing all Office products and/or making sure that Access is the only Office product running. I have seen some weird conflicts between Microsoft Communicator and Outlook; so it's not entirely out of the question for Access to have issues with another MS product.
You may also want to check the size of the database to make sure it's not exceeded 2GB. That causes the infamous "Invalid parameter" error; perhaps it might be causing this as well.
With no other details about how your program works, we may only be able to offer generic advice like this.
I have discovered a way to cause the problem discussed above (and thereby to correct it). Turns out if you create a database object and set it to the current database, you get this problem.
That is,
dim cdb as database
set cdb = currentdb
From this point on, you're cooked.
Instead, figure a way around this by possibly using currentdb directly or not using it at all.
This worked for me.
In your VBA Try checking that all your open Connections to the database are closed. Until the connection is open the LDB fill will be there.
Same symptom of not being able to save form or code mods after application had started. I found a workaround today! In the startup of my first form of the app, I had issued a "DAO.DBEngine.SetOption dbMaxLocksPerFile, 20000". Commenting this statement removed the problem. I did no further testing, but FYI, the DBEngine call was before any reference or attempt to use CurrentDB(). Also the current default on my Access 16 install is 9,500.
I thought I might answer here, since I stumbled upon this question while having a similar issue. Essentially, it boiled down to this: I could either edit forms, VBA, etc. or edit information in the local database (which I'm using as a cache) with currentDB. I also have a backend database, but the locking was clearly on the frontend database.
The solution ended up being weird, but stupidly simple. When the frontend starts up, I have it immediately create a connection to the backend using OpenRecordset (and similarly to you, that backend was still on my own computer for testing purposes). I tried temporarily disabling that code, and suddenly it wasn't an issue anymore. And it turns out, once I call currentDB, I can then call OpenRecordset to open the connection to the backend, and suddenly it isn't a problem anymore.
Tl;Dr: if you're calling OpenRecordset somewhere in your code to connect to a backend, be sure to call something like set db = currentDB beforehand, then everything works. (That is, probably until I publish this answer and Access then decides it doesn't want to anymore).
Why this fixed it is beyond me, someone with more knowledge can maybe answer that.
The solution:
options > current database > click enable -track name auto correct info

Insufficient memory to continue the execution of the program

My Application (Vb.net, Access 2003/2007) is to scan Access Database files for activex controls and to generate report accordingly.
Problem:
Getting an error like:
"Insufficient memory to continue the execution of the program."
The above error occurs while scanning for older version of Access files like prior to office 2000.
And the line of code where I get this is as follows:
Dim oForm As Access.Form
Dim oAccess as Access.Application
oForm = oAccess.Forms(objForms.Name)
But it opens the file and form as well.
Need Help:
Whether it is possible to read the file (Access Forms and Reports) or not?
Please provide me reference or any solution.
You appear to doing COM automation of Access to open the forms and then cycle through their controls looking for certain properties.
Another solution would also involve automating Access, but it wouldn't require actually opening the form, and that's the undocumented Application.SaveAsText command. You'd do something like this:
Application.Saveastext acForm, "dlgWebBrowser", _
"C:\Output\dlgWebBrowser.txt"
You would then have to figure out how ActiveX controls are described in that file. If that file looks like the code for a VB form, that's because that's precisely what it is.
The example above had an IE web browser control on it, and after a dump of OLE data, it had this in it:
OLEClass ="Microsoft Web Browser"
Class ="Shell.Explorer.2"
GUID = Begin
0x54c1ea41936d2046b9dc5b29905976e3
End
I would expect that all ActiveX controls will have an OLEClass, but I non-native avoid ActiveX controls on principle because of the problems they can cause if not properly installed when you try to run the app.
In fact, that could be the source of the problem -- if you open the Access form on a machine that doesn't have the relevant ActiveX control registered, it's going to fail, and the form won't open.
My bet is that Application.SaveAsText is going to sidestep that problem entirely, since the form doesn't have to be opened.
I've seen behaviour very similar to this before. Access 97 files will sometimes report an 'out of memory' error if you try to open them on a computer with more than (I think) 1Gb of RAM. The error doesn't always manifest itself immediately - sometimes the project can appear to run normally but crash when you try to open a particularly large object.
In the case where we did run into this the users were running an old Access 97 database on new XP machines they'd been upgraded to with modern amounts of RAM. Tech support for the company tried everything they could think of - including complete office reinstalls, applying all patches etc. but eventually had to resort to removing RAM from the computers - whereupon the errors went away and everything was rock solid again. I am uncertain as to the exact cause, but it will be connected with memory management in the Access 97 file format (I believe the error is on MSDN somewhere but I wasn't directly involved with Tech support hunting the solution down - I'd just written the application many years before)
I'd suggest you're only way out is to use a special, low memory, PC to run the application.