Trouble calling SQL Server Stored proc from Access 2007 - sql

I have an SP in SQL Server (2012). It returns a single row...verified using SSMS
exec dbo.cpas_DeleteProjects N'3555,3565'
It returns a valid row with record count info in the columns.
From Access(2007), I'm calling it using an adodb call:
Sub DevolveProjects(ProjectIDs As String)
''
' Looking for a comma-delimited list of project IDs in string form: "34,52,14"
'
Dim cnn As New adodb.Connection
Dim rstReturnValues As adodb.Recordset
cnn.ConnectionString = "Provider=SQLOLEDB;Server=" & CurrentServerName() & ";Initial Catalog=" & CurrentDBName() & ";Integrated Security=SSPI;"
cnn.Open
Set rstReturnValues = cnn.Execute("exec dbo.cpas_DeleteProjects N'" & ProjectIDs & "'")
With rstReturnValues...
Problem is, rstReturnValues is closed. No data.
I've verified using SQL Profiler that the sp is running the expected SQL when called from the Access app as above, and seems to be performing just fine, so there are no issues with authentication. I'm just not getting my recordset populated. When I copy and paste the exact SQL statement SQL Profiler saw into an SSMS query, it returns EXACTLY what I expect....
Have I coded the .execute call incorrectly? Ideas?

The code looks right, although you could try using bind parameters instead of a single SQL string. For something quick and dirty it doesn't make any difference, but this removes the possibility of SQL injection
Dim lConnection as new ADODB.Connection
Dim lCommand as new ADODB.Command
Dim lParameter as ADODB.Parameter
Dim lRecordset as ADODB.Recordset
lConnection.ConnectionString = "Provider=SQLOLEDB;Server=" & CurrentServerName() & ";Initial Catalog=" & CurrentDBName() & ";Integrated Security=SSPI;"
lConnection.Open
lCommand.ActiveConnection = lConnection
lCommand.CommandText = "dbo.cpas_DeleteProjects"
lCommand.CommandType = adCmdStoredProc
set lParameter = lCommand.CreateParameter(, adVarWChar, adParamInput, 200, ProjectIDs) 'replace 200 with parameter length, different syntax if nvarchar(max)
lCommand.Parameters.Append lParameter
Set lRecordset = lCommand.Execute()
Debug.Print lRecordset(0) 'Does the recordset contain anything?
...
lRecordset.Close
lConnection.Close

Related

VBA to query field contents in CSV

I'm struggling with ADO connections/recordsets.
My problem statement is: a function that will return the first value of a chosen field, in a chosen .csv file.
I am doing this to identify variably-named .csv files before adding the data to the relevant tables in a database. I am making the assumption that this field is always present and that either it is consistent throughout the file, or only relevant ones are grouped (this is controlled higher up the chain and is certain enough).
My code is being run as part of a module in an MS Access database:
Public Function GetFirstItem(File As Scripting.File, Field As String)
Dim Conn As ADODB.Connection, Recordset As ADODB.Recordset, SQL As String
Set Conn = New ADODB.Connection
Set Recordset = New ADODB.Recordset
'Microsoft.ACE.OLEDB.16.0 / Microsoft.Jet.OLEDB.4.0
Conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=""" & File.ParentFolder & _
"""; Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
SQL = "SELECT " & Field & " FROM """ & File.Name & """ LIMIT 1"
Debug.Print Conn.ConnectionString
Debug.Print SQL
Conn.Open
Recordset.Source = SQL
Recordset.ActiveConnection = Conn.ConnectionString
Recordset.Open
Recordset.MoveFirst
'GetFirstItem = Recordset!Questionnaire
Recordset.Close
Conn.Close
Set Recordset = Nothing
Set Conn = Nothing
End Function
ConnectionString = Provider=Microsoft.ACE.OLEDB.16.0;Data Source="D:\Documents\Jobs\TestPath"; Extended Properties="text;HDR=Yes;FMT=Delimited;";
Field = Questionnaire
SQL = SELECT Questionnaire FROM "test.csv" LIMIT 1
I get an error on Recordset.Open of:
This may be (is probably) down to a complete lack of understanding of how ADO connections/recordsets work. I have tried sans-quotes and it complains about a malformed FROM expression. Additionally, once this hurdle is overcome I am unsure of the syntax of how to return the result of my query. If there is a better way of doing this I am all ears!
Thanks.
In Access you don't need ADO library to query a CSV file:
Public Function GetFirstItem(File As Scripting.File, Field As String) As String
Dim RS As DAO.Recordset, SQL As String
SQL = "SELECT TOP 1 [" & Field & "]" _
& " FROM [" & File.Name & "]" _
& " IN '" & File.ParentFolder & "'[Text;FMT=CSVDelimited;HDR=Yes];"
Debug.Print SQL
Set RS = CurrentDb.OpenRecordset(SQL)
GetFirstItem = RS(0)
RS.Close
Set RS = Nothing
End Function
Usage:
?GetFirstItem(CreateObject("Scripting.FileSystemObject").getfile("c:\path\to\your\file.csv"), "your field")

Trying to update Excel-Table through Access-VBA Code. Error: Cannot find database Object "Ware"

I have a number of Excel-Files that contain data which I need to combine into one table.
Is it possible and reasonable to do this from within Access VBA code, which I would prefer? Or should I just do it in Excel VBA?
My idea was to iterate through the Excel-Files and use an SQL statement for UPDATE Column WHERE MyCondition, to get the Values I want to the Column I want. Is it possible this way or what would be a suggestion to solving this?
I have tried it this way until now from Access:
Sub Execute_UpdateQuery()
Dim conn As ADODB.Connection
Dim NumOfRec As Integer
Dim strPath As String
strPath = "D:\Sortierliste August_September\Test.xlsx"
Set conn = New ADODB.Connection
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strPath & ";Extended Properties=Excel 12.0 Xml;HDR=YES;"
conn.Execute "UPDATE Ware SET Name = 'test'" & _
" WHERE Name = 'Ackermann'", NumOfRec, adExecuteNoRecords
Debug.Print NumOfRec & " records were updated."
conn.Close
Set conn = Nothing
End Sub
But that results into an error "Cannot find access-database module "Ware". I guess it is because it is just an excel-table and not a database? I thought it can find an excel-file containing the table called Ware and execute an sql query. Any help or suggestions would be great on how to solve this issue.
Greetz

SQL Select Statement in Microsoft Access VBA - Need help inserting in Access table as block, not loop

I am trying to do a Select statement from an SQL server using an ADODB connection, within Microsoft Access VBA. The select statement is very complex with calculations and would work better to keep that to try and turn in to a connection with the DB.
I can append the data row by row, but am wondering how I could append as simple as possible as a block of data to save time/vba effort. (Lots of data!)
In order to simplify the example, I have put a basic SQL statement, but if you could review this and let me know if there is a way to append as a recordset block or what would be a better option... The code below works for pasting as a block into excel, and I would think I only need to change that commented out line's method to append in Access...
Option Private Module
Private Const DataServer = "GLSSQLMADPS2"
Private Const sqlconstring = "Driver={SQL Server};Server=" & DataServer & "; Database=PERF_MGMT_BWRSRV_PROD; Trusted_Connection=yes; Connect Timeout = 600"
Sub M2DSQLPull()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String
Dim sql As String
sql = "SELECT " & _
"Employee_Token_NR, " & _
"Null as 'Sum_Month', " & _
"1000 AS 'Data_ID', " & _
"DATEADD(m, DATEDIFF(m, 0, MIN(CALL_TS)), 0) AS 'Metric_1' " & _
"FROM PMBSED_PhoneEvaluations " & _
"GROUP BY Employee_Token_NR "
Set cn = New ADODB.Connection
cn.CommandTimeout = 120
cn.Open sqlconstring
Set rs = New ADODB.Recordset
rs.Open SqlString(i), cn, adOpenStatic, adLockReadOnly
'How I would paste in an excel spreadsheet, how do I block paste in an access database?
'ThisWorkbook.Worksheets("RawData").Cells(RowNumber, 1).CopyFromRecordset rs
RowNumber = RowNumber + rs.RecordCount
rs.Close
cn.Close
End Sub
Thank you for any assistance!
-Robert

Can't insert records from Excel to SharePoint

Currently I am suffering Excel ADO issue.
Here is the thing taht
I was trying to insert some records
from "Excel table" to "SharePoint list" Using ADO connection.
But failed (Can't recognize Excel table in SQL Statement)
Dim SQL As String
Dim CN As New ADODB.Connection
Dim OLEDB As String
Dim LIST As String
Dim SITE As String
LIST = "{EE028282-3D7E-4D37-93EE-50FB69C4432C}"
SITE = "https://asml.sharepoint.com/teams/FFKR_DUV_YS_Installation_and_Relocation/Product"
OLEDB = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=0;RetrieveIds=Yes;" & _
"DATABASE=" & SITE & ";" & _
"LIST=" & LIST & ";"
Set CN = New ADODB.Connection
CN.Open OLEDB
SQL = SQL & "INSERT INTO Schedule_DB (NAME,TYPE_W) "
SQL = SQL & "SELECT * "
SQL = SQL & "FROM [" & ThisWorkbook.FullName & "].[S_RAW$] "
CN.Execute CommandText:=SQL
CN.Close
If I run it I got error ->
Error image
I have already check the miss-spell, and the amount of item is too much, so I would prefer to process it as a one SQL statement.
"Excel to Excel" works well But still have no ideas for "Excel to SharePoint List".
Please share your advice.
When you want to read data from your Excel sheet you need to have a ADODB.Connection with Read permission, then to write data to your SharePoint List you need to have another ADODB.Connection with Write permission.
Note: You can't transport your whole data in that way, You can generate a big command with whole data then use it or generate command for each record of your Excel data.
About your exception it is simply says it can't find your sheet name in SharePoint Lists.
A sample to guide you can be something like this:
Dim cnnXl As New ADODB.Connection
Dim rsXl As New ADODB.Recordset
Dim cnnShP As New ADODB.Connection
conStrXl = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\yourExcel.xlsx';" & _
"Extended Properties=""Excel 12.0;HDR=YES;IMEX=1;"";"
commandXl = "SELECT [Field1], [Field2] FROM [Worksheet$$A1:D7] WHERE [Thing1] > 1"
conStrShP = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=0;RetrieveIds=Yes;" & _
"DATABASE=yourSite;LIST={yourListCLSID};"
Then open cnnXl and run commandXl and read data to rsXl.
Then open cnnShP and loop over rsXl records and create your commandShP and execute it.

insert full ADO Recordset into existing ACCESS table WITHOUT LOOP

I have a filled ADO recordset in my VBA module. I also have a table in ACCESS that has exactly the same structure as the recordset.
Now I fill the table using a loop (which is fine) going through each dataset record.
What I am wondering: is there a way to insert an entire recordset into the access table? (and more importantly: would this be significantly faster)
Here's a basic example (run from excel in this case) which illustrates using a disconnected recordset to add records.
Sub Tester()
Dim con As ADODB.Connection, rs As ADODB.Recordset
Dim i As Long
Set con = getConn()
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient '<<<< important!
'get an empty recordset to add new records to
rs.Open "select * from Table1 where false", con, _
adOpenDynamic, adLockBatchOptimistic
'disconnect the recordset and close the connection
Set rs.ActiveConnection = Nothing
con.Close
Set con = Nothing
'add some new records to our test recordset
For i = 1 To 100
rs.AddNew
rs("UserName") = "Newuser_" & i
Next i
'reconnect to update
Set con = getConn()
Set rs.ActiveConnection = con
rs.UpdateBatch '<<< transfer to DB happens here: no loop!
rs.Close
'requery to demonstrate insert was successful
rs.Open "select * from Table1", con, _
adOpenDynamic, adLockBatchOptimistic
Do While Not rs.EOF
Debug.Print rs("ID").Value, rs("UserName").Value
rs.MoveNext
Loop
rs.Close
con.Close
End Sub
Function getConn() As ADODB.Connection
Dim rv As New ADODB.Connection
Dim strConn As String
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source = " & ThisWorkbook.Path & "\Test.accdb"
rv.Open strConn
Set getConn = rv
End Function
VBA Recordsets exist virtually in memory called during runtime until they are contained into an actual physical format (i.e., csv, txt, xlsx, xml, database temp table) saved to hard disk. This is akin to data frames in R or Python pandas, SAS datasets, PHP arrays, and other data structures.
Consider exporting your ADO in such a format using CopyFromRecordset methods into an Excel spreadsheet to be saved as csv, txt, xlsx, or xml. Alternatively, you can use the Save method to save recordset in a persistent format type like xml.
Then, append resultant file to MS Access table with its automated data migration features:
For spreadsheets: DoCmd.TransferSpreadsheet
For txt, csv, or other delimited files: DoCmd.TransferText
For xml files: Application.ImportXML
For local or ODBC/OLEDB linked database tables: INSERT INTO append SQL query
To accomplish this with a SQL statement you use the SELECT/INSERT... IN [Designate DB A; record posted to] or FROM... IN [Designate DB B; record original source]
You can only use the IN statement once in a single query. Therefore you create the other connection using the ADODB connection to determine the other source connection.
Function example()
Dim dB_External As String
Dim db_Local As String
Dim cnLocal As ADODB.Connection
Dim cnExternal As ADODB.Connection
Set cnLocal = CurrentProject.Connection
Set cnExternal = New ADODB.Connection
cnExternal .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\\...accdb;Persist Security Info=False;"
dB_External = "C:\Users\\...accdb"
db_LOCAL = "C:\Users\\...accdb"
Example A:
strSQL = "INSERT INTO *Local table to receive records* (Column Designations)"
strSQL = strSQL & " SELECT ( *Corresponding records from external table* )"
strSQL = strSQL & " FROM *External table name* IN '" & dB_External & "'"
cnLocal.Execute (strSQL)
I use the above code, with the local ADODB connections if I select from a single external table.
Example B:
strSQL = "INSERT INTO *Local table to receive records* (Column Designations) IN '" & dblocal & "'"
strSQL = strSQL & " ( *Corresponding records from external table* )"
strSQL = strSQL & " FROM *External table name*
cnExternal.Execute (strSQL)
I use the above code using the external ADODB connection, if I select involves joining multiple tables in the external db.
No. There is no reverse equivalent - could be SetRows - to the method GetRows.