Update Sharepoint from Excel via ADO connection - Internal name issue - sql

I need to update a SharePoint table which has a field name with Spaces. The field name is called Tracking log
Unfortunately there are lot of reports already created that don't let me recreate this column with a different name, so I need to find a workaround to address this special name.
Lot of blogs point me to revise the internal name and check the name given when it was created, so I checked the List Setting menu for the whole URL path and see the following:
https://sales.acs.com/SMS/_layouts/15/FldEdit.aspx?List=%7B686F9AF9%2DFB64%2D4AD9%2DA268%2D19A057C432DA%7D&Field=Tracking%5Fx0020%5Flog
Below is the script I've put together which runs perfectly fine for any other field without spaces in the name, but not specifically for this one.
Dim sSQL As String
' Build the connection string
sConn = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;RetrieveIds=Yes;" & "DATABASE=" & sSHAREPOINT_SITE & ";" & "LIST=" & sDEMAND_ROLE_GUID & ";Authentication=Default;"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Open the connection.
With cn
.ConnectionString = sConn
.Open
End With
ID = "12345"
fieldName = "Tracking_x0020_log" 'Display view is "Tracking log", I've tried also with Tracking%5Fx0020%5Flog without luck
FieldValue = "Test"
'sSQL = "SELECT * FROM EMEA_SALES WHERE (APA_number='" & Format(ID, "#") & "');"
sSQL = "UPDATE EMEA_SALES SET " & fieldName & " = '" & FieldValue & "' WHERE (APA_number='" & Format(ID, "#") & "');"
rs.Open sSQL, cn, adOpenDynamic, adLockOptimistic
cn.Close
Set cn = Nothing
End Sub
The error I've got is:
No value given for one or more required parameters.
When I change the fieldname for any other without spaces is run smoothly.
Any clue will be appreciated. Thanks folks!

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")

Performing SQL queries on basic Excel 2013 worksheet as table using ADO with VBA triggers Errors

I'm developping modules on a client XLSm with 32-bits 2013 Excel.
I'd like to use datas on worksheet as if it is an Access table.
With a lot of difficulties, I think connection is now OK.
Still, I have error : 3001 Arguments are of wrong type, are out of acceptable range. Error that I cannot understand.
Here excerpts of VBA lines :
In addition, I added 20 lines in data Worksheet below the header line to permit to Excel to interpret for the type of each columns.
varCnxStr = "Data Source=" & G_sWBookREINVOICingFilePath & ";" & "Extended Properties='Excel 12.0 Xml;HDR=YES;IMEX=15';"
With conXLdb
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Mode = adModeShareExclusive
.Open varCnxStr
End With
strSQL = "SELECT * "
strSQL = strSQL & " FROM [ReInvoiceDB$B2B5072] inum "
strSQL = strSQL & " WHERE inum.InvoiceNum LIKE '1712*' "
strSQL = strSQL & ";"
'>> TRIGGERs ERROR with the current Where Clause !!'
adoXLrst.Open strSQL, conXLdb, dbOpenDynamic, adLockReadOnly, adCmdText
If adoXLrst.BOF And adoXLrst.EOF Then
'no records returned'
GoTo Veloma
End If
adoXLrst.MoveFirst
Do While Not adoXLrst.EOF
'Doing stuff with row'
adoXLrst.MoveNext
Loop
sHighestSoFar = adoXLrst(1).Value '> just to try for RecordSet : Codes are not completed...
sPrefixeCURR = Mid(sHighestSoFar, 1, 4)
Highest = CInt(Mid(sHighestSoFar, 5))
'> Increment >'
Highest = Highest + 1
HighestStr = sPrefixeCURR & Format(Highest, "00")
strGSFNumber = HighestStr
adoXLrst.Close
conXLdb.Close
Veloma:
On Error Resume Next
Set adoXLrst = Nothing
Set conXLdb = Nothing
Exit Sub
Etc.
Any idea about what seems be wrong ?
Thank you
Below is an old example I have been using successfully. Note that the sheet name in the book are Sheet1 and Sheet2, but in the query I had to use sheet1$ and sheet2$. I noticed you had $ signs in the middle of your sheet names. perhaps that's the issue ?
Sub SQLUpdateExample()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
con.Open "Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=" & ThisWorkbook.FullName & ";" & _
"DefaultDir=" & ThisWorkbook.FullName & ";ReadOnly=False;"
Set rs = New ADODB.Recordset
Set rs = con.Execute("UPDATE [Sheet1$] inner join [Sheet2$] on [Sheet1$].test1 = [Sheet2$].test1 SET [Sheet1$].test3 = [Sheet2$].test2 ")
Set rs = Nothing
Set con = Nothing
End Sub
To give more details about the whole module to be implemented : it is to perform a Transaction unit.
This transaction will comprise 3 operations : get a max value from a column (Invoice number) to increment it, record the new number inside an Access table (by DAO), the same Excel file (by ADO) and generating document on HDD.
So it is aimed to use the Excel file as a table not as a file manipulated with Windows script or Excel VBA. My end user is disturbed by the pop-uping of an Excel opening file operation. As a developer, I'm feeling more comfortable with using SQL statements as much as possible inside Transaction session. Is that your opinion too ?

T-SQL query with variable declarations in Excel VBA Code fail

I got a problem with running SQL query with "declare" and "set" functions in VBA.
Sheets("Arkusz1").Select
connstring = _
"ODBC;DRIVER=SQL Server;SERVER=my_database_server;UID=user;PWD=password;APP=Microsoft Office 2010;WSID=some_id;DATABASE=mydatabase"
With ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Worksheets("Arkusz1").Range("A1"), Sql:=Array( _
"declare #dzisiaj date" & Chr(13), _
"set #dzisiaj = getdate()" & Chr(13), _
"select #dzisiaj as dzisiaj"))
.BackgroundQuery = False
.Refresh
End With
In SQL Server 2012 that code works fine, but... when I embed it into it gives me a run-time error '1004'. Also VBA code works on other queries works well.
My full SQL query has about 90 lines with 2 variable declarations (one declaration is a value from another 30 line SQL query), so it's mandatory to include variable declarations :)
How to solve that problem?
I figured it out. The key is to use ADODB connection to import data via SQL Query. Also necessary is to check Microsoft Active X Data Objects 2.0 library in Tools->References in Visual Basic Editor (Shortcut: Alt+F11 in Excel).
So, there is an example of my VBA code:
Sub sql_query_import()
' Declarations
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
' Server connection settings
Server_Name = "192.168.1.106\my_database" ' IP of server name
Database_Name = "mydatabase" ' Database name
User_ID = "myusername" ' User name
Password = "mypassword" ' User password
' SQL Query
SQLStr = "SET NOCOUNT ON " & Chr(13) ' it's mandatory if you don't want to get error 3704
SQLStr = SQLStr & "declare #dzisiaj date " & Chr(13)
SQLStr = SQLStr & "set #dzisiaj = getdate() " & Chr(13)
SQLStr = SQLStr & "select #dzisiaj as 'today'
' Connect to database
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
' Start connection
rs.Open SQLStr, Cn, adOpenStatic
' Load data
With rs
For i = 1 To .Fields.Count
Worksheets(1).Cells(1, i) = .Fields(i - 1).Name ' Include column name if not - delete it
Next i
End With
Worksheets(1).Cells(2, 1).CopyFromRecordset rs ' Start loading data to Cell A2
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
Using in SQL Query "SET NOCOUNT ON" is necessary if you don't want to get error 3704.
Also, using
SQLStr = "SET NOCOUNT ON " & Chr(13) ' it's mandatory if you don't want to get error 3704
SQLStr = SQLStr & "declare #dzisiaj date " & Chr(13)
is more efficient way to include multi-line SQL Queries :)
I'm still new to vb and vba and learning myself, but I know you can declare and write to variables in VB.net which can then feed into an embedded SQL script. I would think you can do the same thing in vba. Here's what I suggest.
Declare a vb string like SQL_Var_1
Insert the 30-line SQL query as a separate query before the main query.
Write the result of the 30-line query to the vb string SQL_Var_1.
Remove the declarations from the Main SQL query but leaving the references to those variables.
Reference SQL_Var_1 as an input parameter in the embedded main query using the exact same name you used in the main query (i.e., #dzisiaj), like here.
If you follow these steps for both SQL variables, you should be able to achieve the same result as if you were using the declared SQL variables.

'if exist' SQL query in VBA with ADODB database connection

I need to uplad data from excel into a database, but I need to check first if there is data in the table for each upload so that I Update or Insert data.
To diferentiate Update or Insert, I'm usign a SQL IF EXIST command, which works okay in SQL. When I try this in Excel VBA I get an error message: "Command text was not set for the command object."
See code below
Dim strSQL As String
Dim Value As String
Dim Reference As String
Set RCconn = New ADODB.Connection
Set TuneCMD = New ADODB.Command
' Establish Recordset
Set Results = New ADODB.Recordset
'Establish a Connection
With RCconn
.Provider = "SQLOLEDB"
.ConnectionString = ConStr
End With
'Open the connection
RCconn.Open
'i Columns
For i = 5 To 10 '16
'j rows
For j = 6 To 60 '145
Value= Sheets("Value").Cells(j, i)
Reference= "W_F/P_" & Sheets("Reference").Cells(j, i)
stringTest = "IF EXISTS (SELECT * FROM UploadTable WHERE Ref = '" & Reference & "') "
stringTest = stringTest & "UPDATE Val "
stringTest = stringTest & "SET Val = '" & Value & "' "
stringTest = stringTest & "where Ref = '" & Reference & "' "
stringTest = stringTest & "Else "
stringTest = stringTest & "INSERT INTO UploadTable (Val , Ref ) "
stringTest = stringTest & "values ('" & Value & "', '" & Reference & "')"
RCconn.Execute strSQL
Next
Next
Set Results = Nothing
RCconn.Close
Set RCconn = Nothing
Is it the case that 'IF EXIST' can not be used in VBA? Is there a work around?
Thanks
ADODB.Connection.Execute sends a pass-through query to your database. It doesn't matter what SQL statement was in that string; if your database can understand it, it will be executed.
So inspect your SQL query again.
Try this:
Put a breakpoint on the line RCconn.Execute strSQL. When the debugger breaks there, inspect the value of strSQL. Copy it and execute in SQL Server Management Studio directly. If that doesn't work, correct your code that builds that string. If it works, then there is some problem with your ConnectionString. In that case, check that the userID and password you are using in the ConnectionString to connect has adequate privileges.

MS Access 2007, checking current user against a table

We have a simple access database, and would like a button on a form to only be available to select members of staff. (The button has an event tied to it). I'd like to store the usernames of the staff allowed to click the button in a separate table.
What I'd like to do, is perform a simple query to see if the username exists in the table, and set the enabled state of the button depending upon the outcome.
My background is C# and SQL Server, but VBA and access are new to me, and I think I'm struggling with the quirks of this environment.
I've got the username of the logged on user in a string fOSUserName via a call to GetUserNameA in advapi32.dll, but I'm struggling with the simplest of queries to determine if the username exists in the table.
Dim strSQL As String
Dim intResult As Integer
Dim db As DAO.Database
Dim rs As Recordset
Set db = CurrentDb
strSQL = "SELECT COUNT(*) FROM [USERS] WHERE [USERS].[NAME] = '" & _
fOSUsername & "'"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
If Not rs.EOF Then
intResult = rs.Fields(0)
Else
intResult = 0
End If
rs.Close
db.Close
This fails on db.OpenRecordset giving me the error
Run-time error '3061':
Too few parameters. Expected 1.
Can anyone offer some pointers?
When you continue a line in VBA, you need a space between before the line continuation character ("_"). So instead of this:
strSQL = "SELECT COUNT(*) FROM [USERS] WHERE [USERS].[NAME] = '" &_
fOSUsername & "'"
Use this:
strSQL = "SELECT COUNT(*) FROM [USERS] WHERE [USERS].[NAME] = '" & _
fOSUsername & "'"
However, as #Igor Turman pointed out, the lack of a space before the underline character should trigger a compile error. So I'm unsure what's going on but suggest you fix it anyway to avoid confusion.
I'll suggest that rather than opening a recordset, and then reading a value from that recordset, this could be handled simply with the DCount() function.
Dim strCriteria As String
strCriteria = "[USERS].[NAME] = '" & fOSUsername & "'"
Debug.Print "strCriteria: '" & strCriteria & "'"
If DCount("*", "USERS", strCriteria) = 0 Then
Debug.Print "not found"
Else
Debug.Print "found"
End IF
If your missing parameter error is because USERS is a query rather than a table, you can ask DCount() to use a table instead. Or fix the query.
Sounds like your [USERS] object is not a table but Query (with parameter). Also, if you had a syntax error like '&_'(invalid) as opposed to '& _'(valid), your database would not compile. So, if table vs query is your case, please use the following:
...
Dim rs As Recordset
Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs("Users")
qdf.Parameters("UserNameParameter") = fOSUsername
Set rs = qdf.OpenRecordset
...
I'm not totally familiar with the way you are using it, but I've always done it this way:
Dim sSQL As String
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=[your access db file path and name];Persist Security Info=False"
sSQL = "SELECT COUNT(*) FROM [USERS] WHERE [USERS].[NAME] = '" &_
fOSUsername & "'"
Set rs = New ADODB.Recordset
rs.Open sSQL, cn
If Not rs.EOF Then
intResult = rs.Fields(0)
Else
intResult = 0
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing