update 2 fields in Access database with Excel data and probably a Macro - vba

In my master database I have a small table that contains two dates and ID numbers. I use this table for updating queries and do some analysis. The table looks like this:
Number | Date
1 | 09.07.2012.
2 | 10.07.2012.
The thing I would like to do is to have an excel file that pops-up a form after startup.
That form should contain 2 fields and 2 buttons. In those fields I input 2 dates (with date picker or whatever) and with 1st button I update mentioned table in Access with fresh data (delete old dates and update with new ones) and with the other I start a predefined Macro in that Access database.
How complicated is this? can you guide me to the solution? Some sample code would be excellent.
Command25_Click()
CurrentDb.Execute "DELETE * FROM Datumi"
Dim tbl As Recordset
Set tbl = CurrentDb.OpenRecordset("Datumi")
tbl.AddNew tbl!brojka = "1"
tbl!datum = Text8.Value
tbl.Update
tbl.AddNew tbl!brojka = "2"
tbl!datum = Text10.Value
tbl.Update

This is going the long way about to a certain extend because I am using the update of the dates to demonstrate how you might also run the saved queries.
'SQL for stored query, this assumes you
'will be updating based on some key
UPDATE DatesTable t
SET t.Date1 = [#Date1], t.Date2 = [#Date2]
WHERE t.aAuto=[#Key]
'Code for Excel
'You could set a library reference to
'Microsoft ActiveX Data Objects x.x Library
Dim cmd As Object
Dim cn As Object
Set cmd = CreateObject("ADODB.Command")
Set cn = CreateObject("ADODB.Connection")
'Connection string, see also http://connectionstrings.com
strCon = "Provider=Microsoft.ACE.OLEDB.12.0; " & _
"Data Source=z:\docs\test.accdb"
cn.Open strCon
'Name of the saved query
cmd.CommandText = "UpdateDates"
cmd.CommandType = adCmdStoredProc
cmd.ActiveConnection = cn
'Some parameters.
'http://www.w3schools.com/ADO/met_comm_createparameter.asp
'Make sure you get the type right, you will find details here:
'http://www.w3schools.com/ADO/ado_datatypes.asp
'You will find direction here:
'http://www.w3schools.com/ado/prop_para_direction.asp
'Make sure you get the order right
'adDate = 7, adInteger = 3, adParamInput = 1
cmd.Parameters.Append cmd.CreateParameter("#Date1", 7, 1, , txtDate1)
cmd.Parameters.Append cmd.CreateParameter("#Date2", 7, 1, , txtDate2)
cmd.Parameters.Append cmd.CreateParameter("#Date2", 3, 1, , MyUniqueKey)
'recs : return for records affected
'adExecuteNoRecords = 128 : no records are returned by this query,
'so this increases efficiency
'http://www.w3schools.com/ADO/ado_ref_command.asp
cmd.Execute recs,,128
'Did it work?
MsgBox "Records updated: " & recs

Related

Excel VBA - Get Data from SQL based of Cell range values

I've been tasked to get data from a SQL DB based off the values in Column A Row 3 onwards.
Example of Excel Sheet:
ITEM | QTY TO PICK | QTY ON ORDER | Column 2 | Column 3 etc
PART 1 | 5 | <Data will be populated here>
PART 2 | 12 | <Data will be populated here>
This code runs through a Command Button.
The data pulled from SQL will be populated starting in C3 onwards.
However, my below code only returns one row at a time.
I know where I need to make changes, I just don't know what. After at least 2 hours googling, I'm thoroughly stumped.
ItemNumber = Range("A3").Value
I've tried amending to ("A3:A100").Value but I just get errors.
Full code below;
Private Sub CommandButton2_Click()
' Create a connection object.
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
' Provide the connection string.
Dim strConn As String
'Use the SQL Server OLE DB Provider.
strConn = "Provider=SQLOLEDB;"
'Connect to the Pubs database on the local server.
strConn = strConn & "server=<server name>;INITIAL CATALOG=<DB Name>;"
'Use an integrated login.
strConn = strConn & " INTEGRATED SECURITY=sspi;"
'Now open the connection.
cn.Open strConn
'
'
ActiveSheet.Range("C3:G10000").Clear ' clear out existing data
Dim ItemNumber As String
ItemNumber = Range("A3").Value
' Create a recordset object.
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
SQLStr = "Select * from vw_WorksOrder WHERE ITEMNO = " & ItemNumber & ""
rs.Open SQLStr, cn
' Copy the records into cell A1 on Sheet1.
Sheet4.Range("C3").CopyFromRecordset rs
' Tidy up
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
You could try building the SQL like so
"Select * from vw_WorksOrder WHERE ITEMNO in (" & _
join(application.transpose(range("a1:a5").Value),",") & ")"
or, for strings.
"Select * from vw_WorksOrder WHERE ITEMNO in ('" & _
join(application.transpose(range("a1:a5").Value),"','") & "')"
My advise is:
1.)
Create a table on SQL Server which contains parameters for your sql statement (itemnumber = 1)
2.)
Write a cycle which loops tru the ranges and adds values one by one to the table like:
i = 1
while cells(i,3).value <> ""
... Insert into temptable values (parameter1,parameter2, etc)
i = i+1
wend
3.)
Modify your sql statement for the recordset joining the table with the parameters and the data you would like to pull and paste that data.

Connection to two (or more) sharepoint lists with ADODB

I can connect to a SharePoint list with ADODB this way :
Dim objCon As New ADODB.Connection
objCon.Open "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=2;RetrieveIds=Yes;DATABASE=mysite/documents;LIST={xxxx-guid-xxxx};"
Dim rst As Recordset
Set rst = objCon.Execute("Select * from list1)
and it's working :).
Now, I would like to connect two list at the same time to do an inner join :
Set rst = objCon.Execute("Select * from list1 inner join list2)
but I don't find the syntax to put the second list GUID on the connection string. How can I do ?
I know this is an older question but I was trying to attempt the same effort a while back and when I was looking for examples I generally saw the same answer of "No its not possible".
As Thomas G points out, it is possible as a 'disconnected recordset' (I typically refer to those as sub-queries) and then to join the two Lists together.
My goal is / was to avoid the need to first import the data into Excel just to run the queries with the Lists joined since I'm actually using it to bulk import several files per week into several Lists in SharePoint. I just don't want to deal with the data maintenance / clean up in Excel if I can avoid it in the first place. (The several files are all using data from two different lists during the import)
In line with the original question, I've simplified the code to just retrieve the results of a Select query against two SharePoint Lists. The code is written for Excel VBA but can be used in any VBA instance if the Excel parts are removed.
Sub SQL_Two_SP_Lists()
Dim sp_sdbPath As String, sp_sConnect As String
Dim SP_List_1 As String, SP_List_2 As String
Dim c As Long
Dim cnSP As New ADODB.Connection
Dim rsSP As New ADODB.Recordset
sp_sdbPath = "https://your_SharePoint_URL_Here/"
sp_sConnect = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=2;RetrieveIds=Yes;DATABASE=" & sp_sdbPath & ";"
SP_List_1 = "LIST={List 1 GUID Here}" 'i.e. xxxx-guid-xxxx
SP_List_2 = "LIST={List 2 GUID Here}" 'Go to List settings > Information Management Policy Settings > GUID is in the URL
'Establish a connection to the first List
cnSP = sp_sConnect + SP_List_1
cnSP.Open
'Write the SQL & Establish a connection to the second List as a sub-query using IN
sSQL = "SELECT A.*, B.* " + _
"FROM List A " + _
"INNER JOIN (Select * From LIST IN 'DATABASE=" & sp_sdbPath & ";" & SP_List_2 & "' 'WSS;RetrieveIds=Yes;') B On A.Cust_ID = B.Cust_ID;"
rsSP.Open sSQL, cnSP, adOpenStatic, adLockReadOnly 'Change cursor & lock type if inserting, updating or deleting
'The rest is to drop the results into an empty worksheet named 'Test'
For c = 0 To rsSP.Fields.Count - 1
ThisWorkbook.Sheets("Test").Cells(1, c + 1) = rsSP.Fields(c).Name
Next
ThisWorkbook.Sheets("Test").Cells(2, 1).CopyFromRecordset rsSP
rsSP.Close
cnSP.Close
End Sub
From Microsoft http://msdn.microsoft.com/en-us/library/ee633650.aspx
Selecting fields from multiple lists is not supported. You can create a dataset for each list and select fields from each dataset.
I don't know your environement but to me the easiest way to accomplish this would be to create 2 Linked tables pointing on your SharePoint lists and then you can manipulate their data the way you want.

Edit records in ADODB recordset

What I am trying to do is to get some data from an online server through an SQL Query and then loop through the recordset modifying the records.
I get an error when trying to modify the recordset:
"Multiple-Step operation generated errors. Check each status value."
My question is: Is there a way of modifying a record from a recordset that I got from a Query?
In this case I am modifying field 2 if field 1 meets a certain criteria. (In this case Field 2 is a string)
Here is the simplified code:
Dim adoConn As ADODB.Connection
Dim locRS As New ADODB.Recordset, proRS As ADODB.Recordset
Dim strConnection As String
Set getSQL = New ADODB.Recordset
'Set Objects
Set adoConn = New ADODB.Connection
'Specify connection string
strConnection = "User ID=xxx; Password=xxx;Data Source=xxx;Provider=OraOLEDB.Oracle"
'Open the connection
adoConn.Open (strConnection)
'Set up recordset properties
getSQL.CursorType = adOpenStatic
getSQL.CursorLocation = adUseClient
getSQL.LockType = adLockBatchOptimistic
'Import the data
getSQL.Open "SELECT FIELD1, FIELD2 FROM TABLE", adoConn, adOpenStatic, adLockOptimistic
Set getSQL.ActiveConnection = Nothing
getSql.Update
'Loop through data
getSQL.MoveFirst
Do While Not stockRS.EOF
'If cetrain condition is met then modify the null column
if getSQL!FIELD1=CRITERIA then
'Error here
getSQL!FIELD2="SOME STRING"
End If
getSQL.MoveNext
Loop
'Close
adoConn.Close
Set adoConn = Nothing
Your SQL is not doing what you think:
SELECT ... NULL OUTCOME ... is going to return the value NULL in a field called OUTCOME but will not link to a field in the table called OUTCOME (which is what I think you are looking for) as your current syntax is setting up an ALIAS not selecting the field. I am assuming the field OUTCOME exists on the table. If not you need to create it up front or do an alter table to add the field before you can write anything to it.
I recommend creating field up front (which I think you have already done). But make sure that the default value is NULL so you don't need to do your NULL trick in the select ALSO make sure that the field is allowed to take a NULL value or you will see errors. Select becomes:
getSQL.Open "SELECT FIELD1, FIELD2, OUTCOME FROM TABLE", adoConn, adOpenStatic, adLockOptimistic
And then manage the NULL value in the function as follows:
if getSQL!FIELD1=CRITERIA then
'Error here
getSQL!OUTCOME="SOME STRING"
ELSE
getSQL!OUTCOME=NULL
End If
This ensure that you always write something to OUTCOME field so processing and OUTCOME don't get out of sync.
Also I still think that you have divorced the recordset data from the server when you:
Set getSQL.ActiveConnection = Nothing
Do this to release resources after your are done.
You may also need a
getSql.Update
After making changes to commit them back to database.

Named variables in SQL using ADODB in vba

I have lots of SQL scripts, many of which use various different variables throughout, and I'd like to be able to drop the results directly into Excel. The hope is to do this as 'smoothly' as possible, so that when someone gives me a new SQL script (which may be relatively complicated), it is relatively clean to set up the spreadsheet that gathers its results.
Currently trying to get this working using ADODB Command objects parameters, but I can't even manage to get a very basic example to work. I have the following VBA:
Dim oConnection As ADODB.Connection
Set oConnection = New ADODB.Connection
oConnection.ConnectionString = "MyConnectionString"
oConnection.Open
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = oConnection
Up to here is just setting up the connection, which seems to work fine.
cmd.CommandText = "DECLARE #DateID integer;" & _
"SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
cmd.CommandType = adCmdText
Dim DateID As ADODB.Parameter
Set DateID = cmd.CreateParameter("#DateID", adInteger, adParamInput)
cmd.Parameters.Append DateID
DateID.Value = 20120831
Dim rst AS ADODB.RecordSet
Set rst = cmd.Execute()
ActiveSheet.Range("A1").CopyFromRecordset rst
Unfortunately, this doesn't return anything. However, if I replace the line:
"WHERE DateID = #DateID"
with this:
"WHERE DateID = 20120831"
Then the query returns exactly what you'd expect (the top 10 records from August 31), so obviously I'm not passing the value of the variable from VBA into SQL properly, but I have to admit that I'm pretty much stuck.
Certainly something is being passed into SQL (if I change the type of the variable #DateID to datetime in the SQL, then I get a SQL Server arithmetic overflow error, from trying to convert something to datetime), but it isn't doing what I was expecting.
I guess there are two questions: Is there a way to fix this code? Is there a better way of achieving the general goal described at the start?
Try this
cmd.CommandText = "DECLARE #DateID integer;" & _
"SET #DateID = ?DateID;" & _
"SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
.....
Set DateID = cmd.CreateParameter("?DateID", adInteger, adParamInput)
Re:
in which case why bother having names for them in the first place
Well, so that you can match them up as shown above. By all means use it many times, but use a sql-server local declare and set it there as shown.
Remove the DECLARE #DateID integer; from the SQL string.
ie:
cmd.CommandText = "SELECT TOP 10 * FROM dbo.SomeRecords " & _
"WHERE DateID = #DateID"
Parameters in an ADO parameterized query want a ? as placeholder so:
"SELECT TOP 10 * FROM dbo.SomeRecords WHERE DateID = ?"

How to return the value in one field based on lookup value in another field

This is basic stuff, but I'm somewhat unfamiliar with VBA and the Word/Access object models.
I have a two column database of about 117000 records. The columns are 'surname' and 'count'. I want a user to be able to type SMITH in a textbox and hit submit. I then want to run something like
SELECT table.count FROM table WHERE surname = string
and return the value of table.count in a string.
It feels like this should be five or six lines of code (which I have but won't post) but I'm obviously missing something!
Cheers
First of all, be careful naming the column 'count' -- this is a keyword in SQL and might cause problems. Similarly, don't call the table 'table'.
Here is some sample code which shows one way of doing it:
' This example uses Microsoft ActiveX Data Objects 2.8,
' which you have to check in Tools | References
' Create the connection. This connection may be reused for other queries.
' Use connectionstrings.com to get the syntax to connect to your database:
Dim conn As New ADODB.Connection
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\tmp\Database1.accdb"
Dim cmd As New ADODB.Command
Set cmd.ActiveConnection = conn
' Replace anything which might change in the following SQL string with ?
cmd.CommandText = "select ct from tbl where surname = ?"
' Create one parameter for every ?
Dim param As ADODB.Parameter
Set param = cmd.CreateParameter("surname", adBSTR, adParamInput, , TextBox1.Text)
cmd.Parameters.Append param
Dim rs As ADODB.Recordset
Set rs = cmd.Execute
MsgBox rs("ct")
rs.Close
conn.Close
It is possible to use InsertDatabase:
Sub GetData()
ActiveDocument.Bookmarks("InsertHere").Select
Selection.Range.InsertDatabase Format:=0, Style:=0, LinkToSource:=False, _
Connection:="TABLE Members", SQLStatement:= _
"SELECT [Count] FROM [Members]" _
& " WHERE Surname='" _
& ActiveDocument.FormFields("Text1").Result & "'", _
DataSource:="C:\docs\ltd.mdb", From:=-1, To:= _
-1, IncludeFields:=True
End Sub
This is an edited macro recorded using the database toolbar.
EDITED Warning: this code, as shown, is subject to a SQL Injection attack.