Connecting an Access form to a SQL Server - ms-access

I have been working on a project that is near completion but this final part is causing me some headaches because I have never done this before and I am having a hard time finding the research to help get me going I have no idea where to even begin. The project is as follows: (this is the context of the email from my boss)
You will need to look up how to check for connectivity using vba. The server you will connect to is the HRLearnDev. I have an access form I will send you that has the connection info in macros on it, where I did something similar. The difference is, my program connected directly to the server. Yours will need to write to a local table, do a check for connectivity when the access file is opened, or every few minutes or something, and if the check reads that there is a connection, write the data from the local server table to the remote server table, then truncate the local table.
I am really stuck and I am running out of options so any insight on where to start to look that is for beginners would be greatly appreciated.

Try something like this to check the connection:
Public Sub TestConnection()
Dim cnn As ADODB.Connection
Dim canConnect As Boolean
Set cnn = New ADODB.Connection
cnn.Provider = "sqloledb"
cnn.Open "Data Source=HRLearnDev;Initial Catalog=YourTableName;UserID=userID;Password='password';"
If cnn.State = adStateOpen Then
canConnect = True
cnn.Close
End If
MsgBox "Can you connect? - " & canConnect
End Sub
Honestly, this is obviously a homework problem and I don't think giving you the entire answer would be the right thing to do, but that should get you started.

Related

use login to allow use of dsnless links

i'm using dsnless links in access 2019 to a mysql instance on aws. I have an Access login form, which passes uid & password to a connection string in VBA, and connects and executes simple "select 1".
All along, i assumed the credentials from my access input form were being used to check against my MYSQL users, BUT...it looks to maybe use a cached user/password instead? When i enter a wrong password into my access login form, it still successfully connects and executes the qdf / sql query.
(i can 'watch' the connection string in vba does have the wrong password)
how can i force odbc to authenticate using the actual id & password actually being sent in connection string??
This simple login form has worked, but just realizing now it will pass a wrong password from my access form, but yet still connect and execute the sql...
Function TestLogin(uid As String, pwd As String) As Boolean
On Error GoTo testerror
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim RST As DAO.Recordset
Dim strcon As String
Dim errX As DAO.Error
Dim strsql As String
Dim strRW
strcon = "ODBC; Driver=MySQL ODBC 8.0 Unicode Driver;" & _
"SERVER={xxx};DATABASE=xxx;PORT=3306;" & _
"UID=" & uid & "; PWD=" & pwd & ";COLUMN_SIZE_S32=1;DFLT_BIGINT_BIND_STR=1;OPTION=3"
Set dbs = CurrentDb()
dbs.QueryTimeout = 5
Set qdf = dbs.CreateQueryDef("")
qdf.Connect = strcon
qdf.sql = "SELECT current_user"
Set RST = qdf.OpenRecordset(dbOpenSnapshot, dbSQLPassThrough)
TestLogin = True
mysqlUser = uid
floor = DLookup("floor", "tblxx", "user ='" & mysqlUser & "'")
Set qdf = Nothing
Set RST = Nothing
DoCmd.Close
DoCmd.OpenForm "Switchboard"
exit_errorTrap:
Set qdf = Nothing
Set RST = Nothing
Exit Function
Ok, the WAY this works can be confusing.
On application start up we asume you do not by accient (or intention) let any form, any VBA code that runs to touch, or logon or use IN ANY POSSBILE way on startup.
Ok, with above? If you linked the tables correct without UID/Password, if you touch, or even try to open a table from the nav pane? you SHOULD get a ODBC prompt. So, test the above - hold down shift key during startup - NO CODE or NO touch of a linked table is assumed here.
Now, click on a linked table - if the table opens, then you screwed up your table linking, and you DO NOT need the logon, then, right????
Next issue - and READ VERY careful.
If you execute a VALID logon (with your logon code), then ONCE you done this, the correct connection is cached - you can NOT IN ANY POSSBILE way blow out, remove, or re-set that cache.
If AFTER having executed ANY valid logon?
Then ANY ADTIONAL attempted logons (say with your logon code) WILL ALWAYS return true and valid. INCLUDING WRONG logons!!!! (they STILL return true!!!!).
The above information thus means some very significant issue's.
to clear hte logon, you will have to (must) exit Access. You thus can't crete a logout form - you must EXIT applcation.
Worse yet, you BETTER ALWAYS BUT ALWAYS BUT ALWAYS exit access first to clear that cache when developing and testing re-linking of tables. If you at any point in time during development by intention (or accident) open a linked table, and enter uid/password (or do so via code, or do so by JUST clicking on a linked table that DOES and DID save the uid/password?.
Then if you decide to re-link tables - EVEN WITH a incorrect UID/password, they WILL REPORT they linked ok!!!! - but they did not!!!! Even during re-link, if you use the wrong UID/Password, you are screwed, since access will in fact use the cached one (if your uid/password are wrong!!!!).
So, you first have to 100%, if not 200% do the first test above - check, double check/ triple check that linked tables do NOT WORK when clicked on.
Now, run your VBA logon.
Now, cliking on any linked table should work. But as noted, ONCE you touched, or logged on (by any possbile means), the UID/PW is cached, and will remain so for that session until such time you exit access.
What this means is you get ONCE chance to logon. They can fail, but the instant you achieve ONE successful logon, then ALL FURTHER attempts at logons WILL WORK - even if incorrect.
In summary:
You can prompt for a logon.
you can do this without having to re-link tables.
All linked tables, and EVEN pass-though queries will use that cached logon.
You MUST exit access to clear this cache, and thus it is IMPOSSILE to now launch your custom logon form and logon with a different user, since the previous user remains cached.
This also as noted means during deveopment, to link tables without uid/pw, you need to exit Access. launch access (without ANY POSSBILE touch of linked tables/data).
You then execute your logon. You THEN re-link tables without UID/Password. Then you have to exit access, re-launch (shift startup by-pass). Now click on a table - it should fail - prompt for odbc.
But, if you exit, shift- by pass startup. Execute your logon. Now click on a linked table - it should work. If it does not, or the first test (without a logon DID work, then as noted, you have royal screwed up something here.
so, for wrong/incorrect logons? You can continue trying to log on.
But ONCE you have logged on - that's quite much the end of this process. Any further attempts at logons will ALWAYS work - even for totaly wrong logons - you have to exit to clear the PW cache.
you also as a result can thus not use two cached passwords - say some tables linked as read only, and some tables linked as read/write (based on different uid/pw). and the reason is you can't control which logon will be used - and access will thus choose the read/write logon.
So, I suppose the most simple explain?
Once a uid/pw is cached, then you can and will be able to use all linked tables regardless of what uid/logon you attempt to use. And EVEN if at that point in time you did decide to run your re-link code? it will re-link JUST fine, even if you supply a incorrect uid/password. But, be carful!!! - you can in some cases thus re-link, check that the tables worked, but when you exit, and re-enter - you find those linked tables now don't work!!!
So, be VERY careful, if not outright SUPER careful when you re-link, especially if you been messing around with connections - you have to exit access, shift by-pass startup. and THEN re-link your tables. One stray cached uid/password, and you are in heaps of trouble - since things will work, and not make any sense at all.
keeping the above simple concept in mind - all will and should now make sense.
I been using this code:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
' this does assume user has enough rights to query built in
' system tables
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
now you used a pass-though query - and I never done/use that before - and don't think it will work. You have to use above format.

MS Access dropping connection to ODBC tables after long period of inactivity

I have an Access 2010 front end which has multiple linked tables on a local MySQL server (Windows) connected via ODBC. Most of the time it works just fine however Access drops the connection if left for several hours with Access open but not being used. When a form is opened again I get an ODBC error.
The problem is fixed by closing Access and opening it again.
I'm guessing that it's a timeout issue but I'm not an Access expert. It seems that I need a way of checking for a valid ODBC connection and if necessary, re-connecting?
Any ideas?
Unfortunately there is no readily available way at this point in time to resolve this issue.
Often the issue is the result of power management on the computer. If the computer goes to sleep, or the computer puts the network card to sleep, then you in trouble and you have to re-start Access.
So if your computer sleeps, or puts the network card to sleep, you often loose the connection - once lost you have to re-start.
Also some hardware with windows 10 also has issues since the DEFAULT setting for windows 10 is fast start up (this means a copy of the kernel and MOST important a copy of the drivers loaded and initialized are written to disk and used to shorten boot/start up time).
If you seeing this issue on windows 10, then I would consider disabling fast start up as that will “always” force a cold re-initializing of the drivers (such as those for the network card). I would also consider turning off the “sleep” mode if that’s been determined to be an issue here (and that such offending computers are seeing this issue after a wake up).
Edit: I should also point out that some "test" for a ODBC connection will not fix this issue since as noted, once lost, you have to re-start Access.
You could try an old trick - at launch to open a simple form bound to a table and hide that form, and leave it open.
I rarely worked during several hours on MySQL tables so I never experienced this issue, but IMO it sounds like a driver-related issue or feature.
Waht I would do in this case is to refresh the tables' connections in VBA, looping over your TableDef objects.
Make a hidden form with a 1 hour timer for instance, and add the following code in the form_timer:
Sub Form_Timer()
Dim tDef As DAO.TableDef
Dim strConString As String
Dim strMySQLServer As String
Dim strMySQLDB As String
Dim strMySQLUser As String
Dim strMySQLPass As String
' ADAPT THIS :
strMySQLServer = ""
strMySQLDB = ""
strMySQLUser = ""
strMySQLPass = ""
strConString = "ODBC;DRIVER={MySQL ODBC 5.1 Driver};Server=" & strMySQLServer & ";Database=" & strMySQLDB & ";Uid=" & strMySQLUser & ";Pwd=" & strMySQLPass & ";Option=3"
For Each tDef In CurrentDb.TableDefs
' You probably have to adapt the folowing if
' Debug and inspect the connection string of your actual MySQL Linked tables
If Left(tDef.Connect, 4) = "ODBC" And InStr(tDef.Connect, "MySQL") > 0 Then
tDef.Connect = strConString
tDef.RefreshLink
End If
Next tDef
End Sub
Watch my comments carefully, espacially if you have linked table to several MySQL databases. It will break some of them without adaptation.
You might also have to adapt the connection string following your MySQL driver, or to use the DSN entry that you specified in the ODBC control panel instead.

Connection to MSAccess DB unable to perform more than one query

I'm setting up my first locally hosted website on a new machine in a long time and to be honest am not very familiar with all the manual settings that get configured now. My last set up was on a Windows XP box and it seemed to "just work" when I enabled IIS. Not so this time.
My latest issues is with connecting to a MSAccess DB. I have a VERY BASIC page with a form that contains 1 input. I check the DB to make sure it doesn't already contain the value and if not, then write the value to the DB. I get the following error:
Provider error '80004005'
Unspecified error
/trips/admin_add_hotel.asp, line 22
I've researched online and everything seems to point to it being a permissions issue. However, I can remove the second portion of the code (the writing) and the page will return fine. If I try to run the page again or refresh, I'll then get the error. This to me says the user has read access. Now, I can wait a little bit and remove the first portion of the code and just write to the DB and it will work fine. Again, to me signifying that the user has write access. However, if I try to run it again... same error.
Here's the ASP code:
<!--#include file="includefile.asp"-->
<%
if Request("action") = "submit" then
'make sure hotel name is filled in
if Request("fhotel") <> "" then
fhotel = Request("fhotel")
'make sure hotel doesn't already exist in DB
sql = "SELECT hotel_id FROM hotels WHERE hotel_name = '" & Replace(fhotel, "'", "''") & "'"
RS.Open sql, ConnectString
if NOT RS.EOF then
Session("msg") = "Hotel already exists"
End if
RS.Close
'add hotel to DB
if Session("msg") = "" then
sql = "INSERT INTO hotels (hotel_name) VALUES ('" & Replace(fhotel, "'", "''") & "')"
Conn.Open ConnectString
Conn.Execute sql
Conn.Close
Session("msg") = "Hotel added successfully"
fhotel = ""
End if
Else
Session("msg") = "Hotel left blank"
End if
Set RS = Nothing
Set Conn = Nothing
End if
%>
My include file is:
<%
ConnectString = "DSN=ConnectionDSN; Uid=username; Pwd=password"
Set RS = Server.CreateObject("ADODB.Recordset")
Set Conn = Server.CreateObject("ADODB.Connection")
%>
My DB has 1 table with two columns:
hotel_id [AUTONUMBER]
hotel_name [TEXT (255)]
Here are my system details:
Windows 7 Pro 64-bit (although connections have been set up for 32-bit based on what I've found online)
IIS 7.5
Just to make sure it wasn't a permissions issue, I've temporarily allowed the 'Everyone' user full access to that folder.
Any help is appreciated. I believe this is the last hurdle I have to get thing fully up and running.
Thanks in advance.
A few things:
32bit vs 64bits: make absolutely sure that your application is set explicitly to x86, not AnyCPU. Also make sure that if you are using the newer .accdb you have the Access Database Engine drivers installed.
Permissions: as Dan Matheus said, make sur that the process under which IIS runs has write permission to the folder. It may not be enough that you set it to Everyone, make sure that your web app can actually create a file in that folder (test this assumption in your code).
Make sure your connection string for the Access file explicitly mentions shared access, and not exclusive access, otherwise, if different processes have the
Keep a connection to the database open all the time to avoid issues with the quick creation/deletion of the lock file.
The Jet/ACE database driver needs to create the lock file every time you access the file (if it is in shared mode). Issues will arise when your app quickly access/releases the database file and the lock file is created/deleted too often.
First it will greatly slow down your performance, and second you will get strange errors.
Just keep a connection open to the database and close it when your app shutdowns.
For more information about the points above, see this:
Intermittent “System resource exceeded” exception for OleDB connection to Microsoft Access data file

Block committing changes to Microsoft Access database

Is there a way to write a hook that will run before changes are committed to an Access DB? I'm looking for a way to block changes if a specific process is currently querying the DB.
You didn't give us much information to work with. Can you adapt something like Create and Use Flexible AutoNumber Fields so specific process first opens a table exclusively? Then any other operations which might change data would have to wait until they can lock that same table.
What is specific process? Do you have a method to determine when/if it is reading data from your database?
If specific process is external to the database, like web server ASP code which uses ADO to fetch data, you could see whether the ADO connection Mode and IsolationLevel properties can help.
Update: I used a form to experiment with the adModeShareDenyWrite Mode property for an ADO connection. While the form is open, other users can open the database, but not make any changes. However, if another user already has the db open when the form attempts to open the connection, it triggers an error.
Perhaps your deployment script could attempt to open a adModeShareDenyWrite connection, and bail out on error.
Option Compare Database
Option Explicit
Dim cn As ADODB.Connection
Private Sub Form_Close()
If Not (cn Is Nothing) Then
cn.Close
Set cn = Nothing
End If
End Sub
Private Sub Form_Load()
Set cn = New ADODB.Connection
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=\\Cmpq\export\Access\backend\links2003.mdb;" & _
"User Id=admin;Password=;"
cn.Mode = adModeShareDenyWrite
cn.Open
End Sub

ADO Connection to Access leaves .ldb file behind with Screen.MousePointer = vbHourglass

I'm writing an MS Outlook (2003) macro which uses an ADO Connection to an Access DB (2003). I am opening a connection, getting some records into a Recordset, which I use to populate a grid (but not bind to). I then close the Recordset and Connection and set both to Nothing.
The process creates an instance of MSACCESS.EXE, and a .ldb file for the Access DB, both of which remain after I have closed the Connection, Recordset, Macro and Outlook itself. One or both of these remnants is preventing opening the Access DB until the MSACCESS.EXE process is manually killed and the .ldb file is deleted.
Similar posts say "close the connection" but that is not solving the problem.
Here's the VBA code:
Screen.MousePointer = vbHourglass
Set db = New ADODB.Connection 'Declared at module level
Set rs = New ADODB.Recordset 'Declared at module level
Dim sSQL As String
sSQL = "SELECT Customers.ContactFirstName As Name, Customers.ContactLastName As Surname, Customers.EmailName AS Email, Customers.Address, Customers.Area, Customers.Town FROM qryCustomersWithEmail ORDER BY Customers.ContactLastName ASC"
db.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & "C:\My Documents\Tables.mdb;Persist Security Info=False"
rs.Open sSQL, db, adOpenStatic, adLockReadOnly
If rs.RecordCount > 0 Then
'actions performed on recordset removed
End If
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
Screen.MousePointer = vbDefault
It's on Vista.
I'm doing this to provide my customer with an easy way to send bulk emails to everyone in his Access database. I tried by accessing Outlook from Access but the security "feature" of Outlook, which pops up a warning message for every email created, scuppered this approach.
UPDATE.
I removed PopulateFlexGrid and the problem still occurred just for opening and closing the recordset. What I previously omitted from this sample, as I considered it irrelevant is that I wrapped the code with Screen.MousePointer = vbHourglass at the start and Screen.MousePointer = vbDefault at the end. I removed this and the problem no longer occurs. Stepping through I see MSACCESS.EXE start up in TM when I call Screen.MousePointer = vbHourglass.
I also tried a version where I used DAO instead of ADO, no other difference, and it works without creating .ldb or starting up an MSACCESS.exe. This works with the Screen.Mousepointer code in there.
Can anybody explain this?
The answer to this is that the reference to
Screen.MousePointer
which i'd omitted as irrelevant, is actually a member of Access. Hence when i call it MSACCESS starts up.
I should have used
Me.MousePointer = fmMousePointerHourGlass
So it's my fault for copying some code from Access VBA to Outlook VBA and expecting it to work the same. Apologies to all of you who spent time looking at this!
What is the code of the function PopulateFlexGrid? Is it possible this is not closing the recordset passed to it?
Try removing this line and instead just looping through the code without doing anything and seeing if it still leaves the LDB. If it still leaves the LDB then the problem is not with the PopulateFlexGrid function
I agree with david saying there is something unclear here. Such a code cannot create an instance of Access or an .ldb file. This code could even run without Access being installed on the machine.
Could you open your recordset with a clientSide cursor? Using a serverSide cursor might cause the access file to be modified (not sure ...) in a way or another. To make sure that your next command does not interfeer in a way or another with access, you could even copy your record locally (to an xml file), close both records and connection, reopen the recordset with the xml file as datasource, and then populate your flexgrid.
By the way, and though it has nothing to do with your problem, it is usually preferable to split the object declaration to:
dim myObect as ADODB....
set myObject = New ADODB....