ADO connection (in VBA) unable to INSERT to Sharepoint list - vba

I'm using ADO because I want to write to a Sharepoint list using VBA in Excel.
Right now I am getting "The Microsoft Access database engine could not find the object 'Isaac Test Excel To Sharepoint', and the code errs on the INSERT line. I suspect it is because of either my site reference being wrong, or my list ID being wrong.
I don't think my list ID is wrong, because I carefully followed the directions to extract the list ID from the URL that's exposed when you go to List Settings, carefully Replacing the 3 replaceable items as mentioned here: https://community.nintex.com/t5/Community-Blogs/Obtaining-a-list-id-in-SharePoint-2010-or-2013/ba-p/77664#:~:text=Navigate%20to%20the%20list%20and%20click%20List%20Settings.,Guid%20Format%20with%20URL%20encoding).
I am passing it in as:
strSharepointListID = "{3404D534–10CB–4F53–BB9D–37F5612155F1}"
I would like to have concluded, "the connection is correct because the code doesn't err until all the way to the INSERT statement", but unfortunately I've proved that to be false: If I pass in a totally non-existent Site value, gibberish, the code still doesn't err until all the way at the INSERT statement.
The name of my list is definitely Isaac Test Excel To Sharepoint
The site I am passing is like this, with me sanitizing this by replacing some text with "text": (I've tried all 3 of these):
strSharepointSite = "https://text.text.text.com"
strSharepointSite = "https://text.text.text.com/sites/text"
strSharepointSite = "https://text.text.text.com/sites/text/_layouts/15/start.aspx#/"
Full code:
Sub Upd2KPIMember_SP()
Dim cnt As ADODB.Connection
Dim mySQL As String
Dim strSharepointListID As String, strSharepointSite As String
'https://community.nintex.com/t5/Community-Blogs/Obtaining-a-list-id-in-SharePoint-2010-or-2013/ba-p/77664#:~:text=Navigate%20to%20the%20list%20and%20click%20List%20Settings.,Guid%20Format%20with%20URL%20encoding).
'list ID from sharepoint URL:
' %7B3404D534%2D10CB%2D4F53%2DBB9D%2D37F5612155F1%7D
'list ID after replacing as follows:
' %7B3404D534%2D10CB%2D4F53%2DBB9D%2D37F5612155F1}
strSharepointListID = "{3404D534–10CB–4F53–BB9D–37F5612155F1}"
strSharepointSite = "[sanitized for SO post]"
Set cnt = New ADODB.Connection
With cnt
.ConnectionString = _
"Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=0;RetrieveIds=Yes;DATABASE=" & strSharepointSite & ";LIST=" & strSharepointListID & ";"
.Open
End With
mySQL = "insert into [Isaac Test Excel To Sharepoint] (column1,column2) values ('col1_val1','col2_val1');"
cnt.Execute (mySQL)
If CBool(cnt.State And adStateOpen) = True Then cnt.Close
Set cnt = Nothing
End Sub
I'm also fairly sure the SQL syntax is good, because the code DID tell me when it was wrong--When at first I used INSERT TABLE instead of INSERT INTO TABLE.

Partial credit to KeshavSharma (see comments) for
correctly mentioning LIST ID not required, use LIST NAME instead
inspiring me to keep focusing on THAT line of code - that it was the problem
The final code that worked was precisely identical to the first code I posted, EXCEPT, inside the connection string, instead of:
LIST={8F7FEF30–C868–4480–8AC8–4FE4FDB3921A};
I need to use:
LIST=Isaac Test Excel To Sharepoint;
(despite spaces in object name - I need to use NO single quotes, NO brackets).
Very happy this got solved - hopefully it helps someone else some day.

Related

Passing a SQL result as an argument for a VBScript object

I am working on an extant .Asp program at the moment which contains the following snippet:
Dim strRel_Report_Location
Dim rs, sql, blnReportExists
Dim strUID
Dim intMonth, intYear
sql = "Select NewID() AS UID"
Set rs = DB.Execute(Sql)
strUID = rs("UID")
strRel_Report_Location = "/Admin/Reports/Temp/t" & strUID & ".html"
My question is, how is it possible to pass the string "UID" as an argument to the object 'rs'? One may easily divine from the code that the intent is to pass the resulting "NewID()" call to the path which is assigned in the statement:
strRel_Report_Location = "/Admin/Reports/Temp/t" & strUID & ".html"
Any illumination would be greatly appreciated as I don't wish to just make assumptions on the code with which I am working.
I'm sure this is a layup for you guys, but thank you for your help!
I have to make an assumption here because you never show how the DB variable is created. I am going to assume you are working with straight ADO because the call signatures in your code match that.
Again, you are probably working with an Ado Command instance which has the method Execute. This method takes a sql string, executes it on the database server, and then returns a Recordset which contains the results of the query that executed. The recordset has an indexer with the name of the columns, using that indexer you can get the value in the column.
If you want to learn more about this code it would help to start reading up on how to work with ADO.

SELECT INTO in VBA results in no records selected or written

When I use this SQL in Access, it works fine. In VBA, the result is to create a new table with no records. It must be a dumb mistake on my part but can't find it. Many thanks for any help or point in right direction.
Mike
strSQL = "SELECT tempconsoltb.[sub-accountNumber],tempconsoltb.[sub-accountDescription], tempconsoltb.sumOfCMBaseCurr INTO tblTempConsolTB FROM tempConsolTB;"
Set qdf = CurrentDb.CreateQueryDef("", strSQL)
qdf.Parameters(0) = Forms!frmMain.txtPM
qdf.Parameters(1) = Forms!frmMain.txtPY
qdf.Parameters(2) = Forms!frmMain.cboBaseFX
qdf.Parameters(3) = Forms!frmMain.cboConsolCo
qdf.Execute
Try checking that the objects in your forms are named properly and are actually feeding the values into the query. You can always use the Watch function in your compiler to see the values there or create a string variable that you initialize its value within the code to see what your actual query and put a watch on it when running the code.

MS Access VBA issue

I'm making a report in MS Access - what I'm trying to do here is basically APPEND a query to a table that I've already created - I select the first value, change it and update the table. The issue that I'm coming across is - this report will be used by a VB6 application. So the user won't be seeing Access at all.
The thing with my append query is that it needs a USER ID to run (4 digit number). Normally when I run a report in Access I pass the parameters to a form in Access - and I use them to run queries. However, in this case, I need the user to enter a value when appending the query, additionally, when appending a query in VBA it first says "You are about to append a query, are you sure" (or something along those lines), so is there a way to automate that as well, so when I append it nothing happens?
Here is my code for appending and selecting date from the tempTable:
CurrentDb.Execute "DELETE from [tempCompanyMgmt-NOW];"
DoCmd.OpenQuery "qryCompanyMgmt-SUE" - i made this append!
Set rs1 = CurrentDb.OpenRecordset("Select * from [tempCompanyMgmt-NOW]", , dbOpenDynamic)
So as long as I press OK, YES when I get notified of the APPEND process and enter the parameter for USER ID - everything works fine.
Looks like a typo in your markdown, should the 2nd line be:
DoCmd.OpenQuery "qryCompanyMgmt-SUE - i made this append!"
You'll need to remove the reference to the form inside the qryCompanyMgmt-SUE - i made this append! query, and swap it for a parameter name. You can use the Access interface to explicitly add a parameters clause to the query, and then using ADO (or DAO) from VB6, set a parameter value before you open/execute the query.
The "You are about to append a query, are you sure" message is an Access feature (and it can be disabled), so if you want the VB6 application to provide such a warning, then you'll need to create it yourself with a MsgBox.
One option would by putting your append query into the code and filling in the parameter that way.
I don't know your exact scenario, but something like:
If not isValidUserID(me.UserID) Then
msgbox "Please enter a a valid user id"
exit sub
End If
Dim strSQL As String
strSQL = "DELETE * from [tempCompanyMgmt-NOW];"
CurrentDb.Execute strSQL, dbFailOnError
strSQL = "INSERT INTO tempCompanyMgmt-NOW ( FieldName1, FieldName2, FieldName3 ) " & _
"SELECT FieldName1, FieldName2, FieldName3 FROM tempCompanyMgmt WHERE UseriD=" & Me.UserID
CurrentDb.Execute strSQL, dbFailOnError
To validate the user id you could do something like:
If (Len(me.UserID) = 4 And IsNumeric(me.UserID)) Then
or
Public Function isValidUserID(varUserID As Variant) As Boolean
Dim blnRet As Boolean
If Len(varUserID) = 4 And IsNumeric(varUserID) Then
blnRet = True
End If
isValidUserID = blnRet
End Function
To get rid of the MsgBox telling me I'm about to append a query i included this in my module before I open my append query..
DoCmd.SetWarnings False
And I realized once I have the value passed to the form (userID), that value gets passed on as a parameter when my query gets appended. So it's all set. Thanks for all help!

Importing specific Access table data into Excel using Excel as the front end

I am trying to store and retrieve data that is entered into Excel into Access. I am an Access newbie and already have an Excel program on the front end, leading me to drive the import from Excel. I have successfully figured out how to save my Excel Named Range into the desired Access table, but now I need to figure out how to pull specific data from that Access table back into Excel. I know I can simply use the Get External Data feature from Excel to import the entire Access table into Excel, but I need to be able to only import a specific portion of the table into Excel based upon a predetermined set of parameters. Is this possible to do?
As a background to the program, basically it stores data from part number runs. Not only do I need to save new part runs into an Access database (which I figured out), but I also need to be able to pull previous part number runs from Access back into Excel to perform further analysis. That is why I need to figure out how to import only a specific portion of the table. I'm not sure what code, if any, I can post since I'm basically looking for code from scratch; but if there's any code you think you need from my Excel program I'm happy to provide it. Thanks for your help. Below is the code:
Sub GetSpecData()
Application.ScreenUpdating = False
'*******************************************************************************
'Open the connection to the data source.
Set Connection = New ADODB.Connection
Connection.Open "Provider=Microsoft.Jet.OLEDB.4.0; " & "Data Source=\\Server2013\network_shared\QC SHARED\Databases\P&Q_Tracking_Data_Storage.mdb;"
'*******************************************************************************
'Create the new RecordSet.
Set Recordset = New ADODB.Recordset
With Recordset
'Define the appropriate Filter(s) and notify the user of the selection criteria.
Src = "Select * from Raw_Data where Tag = 'GHI' "
Src = Src & "or Tag = 'DEF' "
Src = Src & "or Tag = 'LMN'"
.Open Source:=Src, ActiveConnection:=Connection
'Write the field names.
For ODCol = 0 To .Fields.Count - 1
Tracking.Sheets("Selected Past Data").Range("B7").Offset(0, ODCol).Value = .Fields(ODCol).Name
Next
'Write the recordset.
Tracking.Sheets("Selected Past Data").Range("B7").Offset(1, 0).CopyFromRecordset Recordset
End With
Set Recordset = Nothing
Connection.Close
Set Connection = Nothing
'*******************************************************************************
'Create and format the table from the Recordset.
With Tracking.Sheets("Selected Past Data")
DataLastRow = .Range("A" & Rows.Count).End(xlUp).row
.ListObjects.Add(xlSrcRange, Range("B7:M" & DataLastRow), , xlYes).Name = "INC2tbl"
.ListObjects("INC2tbl").ShowTotals = True
End With
Application.ScreenUpdating = True
'*******************************************************************************
End Sub
After googling the suggestion in the comment below, I have a couple questions. First, the code above seems to filter access data by three keys: GHI, DEF, and LMN. Am I interpreting that correctly? Second, where it says "Select * from Raw_Data where Tag = 'GHI' ", since that's in quotes, that's not actual code that will be executed, correct? That's simply a prompt or something like it, correct?
SELECT * FROM TABLE; OUTPUT TO TABLEName.EXL
FORMAT sql;
First, the code above seems to filter access data by three
keys: GHI, DEF, and LMN. Am I interpreting that correctly?
Second,
where it says "Select * from Raw_Data where Tag = 'GHI' ", since
that's in quotes, that's not actual code that will be executed,
correct? That's simply a prompt or something like it, correct?
First and second questions relate closely, so I'll answer as one. The basic idea here is that there is a connection to the database you defined (in the Connection.Open statement). The connection itself does nothing then that; establish a connection. The actual communication with the database is done in a specific language, named SQL (there are many dialects, but for simplicity sake, call it SQL for now). So your code in in the VBA language, but the communication with the database is done in SQL. The VBA code has to produce SQL statements (and those are strings, so you need the quotes). That's what the Src variable holds; and SQL statement. In this case:
"Select * from Raw_Data where Tag = 'GHI' or Tag = 'DEF' or Tag = 'LMN'"
I think this is not the place to teach you SQL, but there is plenty information on the net about it. What this statement does is:
select all columns from table "Raw_Data", but only those rows of data that has 'GHI', 'DEF' or 'LMN' in the Tag column.
So to receive all the data from table "part_numbers", you would have to use:
"SELECT * FROM part_numbers;"
And if you need to import only columns "col_1" and "col_2", you would use:
"SELECT col_1,col_2 FROM part_numbers;"
And if you need to import only columns "col_1" and "col_2", and only rows with "part_id" lower than 1000, you would use:
"SELECT col_1,col_2 FROM part_numbers WHERE part_id < 1000;"
That's it really. Now if your recordset (think of it as an array that holds the data you asked for) has queried the database, you can loop it to parse the data. Something like:
Set Recordset = Connection.Execute(Src)
Do until Recordset.EOF
debug.print Recordset!col_1
Recordset.movenext
loop
Again, google something like: "vba excel adodb access", and you'll hit plenty examples.
After researching SQL code formatting more I have made more sense of the subject. Thanks for the help.

Checkbox to SQL Database

I have a problem which I'm struggling to fix.
I have a form with many checkboxes containing email addresses, the result of which is sent to another page.
This page will send out newsletters.
This is working at the moment, but what I would like to do is include their name.
From the form received I get the results (xx#xx.com, yy#yy.com etc...)
I have managed to separate the results and put them into an array, but now I need to access the SQL db and find the names to the email address. This is where I'm struggling. Here is the code that I've tried to use:
name = request.form("list")
If name = "" Then
Response.redirect ("batchselect.asp")
End If
Dim your_name()
Dim mode
Dim mode_a
Dim i
mode=Request("list")
mode_a=split(mode,",")
For i=LBound(mode_a) to UBound(mode_a)
Next
i = i - 1
Redim PRESERVE your_name(i)
For t = 0 to i
Set conn = Server.CreateObject("ADODB.Connection")
conn.open connStr
strSQL = "SELECT name FROM emails WHERE emails = '" & mode_a(t) & "'"
Set rs = conn.Execute(strSQL)
your_name(t) = rs("name")
Next
If I try and run this I get this error:
Error Type:
ADODB.Field (0x800A0BCD)
Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.
I know the problem is in the SQL Query 'mode_a(t)', because if take out the for... next and change this to mode_a(0) or mode_a(1) it works no problem.
I'm using MS SQL and classic asp
Thanks in advance
Not sure why you are doing this:
For i=LBound(mode_a) to UBound(mode_a)
Next
i = i - 1
Surely this would be enough, and you get rid of any ambiguity in the value of i:
i = UBound(mode_a) - 1
If you are not dealing with too many email addresses I would consider trying to use an IN statement with sql and just bring back all the records for the emails. It would be so much quicker and save you a number of db calls.
If you did this then you could just return the email address with the name in the recordset row and use that to match up.
As for your actual question though I would check the value of i and make sure that it is not being set to -1 or some other value that doesn't actually point to an index. Because your error is happening because there are no results being returned. You should consider checking for EOF before you actually use the recordset.