Creating login procedure for Linking MS Access to Azure SQL server - sql-server

I have an MS Access program which contains a number of SQL tables which are linked to Azure SQL server. Ideally I would like to create a login procedure via a popup form, in which I would ask the user for credentials where I would then update the linked tables and pass through queries with the required data. However I can't get this to work. The code runs fine without error messages, however when I - after executing the procedure - open a form that contains a linked table, I still get the request to login. The idea is to have the login procedure run at the startup screen, with the user not being asked to enter credentials anywhere after successful login.
This is the code I am using for this:
Public Function ConnectToAzureSQL(sServer As String, sDatabase As String, sUserName As String, sPassWord As String)
On Error GoTo Proc_err
Dim con As Object
Dim var As Variant
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strConnect As String
Set db = CurrentDb
Set con = CreateObject("ADODB.Connection")
strConnect = "DRIVER={ODBC Driver 17 for SQL Server}" & _
";Server=sServer" & _
";Database=sDatabase" & _
";UID=sUserName" & _
"PWD=sPassWord".
con.Open strConnect
For Each tdf In db.TableDefs
Debug.Print tdf.Name
If Len(tdf.Connect) Then
tdf.Connect = strConnect
tdf.RefreshLink
End If
Next
con.Close
Proc_exit:
MsgBox ("done")
Exit Function
Proc_err:
Debug.Print Err.Description & " : " & Str(Err.Number)
Resume Proc_exit
End Function

What I forgot to mention is that this method uses the SQL server login method.
Fortunately, I found the answer myself. Should anyone need it, here is the procedure. The disadvantage of this method is that the login data is captured in the connection string. On second thought, I opted for the Azure Active Directory login method with MFA, where no password is stored in your application.
Public Function ConnectToAzureSQL(sServer, sDb, sUID, sPWD As String, bConn As Boolean)
On Error GoTo Proc_err
Dim con As Object
Dim var As Variant
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strConnect As String
Set db = CurrentDb
Set con = CreateObject("ADODB.Connection")
sConnect = "DRIVER={ODBC Driver 17 for SQL Server}" & _
";Server=" & sServer _
& ";Database=" & sDb _
& ";UID=" & sUID _
& ";PWD=" & sPWD
con.Open strConnect
bConn = True
DoCmd.OpenForm "Frm_Bericht"
For Each tdf In db.TableDefs
If Len(tdf.Connect) Then
tdf.Connect = strConnect & ";UID=" & sUID & ";PWD=" & sPWD
Forms!Frm_Bericht.Caption = "Update verbinding naar tabel: " & tdf.Name
tdf.RefreshLink
End If
Next
con.Close
DoCmd.Close acForm, "Frm_Bericht"
Proc_exit:
Exit Function
Proc_err:
Debug.Print Err.Description & " : " & Str(Err.Number)
Resume Proc_exit
End Function

Related

Adding SQL Server Credentials to ADO Connection

I have an Excel workbook that builds a bunch of SQL Update scripts, and then executes them in SQL Server.
I got assistance with the below VBA script. The below works fine if I am running it while logged in as the Admin user Windows. However, when running from a users workstation I run into issues.
The main issue seems to be the user id and password are incorrect. I am not sure where on the below I can add the system administrator (sa) user name and password for SQL Server. Please may I get some assistance.
My code:
Sub test()
Const SERVER = "SRV\ServerName"
Const DATABASE = "Test Database"
Dim fso As Object, ts As Object, ar
Dim ws As Worksheet
Dim iLastRow As Long, i As Long
Dim sql As String, timestamp As String
Dim Folder As String, SQLfile As String, LOGfile As String
Dim t0 As String: t0 = Timer
' query file and log filenames
timestamp = Format(Now, "YYYYMMDD_HHMMSS")
Folder = "\\SRV\Test Folder\"
SQLfile = Folder & timestamp & ".sql"
LOGfile = Folder & timestamp & ".log"
Set fso = CreateObject("Scripting.FileSystemObject")
' read data from sheet into array to build sql file
Set ws = ThisWorkbook.Sheets("UDF Update")
iLastRow = ws.Cells(Rows.Count, "N").End(xlUp).Row
If iLastRow = 1 Then
MsgBox "No data in Column N", vbCritical
Exit Sub
End If
ar = ws.Range("N2").Resize(iLastRow - 1).Value2
' connect to server and run query
Dim sConn As String, conn, cmd, n As Long
sConn = "Provider=SQLOLEDB;Server=" & SERVER & _
";Initial Catalog=" & DATABASE & _
";Trusted_Connection=yes;"
' open log file
Set ts = fso.CreateTextFile(LOGfile)
' make connection
Set conn = CreateObject("ADODB.Connection")
conn.Open sConn
' execute sql statements
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
For i = 1 To UBound(ar)
ts.writeLine ar(i, 1)
.CommandText = ar(i, 1)
.Execute
On Error Resume Next
Next
End With
ts.Close
conn.Close
MsgBox UBound(ar) & " SQL queries completed (ADODB)", vbInformation, Format(Timer - t0, "0.0 secs")
End Sub
If you use Trusted_Connection=yes, the SQL server accepts/rejects you via Windows authentication. It seems that your admin account is accepted by the server while other accounts are not.
Either the other accounts are added to the database server by the database admin or you need to provide credentials and set Trusted_Connection=no (or omit it as that is the defaults)
sConn = "Provider=SQLOLEDB;Server=" & SERVER & _
";Initial Catalog=" & DATABASE & _
";Trusted_Connection=no" & _
";User ID=MyUserID;Password=MyPassword;"
See https://learn.microsoft.com/en-us/sql/ado/guide/appendixes/microsoft-ole-db-provider-for-sql-server?view=sql-server-ver15

Access VBA generated ODBC connection string reverts

I am creating a local MS Access (365) front end application for a SQL Server (Express 2019) DB which is located on a local shared server.
I have a login form that relinks all of the linked tables and views when a user logs in. (This is not primarily for security, so please don't tell me how inadequate this set up is for security - I know.)
Basically, I have a local table in the Access application that lists all the table names that need relinking at login. At login, the current links are deleted, then the code loops through the list of tables and links them according to a connection string that is built in the process, including the UID and the PWD. But when I check on the connection string after login, it doesn't include the login info. My Excel workbook that has a data connection to one of these linked tables cannot connect until I manually edit the string in the Linked Table Manager.
Below is the code for the login process:
Private Sub cmdConnect_Click()
Dim db As Database
Dim tdf As TableDef
Dim rst As Recordset
Dim rst1 As Recordset
Dim strServer As String
Dim strDB As String
Dim strTable As String
Dim strConnect As String
Dim strMsg As String
Dim strPass As String
Dim strPrimary As String
On Error GoTo HandleErr
Set db = CurrentDb
strPass = DLookup("[Password]", "tblUsers", "[User] = '" & Me.txtUser & "'")
If StrComp(Me.txtPwd, strPass, vbBinaryCompare) <> 0 Then
strMsg = "Incorrect Username or password!"
GoTo ExitHere
End If
' Create a recordset to obtain server object names.
Set rst = db.OpenRecordset("tblSQLTables", dbOpenSnapshot)
If rst.EOF Then
strMsg = "There are no tables listed in tblSQLTables."
GoTo ExitHere
End If
'Assign the current user in table
Set rst1 = db.OpenRecordset("tblUsers", dbOpenDynaset, dbSeeChanges)
With rst1
.MoveFirst
Do Until rst1.EOF
.Edit
Select Case !user
Case Me.txtUser
!Current = -1
Case Else
!Current = 0
End Select
.Update
.MoveNext
Loop
End With
strConnect = "ODBC;Driver={ODBC Driver 17 for SQL Server};Trusted_Connection=No;DSN=SQL1;UID=" _
& Me.txtUser & ";PWD=" & Me.txtPwd & ";"
'delete all existing linked tables
Call deleteLinks
' Walk through the recordset and create the links.
Do Until rst.EOF
strServer = rst!SQLServer
strDB = rst!SQLDatabase
strTable = rst!SQLTable
' Create a new TableDef object.
Set tdf = db.CreateTableDef("dbo_" & strTable, 0, "dbo." & strTable, strConnect & "Server=" & strServer & ";Database=" & strDB & ";")
' Set the Connect property to establish the link.
db.TableDefs.Append tdf
Debug.Print tdf.Connect
Set tdf = Nothing
rst.MoveNext
Loop
strMsg = "Tables linked successfully."
rst.Close
Set rst = Nothing
Set tdf = Nothing
Set db = Nothing
DoCmd.Close acForm, Me.name
DoCmd.OpenForm "frmStart"
ExitHere:
MsgBox strMsg, , "Link SQL Tables"
Exit Sub
HandleErr:
Select Case Err
Case Else
strMsg = Err & ": " & Err.Description
Resume ExitHere
End Select
End Sub
Private Sub deleteLinks()
Dim rst As Recordset
Dim db As Database
Dim tdf As TableDef
Set db = CurrentDb
For Each tdf In db.TableDefs
If tdf.name Like "dbo_*" Then
DoCmd.DeleteObject acTable, tdf.name
End If
Next
End Sub
When I look at the immediate window to see the printed tdf.connect it gives me:
ODBC;DRIVER=ODBC Driver 17 for SQL Server;SERVER=RNC1SQL\SQLEXPRESS;UID=****;PWD=*************;Trusted_Connection=No;APP=Microsoft Office;DATABASE=RNCMasterfile;
But when I look at the connection string in the Linked Table Manager, I get the following:
DRIVER=ODBC Driver 17 for SQL Server;SERVER=RNC1SQL\SQLEXPRESS;Trusted_Connection=No;APP=Microsoft Office;DATABASE=RNCMasterfile;
The odd thing is I can access and use the tables in Access, but I have Excel spreadsheets with connections to Access queries based on the linked tables and they don't work if the connection string doesn't contain the login info.
Any ideas to programmatically force the connection string to contain this info?
Try linking your tables using DoCmd.TransferDatabase instead.
DoCmd.TransferDatabase acLink, "ODBC Database", [your_cnn_string], acTable, [source_tbl_name], [linked_table_name], , True
The last option in TranserDatabase is StoreLogin.
I use this in my own apps.
Read about TransferDatabase here.

Connect to SQL Server local database

I'm writing a macro in Microsoft Excel that makes an update in a table of my local SQL Server database,.
My connection string:
sConnect = "Driver={SQL Server};Data Source=(localdb)\MSSQLLocalDB;Database=Scrape;"
I get this error:
Data source name not found and no default driver specific
How do I write the connection string?
Ok, this should be pretty simple. See the link below.
https://www.erpsoftwareblog.com/2017/01/microsoft-excel-connections-sql-databases/
Also, check this out.
https://www.connectionstrings.com/sql-server/
Finally, to update a SQL Server table with Excel/VBA code, do the following.
Sub UpdateMyTable()
Dim cnn As ADODB.Connection
Dim uSQL As String
Dim rngName As Range
Set cnn = New Connection
cnnstr = "Provider=SQLOLEDB; " & _
"Data Source=MyServer; " & _
"Initial Catalog=MyDB;" & _
"User ID=User;" & _
"Password=Pwd;" & _
"Trusted_Connection=No"
Set rngName = ActiveCell
cnn.Open cnnstr
uSQL = "UPDATE MyTable SET Field = 1 WHERE Field = ' " & rngName & " ' "
'Debug.Print (uSQL)
cnn.Execute uSQL
cnn.Close
Set cnn = Nothing
Exit Sub
End Sub
Post back, with specific details, if you have issues with this code. Thanks.

Not able to connect with database

I am new in Excel VBA. I have ready made code which is written for machine of IP address 199.63.106.70. Now i want same code to be run for another machine 199.56.122.155. I have install MS SQL server 2008 R2 on new machine. I also checked with connection using Data Connection Wizard. Data is Fetched.
But when i try to get data by click on button it display error message "Error in Process".
Controller is Jumping from oCon.Open
How can this error will be solved? is format of connection string is correct?
User Id and Password is windows login credentials which is used in string.
Dim oCon As ADODB.Connection
Dim oRS As ADODB.Recordset
Dim rowcounter As Long
On Error GoTo errhandler
rowcounter = 2
Set oCon = New ADODB.Connection
oCon.connectionstring = "Driver={SQL Server};Server=199.63.106.70;Database=dashboard;User Id=dashboardadmin;Password=passwrd;"
oCon.Open
Set oRS = New ADODB.Recordset
oRS.ActiveConnection = oCon
oRS.Source = "SELECT HourlyReadingTimestamp, Hourlyreading,cost FROM MeterConsumptioNDetail where meterid=" & Range("J5").Value & " and HourlyreadingTimestamp between '" & Range("K5").Value & "' and '" & Range("L5").Value & " 23:59:59' order by HourlyreadingTimestamp"
oRS.Open
While Not oRS.EOF
Range("A" & rowcounter).Value = oRS.Fields(0).Value
Range("B" & rowcounter).Value = oRS.Fields(1).Value
Range("C" & rowcounter).Value = oRS.Fields(2).Value
rowcounter = rowcounter + 1
oRS.MoveNext
Wend
oCon.Close
If Not oRS Is Nothing Then Set oRS = Nothing
If Not oCon Is Nothing Then Set oCon = Nothing
MsgBox ("Data fetched successfully")
Exit Sub
errhandler:
MsgBox ("Error in process!")
End Sub
The connection string is incorrect if you want to use Integrated Security (Windows Login) use:
Driver={SQL Server};Server=199.63.106.70;Database=dashboard;Trusted_Connection=Yes;
The driver will deal with authentication based on the user running the process.

Excel VBA to SQL Server without SSIS

Excel problem: User clicks a button and VBA parses an input file, putting data into cells in the spreadsheet. Then she mails copies of the spreadsheet to people who do work with the data.
I am to replace this with SSRS or ASP or Sharepoint displaying the data from SQL Server.
In order to work on this without interrupting the current process, I'd like to have the Excel VBA, each time it writes a row to the spreadsheet, also insert it into the SQL Server DB via stored proc.
I can have it write the row in CSV to a file for later SSIS import, but I'd rather go direct to the DB.
I know how to do it in VB.Net but I've never written data in VBA (often read data into recordset but not written).
I'd prefer to pass the values as params to a stored proc, but I could generate the slower INSERT command for each row if I have to.
From VBA, the easiest data-access library to use is ADO. Add a reference to "Microsoft ActiveX Data Objects Library" so that you can use the ADODB.* objects.
To execute a stored proc (which in your case will add a record to a table), you could do it:
...the lazy way (creating SQL statements directly, without using Parameter objects; this is prone to SQL-injection hacks):
Public Sub AddFoo _
( _
strServer As String, _
strDatabase As String, _
strUsername As String, _
strPassword As String, _
lFooValue As Long _
)
' Build the connection string
Dim strConnectionString As String
strConnectionString = "Driver={SQL Server}" _
& ";Server=" & strServer _
& ";Database=" & strDatabase _
& ";UID=" & strUsername _
& ";PWD=" & strPassword
' Create & open the connection
Dim oConnection As Connection
Set oConnection = New Connection
oConnection.ConnectionString = strConnectionString
oConnection.Open
' Build the SQL to execute the stored procedure
Dim strSQL As String
strSQL = "EXEC AddFoo " & lFooValue
' Call the stored procedure
Dim oCommand As Command
Set oCommand = New Command
oCommand.CommandType = adCmdText
oCommand.CommandText = strSQL
oCommand.ActiveConnection = oConnection
oCommand.Execute
oConnection.Close
End Sub
...or the correct way (which deals with encoding of all parameters, and is thus not prone to SQL-injection hacks - either deliberate or accidental):
Public Sub AddFoo _
( _
strServer As String, _
strDatabase As String, _
strUsername As String, _
strPassword As String, _
lFooValue As Long _
)
' Build the connection string
Dim strConnectionString As String
strConnectionString = "Driver={SQL Server}" _
& ";Server=" & strServer _
& ";Database=" & strDatabase _
& ";UID=" & strUsername _
& ";PWD=" & strPassword
' Create & open the connection
Dim oConnection As Connection
Set oConnection = New Connection
oConnection.ConnectionString = strConnectionString
oConnection.Open
' Build the SQL to execute the stored procedure
Dim strSQL As String
strSQL = "EXEC AddFoo " & lFooValue
' Create the command object
Dim oCommand As Command
Set oCommand = New Command
oCommand.CommandType = adCmdStoredProc
oCommand.CommandText = "AddFoo"
' Create the parameter
Dim oParameter As Parameter
Set oParameter = oCommand.CreateParameter("foo", adParamInteger, adParamInput)
oParameter.Value = lFooValue
oCommand.Parameters.Add oParameter
' Execute the command
oCommand.ActiveConnection = oConnection
oCommand.Execute
oConnection.Close
End Sub
How do you read data with VBA?
If you use ADO recordsets: Have a look at the ADODB.Command class; this allows you to execute SQL or stored procedures and pass parameters to it (Google for ado command example).
If you use DAO recordsets: The Execute method of your DAO database allows you execute SQL statements.
In the long run, people are finally beginning to accept a better way: automation (not a button click) reads the file directly into the DB (SSIS), and people who need the data look at a report instead of an e-mailed Excel file.

Resources