Excel VBA SQL Data - sql

I have a small excel program.
I would like to be able to use this program to update a SQL table.
What would be the function to say update line 2 in SQL table Test in Database ABC
Thanks

First of all you need to add a reference to the ActiveX Data Objects library, which contains the set of objects that allow you to do database access - in the Excel Visual Basic editor, go to Tools|References... In the dialog box, scroll down until you find Microsoft ActiveX Data Objects 2.8 Library. Check the box next to the library name.
VBA References dialog with ADO library checked http://philippursglove.com/stackoverflow/adoreference.png
Your code to update the database should then look something like this (using the SQL from JohnK813's answer):
'Declare some variables
Dim cnn As ADODB.Connection
Dim cmd As ADODB.Command
Dim strSQL As String
'Create a new Connection object
Set cnn = New ADODB.Connection
'Set the connection string
cnn.ConnectionString = myDatabaseConnectionString 'See http://connectionstrings.com if you need help on building this string for your database!
'Create a new Command object
Set cmd = New ADODB.Command
'Associate the command with the connection
cmd.ActiveConnection = cnn
'Tell the Command we are giving it a bit of SQL to run, not a stored procedure
cmd.CommandType = adCmdText
'Create the SQL
strSQL = "UPDATE Test SET YourField = NeValue WHERE IDField = 2"
'Pass the SQL to the Command object
cmd.CommandText = strSQL
'Open the Connection to the database
cnn.Open
'Execute the bit of SQL to update the database
cmd.Execute
'Close the connection again
cnn.Close
'Remove the objects
Set cmd = Nothing
Set cnn = Nothing

I see you have other questions open that deal with actually connection to the SQL Server, so I won't add any more to that discussion.
Relational database tables don't think of things as being in a certain order, so you can't really say that a certain record is "record 2" or "line 2" just because you added it to the table second. Unless of course you use a field to create an ID number that increments with each new record added.
Then you can access that record by saying
UPDATE Test SET YourField=NewValue WHERE IDfield=2
Here's more information on the UPDATE command, if you need it.

Related

Populate results from SQL Server using Recordset in MS Access using VBA code

I am not sure how I can put the results from Record Set into a query or result pane in MS Access using VBA code. The results in the recordset are from SQL Server, so I want to display the results in MS Access. I need to do it this way, is that possible? I would think I need to do something where are x's are.
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strConnString As String
strConnString = "Provider=SQLNCLI11;Server=SRV;Database=Staging;Trusted_Connection=yes;"
Set conn = New ADODB.Connection
conn.Open strConnString
Set rs = conn.Execute("Select * from MSAccess_APP_ComplianceDashBoard ")
XXXXXXXXXXXXXXXXXX
rs.Close
Assuming a continues form,or a multiple items form?
In the forms on-load event just go:
me.ReocrdSource = "Select * from MSAccess_APP_ComplianceDashBoard"
It is of course assumed that you have a linked table to SQL server with the above name.
In fact, you can set the forms record source in design mode and as a result you need zero lines of code.
So, setup a linked table - you not need to write any code.
Create a pass-through query, put your connection string there, and do whatever you your needs over this query.

How Can I Limit an .OpenDataSource in Word Mail Merge to Only 1 Record Using VBA?

Word 2013, SQL Server 2014
I have a Word Mail Merge template that was originally created for a licensing application that uses an .ini file and an Excel file to generate one certificate from a dataset of many.
I want to make the Word Template work on it's own. I was able to wire up a .udl file to make a connection to the database but it gives me all the tables, then I pick one, then it gives me a document for each row in that table when I only need one.
How can I limit/filter the document that comes from the template to only use a specific table and a specific row (license_id) I request?
Sub AutoNew()
'THIS RETURNS ALL ROWS AFTER I PICK A TABLE
With ThisDocument.MailMerge
.OpenDataSource Name:="C:\Users\or0146575\Desktop\xxx.udl"
.Execute
End With
End Sub
I would wire up the below code to only return 1 row if I knew how.
Dim sql As String
sql = "SELECT full_name, BigLicenseType, LicNosDisplay, expiration_date FROM OpCerts WHERE person_id= 30012"
I decided to take a totally different route and hope it doesn't detract from my points.
Using a datasource file like a .udl or .odc was bringing back all records AND required selecting the table at runtime and I couldn't get the sql to work.
I decided to make the connection with good old ADODB (Microsoft ActiveX Data Objects 2.5 Library in Tools > References) and assign the values to the mailmerge fields or DOCVARIABLE fields or Bookmarks, which ever will work. No sense in using mailmerge for just one record. I hope this helps someone.
Sub AutoNew()
Dim strWhat As String
strWhat = InputBox("Enter License ID", "OpCert Wall Certificate")
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
conn.ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=DWS_Licenses;Data Source=WPDHSCLR16C"
conn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandText = "SELECT full_name, BigLicenseType, LicNosDisplay, expiration_date FROM OpCerts WHERE person_id=" & CInt(strWhat)
Dim rs As ADODB.Recordset
Set rs = cmd.Execute() 'Execute stored procedure.
'THIS WILL BE CHANGED TO BOOKMARK(S) PROBABLY IF DOCVARIABLES DOESN'T WORK
ActiveDocument.Variables("expiration_date").Value = rs(3)
'PUT full_name, BigLicenseType, LicNosDisplay TAGS HERE
rs.Close
Set rs = Nothing
Set cmd = Nothing
conn.Close
Set conn = Nothing
End Sub

How Do I Return Multiple Recordsets from SQL Stored Procedure in Access 2010

I’ve created a pass-through query in Access which executes a stored procedure that searches for a string across all tables in my SQL database. The stored procedure on the SQL server runs as expected, returning multiple Recordsets that contain the value of my search string. However, when I double-click on the pass-through query in Access, in Datasheet View I see the results of only one Recordset. Since it appears that Access is not designed to handle multiple result sets, then how do I use VBA in Access to accomplish this?
exec sqlsp_searchalltables #Tablenames='', #SearchStr='%motion%'
I'm not quite sure how you expected to "bind" your form to the multiple recordsets returned by the stored procedure, but as far as I know the only way to deal with SQL Server stored procedures that return multiple recordsets is to use ADODB.Recordset objects.
(Don't be misled by the "Recordset.NextRecordset Method (DAO)" article here. If you try that approach you will receive run-time error '3847': "ODBCDirect is no longer supported. Rewrite the code to use ADO instead of DAO.")
For example, I have a SQL Server stored procedure that returns two recordsets and I create a pass-through named [dbo_myMultiRsSp_1] to call it:
EXEC dbo.myMultiRsSp #id=1
If I open it in Datasheet View by double-clicking it I see the results of the first recordset.
If I want to process all of the recordsets in VBA I cannot use the pass-through query directly, but I can use its .Connect and .SQL properties as follows
Option Compare Database
Option Explicit
Sub MultiRsSpTest()
Dim cdb As DAO.Database
Dim con As ADODB.Connection, cmd As ADODB.Command
Dim r1 As ADODB.Recordset, r2 As ADODB.Recordset
Set cdb = CurrentDb
Set con = New ADODB.Connection
' connect directly to the SQL Server
' (by using the .Connect property of the pass-through query)
con.Open Mid(cdb.QueryDefs("dbo_myMultiRsSp_1").Connect, 5) ' omit "ODBC:" prefix
Set cmd = New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdText
cmd.CommandText = cdb.QueryDefs("dbo_myMultiRsSp_1").SQL
Set r1 = cmd.Execute
Debug.Print
Debug.Print "First Recordset:"
Do Until r1.EOF
Debug.Print r1(0).Value
r1.MoveNext
Loop
Set r2 = r1.NextRecordset
Debug.Print
Debug.Print "Second Recordset:"
Do Until r2.EOF
Debug.Print r2(0).Value
r2.MoveNext
Loop
' r1.Close (happens implicitly)
Set r1 = Nothing
r2.Close
Set r2 = Nothing
Set cmd = Nothing
Set con = Nothing
Set cdb = Nothing
End Sub

Execute Query from Access via Excel Query in VBA

Access has saved a query that was designed with the query builder called 'myQuery'. The database is connected to the system via ODBC connection. Macros are all enabled.
Excel Has makes a ADODB connection to connect to the database via
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "MyDatabase.accdb"
End With
Usually you would go ahead and just write your SQL, which is perfectly fine and then just do something like
Dim sqlQuery As String
sqlQuery = "SELECT * FROM myTable"
Set rs = New ADODB.Recordset
rs.Open sqlQuery, con, ...
But I want to access the query that I saved in the access database. So how do I call the saved query in the database that I just connected.
Tried already
con.Execute("EXEC myQuery") but that one told me it could not be find myQuery.
rs.Open "myQuery", con but that one is invalid and wants SELECT/etc statements from it
I think you can treat it like a stored procedure.
If we start right before Dim sqlQuery As String
Dim cmd as new ADODB.Command
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "myQuery"
cmd.ActiveConnection = con
Set rs = cmd.Execute()
Then pickup your recordset work after this.
You were nearly there:
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "z:\docs\MyDatabase.accdb"
End With
con.Execute "MyQuery"
Just leave out Exec.
You can add parameters, too, this is a little old, but should help: update 2 fields in Access database with Excel data and probably a Macro
I was able to run an update query that was already saved in Access using:
Connection.Execute "My_Update_Query_Already_Saved_In_Access", adExecuteNoRecords, adCmdStoredProc
This gave me errors until I replaced spaces in the query name with underscores in both the Access database and the execute statement.
This is sort of a hack job, but you can query a query. That is, replace your sql string with the following:
sqlQuery = "SELECT * FROM QueryName;"
Before running this, one must ensure that the Access Database has been saved ie. press Ctrl+S (it is not sufficient that the query was run in Access).
Long time since this thread was created. If I understand it correctly, I might have something useful to add. I've given a name to what the OP describes, that being the process of using SQL from a query saved in an ACCDB to run in VBA via DAO or ADOBD. The name I've given it is "Object Property Provider", even with the acronym OPP in my notes, and for the object name prefix/suffix.
The idea is an existing object in an ACCDB (usually a query) provides a property (usually SQL) that you need to use in VBA. I slapped together a function just to suck SQL out of queries for this; see below. Forewarning: sorry, but this is all in DAO, I don't have much use for ADODB. Hope you will still find the ideas useful.
I even went so far as to devise a method of using/inserting replaceable parameters in the SQL that comes from these OPP queries. Then I use VBA.Replace() to do the replacing before I use the SQL in VBA.
The DAO object path to the SQL of a query in an ACCDB is as follows:
mySqlStatement = Access.Application.CurrentDb.QueryDefs("myQueryName").SQL
The way I use replaceable parameters is by evaluating what needs to be replaced, and choosing an unusual name for the paramater that cannot possibly exist in the real database. For the most part, the only replacements I've made are field or table names, or the expressions of WHERE and HAVING clauses. So I name them things like "{ReplaceMe00000001}" and then use the Replace() function to do the work...
sqlText = VBA.Replace(sqlText, "{ReplaceMe00000001}", "SomeActualParameter")
...and then use the sqlText in VBA. Here's a working example:
Public Function MySqlThing()
Dim sqlText as String
Dim myParamater as String
Dim myExpression as String
'Set everything up.
sqlText = getSqlTextFromQuery("myQuery")
myParameter = "{ReplaceMe00000001}"
myExpression = "SomeDateOrSomething12/31/2017"
'Do the replacement.
sqlText = VBA.Replace(sqlText, myParameter, myExpression)
'Then use the SQL.
db.Execute sqlText, dbFailOnError
End Function
Function getSqlTextFromQuery(ByVal oppName As String) As String
Dim app As Access.Application
Dim db As DAO.Database
Dim qdefs As DAO.QueryDefs
Dim qdef As DAO.QueryDef
Dim sqlText As String
Set app = Access.Application
Set db = app.CurrentDb
Set qdefs = db.QueryDefs
Set qdef = qdefs(oppName)
oppGetSqlText = qdef.SQL
End Function

Connect to a linked table

Connect to a linked table with code.
I have some linked tables from a SQL-server; they are linked with an ODBC connection. The password is not saved with the connection. When I am double clicking on the table in Access table-view I get a prompt for username and password. After entering the password I can view the data in the table.
My problem is when I try to access the table with code before having opened it in this way. What I try to do is to use ADODB to open a recordset with data from the linked table, like:
Dim rst as new ADODB.Recordset
Dim sql as string
Sql = “SELECT * FROM LinkedTable”
rst.Open sql, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
Running this code without having access the table before will generate this error: Error# -2147467259, ODBC: connection to dns-name failed.
So, my question is, are there any way to connect to the database with code that can be run when the database is opened? This would also help the users as they would not have to remember a password to the SQL-server.
It seems that you are mixing 2 technologies that might not work together, ie linked tables through ODBC and ADODB recordsets. Have you tried to open DAO recordsets on your linked tables?
Dim rst as DAO.Recordset
Dim sql as string
Sql = “SELECT * FROM LinkedTable”
set rst = currentDb.openRecordset(sql,<your parameters>)
You could of course use ADODB recordsets through 2 ADODB connections, one to your access file, the other one to your SQL server:
Dim rsSQL as ADODB.recordset, _
rsACCESS as ADODB.recordset, _
connectionSQL as ADODB.connection, _
connectionACCESS as ADODB.connection
set connectionSQL = New ADODB.connection
set connectionACCESS = New ADODB.connection
connectionSQL.properties(...) = enumerate your SQL parameters
connectionACCESS.properties(...) = enumerate your ACCESS parameters (use currentproject.accessConnection if your access tables are local tables only)
set rsSQl = New ADODB.recordset
set rsACCESS = New ADODB.recordset
rsSQL.open "SELECT * FROM ...", connectionSQL, <other parameters>
rsACCESS.open "SELECT * FROM ...", connectionACCESS, <other parameters>
Linking ADO recordsets to forms and comboboxes in Access is possible. But, when creating forms, this technology has to be mainly managed through VBA code (you will have to write 'on open' events such as set me.recorset = ...), while the standard "linked tables" technology can be easily used through the user-friendly 'form-design' interface.
You can use a connection string in your code, it is easy enough, seeing you are already using ADO: http://www.connectionstrings.com/
You will need to find out which version of SQL Server you are linking to.