I have been able to run the following VBA code (within Excel) using my own Windows account to pull data from a SQL server:
Sub GetData()
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim ConnectionString As String
ConnectionString = "Provider=SQLOLEDB; Data Source = ServerName;Trusted_connection=yes;"
However, now I'm at the point where I have additional users I would like to provide the file so that they can run the VBA and refresh the data (among other things). I have a generic Windows account that I would like to use, however the solution is not as simple as changing the connection string as shown below because the password is not a SQL server password but rather a Windows password.
ConnectionString = "Provider=SQLOLEDB; Data Source = ServerName;UID=user;PWD=password"
I've read about things such as "impersonation", but haven't been able to figure it out. Is there any reasonably simple solution to make this work? Much thanks!
Related
I have a MS Access application that has been in use for at least 10 years. Recently I moved my work to a new development machine with Office 365 and SQL Server Express 2019 installed. The machine OS is Windows 10 Pro. In my old machine my application would run just fine. There is a query using a stored procedure that retrieves a piece of data from a table in the SQL Server backend. I call this procedure using a ADODB recordset based on the stored procedure output. All my calls use a connection string based on an ODBC DNS. This connection string works fine on the new machine when relinking tables to the SQL Server backend, but when I use it in the ADODB connection I get an error "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified". On the old Windows 7 development machine this ran fine. It also runs on the client's machines which are Windows 10 and Office 365. The code that raises the error follows. The error occurs at the open connection line. The connection string is: ODBC;DSN=VROM;Trusted_Connection=Yes;APP=2019 Microsoft Office system;DATABASE=VROM1.
Set con = New ADODB.Connection
con.ConnectionString = DLookup("Link", "tblLinkData", "Use = True")
con.Open
Set rs = New ADODB.Recordset
My question "Is there a setting in SQL Server that could be causing this error?". As far as I can tell both systems are set up the same, but there is obviously something different between the two. Is there another reason this could be working on one system and not another?
Hum, where to start?
Ok, first up, if you using the ODBC panel to create a ODBC connection, then you NEVER were actually using a ADO connection in that DSN config = ODBC!!!!
That means you been feeing ADO a ODBC connection string. you can do this, but at least lets be aware of what is going on.
Next up:
Are you running the SQL browser service? You MUST do that now!. Don't know if you installed a later version of SQL SERVER, but a few versions ago you will find now that you MUST run the browser service.
This one:
The reason of course is that you can (may) have multiple instances of sql server running, and the default instance (SQLEXPRESS) now MUST BE specified. As noted older instances did NOT have this requirement. And to "resolve" the multiple instances, you now must run the SQL browser service. As noted, this was NOT a requirement in the past - it is now. That browser service is what connects the IP/server name to the instance, and you now in most cases have to run this.
There are exceptions, but you don't want much pain.
Next up:
For a VERY long time, it is recommended for Access linked tables you use a DSN-less connection. that way then at deployment time to all workstations, you don't need to setup a DSN on each workstation.
And if you link Access tables using a FILE dsn (not system or user), then upon the table link process, access BY DEFAULT converts all table links to DSN-less. That means once you linked, then you could even delete the DSN - you do NOT need it anymore.
Again: this ONLY holds true if and when you create a FILE dsn, and use that to link the tables. So, that takes care of the DSN-less linked tables.
Note that if you were to modify the DSN, you would have to link, since I just told you by default access creates + uses dsn-less links (assuming you used a FILE dsn to link).
now, you CAN of course use that SAME dsn for ADO, but that means you are feeding ADO a ODBC driver connection!!!
If you want to create a real ADO connection, then you would/could/should say use this:
Dim strCon As String
strCon = "Provider=SQLOLEDB;;Initial Catalog=TEST4; " & _
"Data Source =.\SQLEXPRESS;Trusted_Connection=yes"
Dim conn As New ADODB.Connection
conn.ConnectionString = strCon
conn.Open
Dim rst As New ADODB.Recordset
rst.Open "SELECT * from tblHotels", conn
Do While rst.EOF = False
Debug.Print rst!HotelName
rst.MoveNext
Loop
Now now how I used a "." for localhost. That could be replaced with (local), or in fact the computer (server) name say like this:
strCon = "Provider=SQLOLEDB;;Initial Catalog=TEST4; " & _
"Data Source =ALBERTKALLAL-PC\SQLEXPRESS;Trusted_Connection=yes"
Next up, make sure you enabled the TC/IP connections.
here:
However, since your case all along you actually been using ODBC driver with ADO, then I would not rock the boat.
But, check your settings as per above.
Since linked tables, and quite much everything else is DAO + odbc?
then I would probably not introduce ADO into that application for JUST calling + using sql server store procedures.
I as a general rule would say use this;
with currentdb.tabledefs("qryPT")
.sql = "exec MyProcName"
.execute
end with
Or, if it is to return data, then I would use this:
dim rst as DAO.RecordSet
with currentdb.tabledefs("qryPT")
.sql = "exec MyProcName"
set rst = .OpenRecordSet()
end with
So, I am hard pressed to find a reason to use ADO. Now of course since you been using ADO, then I guess I would continue to do so.
but, check the browser settings. And if the tables were linked using a FILE dsn, then they are dsn-less.
You could try feeding the ADO connection a existing connection from a existing linked table.
eg:
strCon = CurrentDb.TableDefs("dbo_tblHotels").Connect
strCon = Mid(strCon, 6)
Dim conn As New ADODB.Connection
conn.ConnectionString = strCon
conn.Open
Skipping the first 6 chars skips this part:
ODBC;DRIVER=SQL Server;SERVER=ALBERTKALLAL-PC\SQLEXPRESS;
UID=AlbertKallal;Trusted_Connection=Yes;APP=Microsoft Office 2010;
DATABASE=Test4;Network=DBMSLPCNM
So once again we are feeding ADO ODBC connection string.
(of course above connection string is one line).
WE use a spreadsheet to collect and distribute various data into sheets for company use.
Use were using MS Excel 2013 and an early version of MS SQL Server
Which worked perfectly without any errors, here is the code from our VBA file:
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
MyConStr = "Provider=SQLOLEDB;Data Source=sqlserver\SQL;Initial Catalog=MYDB;user id=sa;password=Mon87653day9856"
con.Open MyConStr
Now we have upgraded to SQL Server 2017, and we get the error.
Unable to complete login process due to delay in opening server connection
I have tried looking at pipes and changing the order, still get the error.
I have downloaded the new MSOLEDBSQL driver and still get the error.
I have tried the trusted connection and time out settings and still get the error.
Any one got any ideas?
Edited
I am not sure if this was a mistake in your posting or in your original code, but you are missing the terminating quotation marks at the end of your connection string (I would put this in the comments but don't have a high enough reputation).
Also, in the past, I would have to specify the IP address of the server in order to establish the connection to the server. May be worth a try.
Update: This is fixed thanks to some great help here. If you're having similar issues do the following:
Enable ALL exceptions before running
Figure out the exact error you're getting when trying to connect
Make sure that all users on SQL side have a user assigned to a login for that specific database
I've got a very nice program I've made that I'm ready to start pushing out for testing. The problem is that when I coded all of this I simply used the Integrated Security which uses my windows login to connect to the SQL Server. That worked fine as I'm a sysadmin on that whole server, including the database in question.
Now I'm ready to push this out to other users and I need to change the code to either use my login for all users (hard coded to the connection string) or use a new login specifically for that database.
I've used the following connection string and it won't work! I've also added the server to the data connections section of the server explorer but I guess I don't know how to tell the program to use that connection in my code.
I've obfuscated the password in the code below but it's written out in my code. No errors or anything when running - it just doesn't connect or pull data.
Thoughts? Thanks!
Dim strSQLConn As String = ("Server=Hertz1455;Database=AbsenceApplication;User ID=hac0421;Password=********")
Update - hertz1455 is the server name, there isn't a port that I need to use. Below is the rest of the code for when the program starts. I've also commented on some answers with the error I'm getting.
Dim strSQLConn As String = "Fleet_PTO.My.MySettings.AbsenceApplicationConnectionString"
Dim strQuery As String
Dim sqlSQLCon As SqlConnection
sqlSQLCon = New SqlConnection(strSQLConn)
Dim cmd As SqlCommand = New SqlCommand("SELECT person FROM tblSupervisor", sqlSQLCon)
sqlSQLCon.Open()
Dim myDA As SqlDataAdapter = New SqlDataAdapter(cmd)
Dim myDataTable As DataTable = New DataTable
myDA.Fill(myDataTable)
sqlSQLCon.Close()
When I change the strSqlConn to the string below, everything works just fine.
Dim strSQLConn As String = ("Data Source=Hertz1455;Initial Catalog=AbsenceApplication;Integrated Security=True")
We can only guess since the question is a bit unclear without any exceptions or warning messages.
Try this:
Create a new text file anywhere. (say Desktop)
Rename the extension to udl and open the file.
You should be seeing window.
Test your connection, see if you can connect.
Lat94 might be correct with the Server=Hertz:1455 part although it's not the default MSSQL port.
Also check your server's firewall, it might be blocking the connection request. You might be getting an exception (like connection forcefully rejected) but it might not be popping up. Check exception settings, enable everything since you find a relative clue.
Note:
Dear future viewer, please follow the comments.
Perhaps you should add the driver you're using in order to get it done, like:
Dim strSQLConn As String = ("Server=SQLOLEDB;Server=Hertz1455;Database=AbsenceApplication;User ID=hac0421;Password=********")
Is "1455 at Server=Hertz1455 the port number? Shouldn't it be Server=Hertz:1455 in that case?
Check this link for more info. It is in C#, but it will not be a problem.
I'm working in an environment where users have two separate accounts. One logs them into their host machine, and then they use a separate one to access a VM with special software.
One of the VMs has an SQL database that records alarms that they would like to be able to access from excel installed on the host machine. I've tested the following code out and it works fine on my test VM, but it fails from the host VM.
Sub Alarm_Query()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
With cn
.ConnectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=SERVER;INITIAL CATALOG=A2ALMDB;INTEGRATED SECURITY=sspi;"
.Open
End With
I know that the reason is because the user name being used to log into the host machine does not (and should not) have the credentials required to access the SQL database. I've tried changing it to
Sub Alarm_Query()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
With cn
.ConnectionString = "PROVIDER=SQLOLEDB;DATA SOURCE=SERVER;INITIAL CATALOG=A2ALMDB;"
.Properties("Prompt") = 2
.Open
End With
Which does let me enter a unique username/password but when I give it the correct domain account I get an error message saying
"Login Failed for user.... Reason:Attempting to use an NT account name
with SQL Server Authentication
.
Is there a way to prompt the user running my macro to provide a username/password using windows authentication separate from what they are logged in as?
If not it seems like my options are to
1) Set it up for them to run it from within the VMs (Possible, but inconvenient)
2) Hard code an SQL username/password with read-only access to the database (Don't like the idea of this at all)
3) Add the host's username on an individual basis to have access to the SQL database (not really feasible)
4) Add the entire user group for the host's usernames to have read-only access to the SQL database (tolerable, but opening up access to a much wider base than I'd prefer)
Windows Authentication will not let you enter a user+password - that's the whole point: Windows does the authentication. If you want a user+password, you need to set up an SQL user.
Make sure whatever user is logged in on your host VM has access to the SQL instance, and it should just work.
Unrelated side note, this:
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Defeats the purpose of this:
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
If you want late-binding, you should declare cn and rs as Object variables. Otherwise there's no point using CreateObject - just New it up, the project necessarily has a reference to ADODB if these declarations compile!
I have to connect a Word Document to a SQL Server with VBA in order to read and write records. Now, I'M really confused as of the many different ways to connect to a database. There's ADO, ODBC and so on. I've seen very different ways of connecting a SQL Server database.
A co-worker wants me to use ODBC.
So: What is the best way to connect to a SQL Server database using ODBC in Office VBA?
An example for a SELECT and INSERT statement would also be appreciated.
Edit: Isn't there something like "System.Data.SqlClient.SqlConnection" and "System.Data.SqlClient.SqlCommand" in VB .Net/C#?
This example uses ODBC:
'Microsoft ActiveX Data Objects x.x library
Dim cn As New ADODB.connection
Dim rs As New ADODB.recordset
cn.Open "DRIVER={SQL Server};SERVER=srv;" & _
"trusted_connection=yes;DATABASE=test"
rs.Open "SELECT * FROM table_1", cn
This example uses OleDb
'Microsoft ActiveX Data Objects x.x library
Dim cn As New ADODB.connection
Dim rs As New ADODB.recordset
cn.Open "Provider=sqloledb;Data Source=srv;" & _
"Initial Catalog=Test;Integrated Security=SSPI;"
rs.Open "SELECT * FROM table_1", cn
See also: http://www.connectionstrings.com/sql-server-2008
The reason your co-worker probably wants you to use ODBC is that your company delivers standardized ODBC connections for every single workstation.
The good thing here is that you don't have to worry about connection properties except login/password, because it's all set. Imagine ODBC acting between a software (word) and a server, it makes things alot easier when it comes to changes in your company. (Server address may change and IT is able to change settings of ODBC without the end user even knowing about it)
Beste would be to talk to your co-worker and ask about his concerns. Another reason could be that ODBC might be faster than the ado one. I made this experience, too.