MS Access - SQL Server Login Prompt won't go away - sql-server

So I have this application and I moved all local tables to SQL Server using upsizing, now they are currently linked tables. I'm able to access tables and forms related to tables can be accessed with no problems. But when I programmatically fetch a record, or perform a sql operation in VBA script, a SQL Server Login prompt pops up asking me to enter in the SQL Authentication login to access the database.
I followed this link here:
https://support.microsoft.com/en-us/kb/177594
Where this is my end code:
Dim db1 As Database
Dim db2 As Database
Dim rs As Recordset
Dim strConnect As String
Set db1 = OpenDatabase("C:\Workspace\ms1.mdb")
strConnect = UCase(db1.TableDefs("dbo_TableA").Connect) & ";UID=User1;PWD=Password1"
Set db2 = OpenDatabase("", False, False, strConnect)
db2.Close
Set db2 = Nothing
Set rs = db1.OpenRecordset("dbo_TableA")
rs.Close
db1.Close
Set rs = Nothing
Set db1 = Nothing
DoCmd.RunCommand acCmdSaveRecord
'Sql Server login prompt pops up after running the below code;'
If DCount("*", "TableA", "[ColA] = [forms]![FRM_LOGS]![USER]") = 0 Then
MsgBox "User ID not found - contact HelpDesk", vbCritical
DoCmd.Quit
Exit Sub
End If
The DCount is triggering the SQL Server Login Prompt. I need this prompt to go away. If I open up a form, query, report, anything where the access object is bound to the data, I get no message. It ONLY happens in VBA when I'm trying to access the data object.
Edit! I did find the culprit. I deleted the linked table to the TableA in sql server, and I relinked it again, and clicked the Save password checkbox. I did this before, and it didn't work. Did it again, and it fixed everything. Not sure why this didn't work the first time. I marked the below as an answer because that did solve the problem given the circumstances.

Not sure what you're doing here with two database connections and using DCOUNT on an internal table?
It looks like your database connection has linked tables that have stored passwords
Why not just use your recordset that works to check for a valid user?
Set db1 = OpenDatabase("C:\Workspace\ms1.mdb")
Set rs = db1.OpenRecordset("SELECT [ColA] FROM [dbo_TableA] WHERE [ColA] = """ & [forms]![FRM_LOGS]![USER] & """")
if rs.EOF Then
MsgBox "User ID not found - contact HelpDesk", vbCritical
DoCmd.Quit
Exit Sub
End If
rs.Close
db1.Close
Set rs = Nothing
Set db1 = Nothing

Related

Application.CalculateUntilAsyncQueriesDonecode prevents the login mask of an SQL query in Excel

I have an SQL query in Excel. After the query a message should appear. This works well as an existing user, but for new users the password query is hidden.
I was looking for an alternative to Application.CalculateUntilAsyncQueriesDone but couldn't find a solution. The Excel login mask is always not displayed.
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone
MsgBox "The new data has been imported.", , "Import done"
How can I get Excel to wait for the end of the query and get the login displayed before (if I have never entered the password as a new user)?
Ok, so this not the solution you're looking for, but I don't think it exists I'm afraid. Embedded query objects in Excel are horrible to work with, and they expect you to be using Active Directory for your SQL Server password, hence the exceptionally poor handling of the "login" popup box.
My advice would be to move away from embedded workbook tables / queries and script out your queries using an ADODB connection, purely in VBA.
If the user's password is a simple username / password combo, then you can read it from a cell in your sheet before you send the query to the server.
If the login is based on Active Directory, then the user doesn't need to enter their password at all, ADODB will just log them on automatically.
Here's my simple SQL function I use to query SQL Server databases using ADODB. The long string in the middle after "conn.open" is the connection string. In that, replace "DatabaseHostName" with the Host name of your DB, and "DatabaseName" with the name of the DB you want to query by default:
Sub ReadSQL(SQLQuery As String, DestinationRecordSet As Object)
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
Set DestinationRecordSet = CreateObject("ADODB.Recordset")
conn.Open "Provider=SQLOLEDB;Data Source=DatabaseHostName;Initial Catalog=DatabaseName;Integrated Security=SSPI;"
conn.CommandTimeout = 0
Set DestinationRecordSet = conn.Execute(SQLQuery)
End Sub
then I call it like this:
Sub GetData()
Dim wb As Workbook
Set wb = ThisWorkbook
Dim OutputRecordSet As Object
Dim SQLQuery As String
SQLQuery = "SELECT TOP 10 * FROM dbo.SomeTable"
ReadSQL SQLQuery, OutputRecordSet
'Clear output sheet'
wb.Sheets("Output").Cells.ClearContents
'Write Headers from query in row 1'
For x = 0 To OutputRecordSet.Fields.Count - 1
wb.Sheets("Output").Cells(1, x + 1).Value = OutputRecordSet.Fields(x).Name
Next x
'Copy the data from the query to the worksheet, under the headers'
wb.Sheets("Output").Range("A2").CopyFromRecordset OutputRecordSet
End Sub
When I call my "ReadSQL" sub from this sub, by default it waits until the query is complete before doing anything else.
Again I would strongly recommend active directory logins for your DB, then you never have to worry about passwords, but If you wanted to embed a user's password into the connection string, you could, or you could build the connection string based on something the user entered, or had entered into a cell in the workbook.
In any case, you will find once you move away from Excel's embedded tables which work with the dreaded "Refresh All" button, things will become much easier to control, and your queries will run about 10 times faster.

Set commandtimeout for linked SQL Tables/Views in Access front end

We have moved some back-end data tables over from a network drive (mbd file) to being on an SQL Server database. Things mostly work great, but if staff are accessing things through a VPN (which slows things down a lot), then we get connection errors when we run reports that retrieve a lot of data. My guess is that I need to set a timeout to a larger value, and I did some research and it seems that I need to set the commandtimeout (or maybe query timeout?).
Below is the VBA code we use to connect the SQL Server tables/views to our Access front end from the SQL Server back end. Am I right that I likely need to specify a commandtimeout? Where in this would we add the commandtimeout (or other timeout) value?
Public Sub CreateSQLLinkedTable(strSourceTableName As String, strNewTableName As String)
'************************************************************************************
'* Create a linked table in the current database from a table in a different SQL Server file.
'* In: *
'* strNewTableName - name of linked table to create *
'* strSourceTableName - name of table in database *
'************************************************************************************
Setup:
Dim tdf As TableDef
Dim strConnect As String, strMsg As String
Dim myDB As Database
' set database vars
Set myDB = CurrentDb
Set tdf = myDB.CreateTableDef(strNewTableName)
MakeConnections:
On Error GoTo OnError
' turn system warnings off
DoCmd.SetWarnings False
' define connect string and source table
' We do not need to specify the username (Uid) and password (Pwd) in this connection
' string, because that information is already cached from the connection to the SQL
' Projects database that we created in CheckSQLConnection() that was run to check connection
' to the database. So here we can have a connection string without the Uid and Pwd.
With tdf
.Connect = "ODBC;Driver={SQL Server};" & _
"server=" & myServer & ";" & _
"database=" & mySQLDB & ";"
.SourceTableName = strSourceTableName
End With
' execute appending the table
myDB.TableDefs.Append tdf
' turn system warnings back on
DoCmd.SetWarnings True
ExitProgram:
' this block of code will run if there are no errors
Exit Sub
OnError:
' this block of code runs if there is an error, per On Error assignment above
' display error message with details
MsgBox "There was an error connecting to the SQL Server data source Projects. Error = " & err & ", Description: " & err.Description
'exit Projects
Call CloseFormsAndQuit
End Sub
There is an ODBC timeout property. Open the query in design view, and go to properties to see it. There is also an (ODBC) query timeout on the current database properties page. You can set it programmatically as well:
Dim objDB As DAO.Database
Set objDB = CurrentDb()
objDB.QueryTimeout = 120
http://www.geeksengine.com/article/how-to-change-timeout-value-for-access-sql.html
Also check the server configuration. There is a query timeout on server side.

Microsoft Access -> SQL Server - blank/default Schema

we have a large MS Access application which uses SQL Server for the database (about 200 tables).
We want to convert it to a multi-tenancy database, where we will have a single large SQL Server database. Inside the database each client will have their own set of tables in their own schema. Eg, ten clients using database - ten Schemas in that database.
We will then migrate it to Azure and run the MS Access application as an Azure RemoteApp.
We want to create an Active Directory User Group for each client, and map it across to the default SQL Server Schema for that client.
The idea is that new users are added to the relevant AD User Group, and by default get mapped across to the right Schema with their data,
The problem we have is the MS Access Linked Tables contain a hard-coded explicit Schema (dbo by default).
Can anyone think of a way to store a "Source"/external/linked table in MS Access without having to specify a Schema. Eg. just "tblSales", not "dbo.tblSales".
A typical relink code goes like this (a snip only):
For Each tdf In dbs.TableDefs
strName = tdf.Name
If Asc(strName) <> Asc("~") Then
If InStr(tdf.Connect, cstrDbType) = 1 Then
tdf.Connect = strConnect
tdf.RefreshLink
Debug.Print Timer, tdf.Name, tdf.SourceTableName, tdf.Connect
DoEvents
End If
End If
Next
I have no other schema than dbo to test with, and I'm not sure if the property SourceTableName is read-only. If not, it could be adjusted:
For Each tdf In dbs.TableDefs
strName = tdf.Name
If Asc(strName) <> Asc("~") Then
If InStr(tdf.Connect, cstrDbType) = 1 Then
tdf.Connect = strConnect
tdf.SourceTableName = strNewSchema & "." & Split(tdf.SourceTableName, ".")(1)
tdf.RefreshLink
Debug.Print Timer, tdf.Name, tdf.SourceTableName, tdf.Connect
DoEvents
End If
End If
Next
If it is read-only, you will have to delete the linked table and recreate the link.
That said, I'm not sure if your idea of a schema for each client is such a good idea. We had similar considerations and decided simply to create a database for each client. If for nothing else, backup and restore clientwise is greatly simplified.

How to use connection string in ODBC to create a table in Access permanently linked to a SQL source?

I have created a table in my Access front end application, and try to connect it to the back end database with the following subroutine:
Sub createFlowTable()
Dim db As Database
Dim tblDef As TableDef
Set db = CurrentDb
Set tblDef = db.CreateTableDef("myTable")
tblDef.Connect = "ODBC;DRIVER=SQL Server;SERVER=myServer; Trusted_Connection=No;UID=<myUID>;PWD=<myPWD>;APP=2007 Microsoft Office system;DATABASE=myDataBase;Network=DBMSSOCN;TABLE=dbo.myTable"
tblDef.SourceTableName = "mySourceTableName"
db.TableDefs.Append tblDef
End Sub
After I close the front end Access database, and upon reopening it, the table fails to open. Even though I have set the Trusted_Connection to "No" in my string, the table still tries to use the Windows Authentication. Also, when I open the table on design view, I see in front of "Description":
ODBC;DRIVER=SQL Server;Server=myServer;APP=2007 Microsoft Office System;DATABASE=myDatabase;Network=DBMSSOCN;Table=dbo.myTable
So obviously Access has not saved the UID and PWD, nor has it saved the instruction on setting the Trusted_Connection to "No".
I insist to get this done with the connection string, and using DSN will not work for the purpose of my application. Help would be greatly appreciated.
You need to add the dbAttachSavePWD-Attribute to the created table to store your credentials with the linked table in Access.
Before appending the tabledef you should put this line of code:
tblDef.Attributes = (tblDef.Attributes Or dbAttachSavePWD)

Read data from a SQL Server database in Visual Basic in MS Access

What's the best way to read data from a SQL Server database in VB from MS Access?
I have a SQL Server database set up and I'm doing the forms etc. in Access. Now I need to read a boolean value and do so in VB.
I'd like to do that without opening a new connection. Is that somehow possible?
You can run a query against a linked table. As far as I know, the usual choice for Boolean in SQL Server is bit:
SELECT dbo_Table1.ID, dbo_Table1.ABoolean
FROM dbo_Table1
WHERE dbo_Table1.ABoolean=True
In MS Access, True displays as -1 and in SQL Server it displays as 1.
The query can also be run through VBA, if that is what you need to do.
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("dbo_table_1")
Do While Not rs.EOF
If rs!ABoolean = True Then
Debug.Print rs!ID
End If
rs.MoveNext
Loop
Or
sSQL = "SELECT ID, ABoolean FROM dbo_table_1 WHERE ABoolean=True"
Set rs = CurrentDb.OpenRecordset(sSQL)
rs.MoveLast
Debug.Print rs.RecordCount
Or
Debug.Print DLookup("Aboolean", "dbo_table_1", "ID=37")

Resources