Reference userform data in excel vba sql statements? - sql

I'm trying to reference userform data in SQL queries in excel 2010. When running the following code as my form submit action, I get an error that one or more parameters have not been provided in the SQL query.
Private Sub SubmitButton_Click()
Dim Connection As ADODB.Connection
Dim ConnectionString As String
ConnectionString = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source=I:\DB.xlsx; Extended Properties=""Excel 12.0 Xml; HDR=YES"";"
Dim SQL As String
'Transfer information
SQL = "INSERT INTO [Tests$]" & _
"(PartNo, RootCause, CorrectiveAction, AssignedTo, Verification, Comments, DateOpened, DateClosed, " & _
"Status, Purpose, ProdDate, ShipDate, TestDate, SampleDate, CusName, Facility, Result, Wire, StartingDia, " & _
"WireType, IncomingDia, FailMode, RootCauseDetail)" & _
"VALUES" & _
"([Forms][frmTesting]![PartNo], [Forms][frmTesting]![RCause], [Forms][frmTesting]![Corrective], " & _
"[Forms][frmTesting]![Assigned], [Forms][frmTesting]![Verification], [Forms][frmTesting]![Comments], " & _
"[Forms][frmTesting]![OpenDate], [Forms][frmTesting]![CloseDate], [Forms][frmTesting]![Status], " & _
"[Forms][frmTesting]![Purpose], [Forms][frmTesting]![ProdDate], [Forms][frmTesting]![ShipDate], " & _
"[Forms][frmTesting]![TestDate], [Forms][frmTesting]![SampleDate], [Forms][frmTesting]![Customer], [Forms][frmTesting]![Facility], " & _
"[Forms][frmTesting]![Result], [Forms][frmTesting]![Wire], [Forms][frmTesting]![StartingDia], " & _
"[Forms][frmTesting]![WireType], [Forms][frmTesting]![IncomingDia], [Forms][frmTesting]![FailMode], [Forms][frmTesting]![RCDetail])"
Set Connection = New ADODB.Connection
Call Connection.Open(ConnectionString)
Call Connection.Execute(SQL, , CommandTypeEnum.adCmdText Or ExecuteOptionEnum.adExecuteNoRecords)
Connection.Close
Set Connection = Nothing
End Sub
Am I using the correct form object reference syntax for SQL queries? Is there a difference between Excel and Access with how to reference form data?

In case any viewers run across the same issue and are interested. I found the easiest solution to be something like SQL = "INSERT INTO [Tests$] (PartNo) Values ('" & frmTesting.PartNo & "')"

Related

INSERT INTO - errors, but allows input into table

For reasons I cannot see I get the following error message:
Compile error: Method or data member not found
when I use the following:
Private Sub cmd_Add_Click()
Dim strSQL As String
strSQL = " INSERT INTO BERTHAGE " _
& "(BOAT, LOCATION, BERTH_WEEK, BERTH_YEAR, BERTHED) VALUES " _
& Me.Add_Boat & "','" _
& Me.LOCATION & "','" _
& Me.txt_week & "','" _
& Me.txt_year & "','" _
& Me.In_Port & "');"
cmd_Clear_Click
End Sub
Once I click OK and use the refresh button the entry is put into the database, but each time I do an entry I have to go to the same process.
I would like to figure out what method or data is missing?
I should add that there is an outnumber primary key field on this table (Berth_ID), and each time I use the cmd_Add button a new ID number is created for the new record. This includes creating a new ID number for the new record that triggers the error.
Here is all the VBA associated with this form
Private Sub Form_Load()
DoCmd.RunCommand acCmdRecordsGoToLast
End Sub
Private Sub LOCATION_Change()
Me.txt_Cur_Flo = Me.LOCATION.Column(1)
Me.txt_Cur_Doc = Me.LOCATION.Column(2)
Me.txt_Cur_Ori = Me.LOCATION.Column(3)
End Sub
Private Sub cmd_Add_Click()
Dim strSQL As String
strSQL = " INSERT INTO BERTHAGE " _
& "(BOAT, LOCATION, BERTH_WEEK, BERTH_YEAR, BERTHED) VALUES " _
& Me.Add_Boat & "','" _
& Me.LOCATION & "','" _
& Me.txt_week & "','" _
& Me.txt_year & "','" _
& Me.In_Port & "');"
cmd_Clear_Click
End Sub
Private Sub cmd_Clear_Click()
Me.Add_Boat = ""
Me.LOCATION = ""
Me.txt_Cur_Flo = ""
Me.txt_Cur_Doc = ""
Me.txt_Cur_Ori = ""
Me.Add_Boat.SetFocus
End Sub
Private Sub cmd_Close_Click()
DoCmd.Close
End Sub
Consider the best practice of parameterization and not string concatenation of SQL mixed with VBA variables. Due to missing quotes, the compiler attempts to reference a column name and not its literal value. Instead, consider parameterization with defined types which is supported with Access SQL using QueryDefs. Notice below, SQL and VBA are complete separate.
SQL (save as stored query)
PARAMETERS prmBoat TEXT, prmLoc INT, prmBerthed INT;
INSERT INTO BERTHAGE (BOAT, LOCATION, BERTHED)
VALUES(prmBoat, prmLoc, prmBerthed)
VBA
Dim db As Database
Dim qdef As QueryDef
Dim strSQL As String
Set db = CurrentDb
Set qdef = db.QueryDefs("mySavedParamQuery")
' BIND PARAM VALUES
qdef!prmBoat = Me.Add_Boat
qdef!prmLoc = Me.LOCATION
qdef!prmBerthed = Me.In_Port
' EXECUTE ACTION QUERY
qdef.Execute
Set qdef = Nothing
Set db = Nothing
Even better, save your query with form controls intact and simply call OpenQuery:
SQL (save as stored query)
INSERT INTO BERTHAGE(BOAT, LOCATION, BERTHED)
VALUES(Forms!myForm!Add_Boat, Forms!myForm!LOCATION, Forms!myForm!In_Port)
VBA
Private Sub cmd_Add_Click()
Dim strSQL As String
DoCmd.SetWarnings False ' TURN OFF APPEND PROMPTS
DoCmd.OpenQuery "mySavedActionQuery"
DoCmd.SetWarnings True ' RESET WARNINGS
Call cmd_Clear_Click
End Sub
Missing opening parenthesis after VALUES. Also missing apostrophe in front of Me.Add_Boat. These special characters must always be in pairs, an even number by counting.
If Berth_Week and Berth_Year are number fields (and should be), don't use apostrophe delimiters.
If In_Port is a Yes/No field, don't use apostrophe delimiters.
The issue appears to be that I was doubling up the inputs into the 'week' and 'year' field. this was happening (I believe) because those text box fields were already accessing the week and year information directly from the default value on the BERTHAGE table. Essentially I went through each input and would run it individually waiting for the error to occur. Once it occurred I took it out of the INSERT INFO statement. With the removal of week and year, everything is working. That was a painful exercise, and still not complete, but I am back to a function form/DB so I'll take the small victories when they occur.
Private Sub cmd_Add_Click()
Dim strSQL As String
CurrentDb.Execute " INSERT INTO BERTHAGE " & "(BOAT, LOCATION, BERTHED) VALUES ('" & Me.Add_Boat & "'," _
& Me.New_Loc & "," _
& Me.In_Port & ");"
cmd_Clear_Click
DoCmd.Requery
End Sub`

SQL query works in access but not in excel

I need to get data from a recordset. The SQL query works fine in MS Access and returns exactly the expected values, but when the same query is lunched in VBA Excel, I get the following error:
No value given for one or more required parameters
Do you have any ideas why this problem occurs?
Thank you.
Philippe-Olivier Roussel
Private Sub CBtype_AfterUpdate()
Dim strConnexion As String
Dim connexion As New ADODB.Connection
strConnexion = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & Database & ""
connexion.Open strConnexion
Dim rsMarque As New ADODB.Recordset
Dim seltype As String
seltype = CBtype.Value
rsMarque.Open "SELECT DISTINCT tblMarque.marque_nom FROM tblMarque, tblModele WHERE " & _
" tblMarque.marque_id = tblModele.marque_id AND tblModele.marque_id IN " & _
" (SELECT DISTINCT tblModele.marque_id FROM tblModele, tblType " & _
" WHERE tblModele.type_id = tblType.type_id AND tblModele.type_id = " & _
" (SELECT tblType.type_id FROM tblType WHERE " & _
" (tblType.type_nom = " & seltype & ")))", connexion, adOpenStatic
rsMarque.MoveFirst
With UserForm2.CBmarque
.Clear
Do
.AddItem rsMarque!marque_nom
rsMarque.MoveNext
Loop Until rsMarque.EOF
End With
End Sub
This error message looks like an output from the DBMS rather than Excel
I think you might be missing the apostrophe before and after your string variable. See if
" (tblType.type_nom = '" & seltype & "')))" works (I'm assuming the column you're querying is varchar type, since you declared seltype as string)

VB.NET Update to Excel

I am developing an application in Visual Basic using Visual Studio 2013. In this application I am attempting to use an oledb UPDATE to write data out to an Excel spreadsheet treated as a database. I have tried numerous different formats of this but I either get a syntax error or it pretends to work but nothing actually gets written to the file. Can anyone tell me what is wrong with this code:
Public Function WriteToExcel(ExcelPath As String, dtUser As DataTable)
Dim vOffice As String = dtUser.Rows(0).Item("Office").ToString
Dim vDivision As String = dtUser.Rows(0).Item("Division").ToString
Dim vSection As String = dtUser.Rows(0).Item("Section").ToString
Dim vUser As String = dtUser.Rows(0).Item("UserID").ToString
Dim ExcelconnString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath & ";Extended Properties='Excel 12.0 Xml;HDR=YES';"
Dim BatchID As Long = 0
Dim sql As String = "UPDATE [InstallationReport$] SET Office = #uOffice WHERE [Primary User] = #uUser"
'Dim sql As String = "UPDATE [InstallationReport$] SET Office = #uOffice, " & _
'"Division = #uDivision, " & _
'"Section = #uSection " & _
'"WHERE [Primary User] = #uUser"
Using conn As New OleDb.OleDbConnection(ExcelconnString)
Dim cmd As New OleDb.OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("#uOffice", vOffice)
cmd.Parameters.AddWithValue("#uDivision", vDivision)
cmd.Parameters.AddWithValue("#uSection", vSection)
cmd.Parameters.AddWithValue("#uUser", vUser)
Try
MessageBox.Show("Attempting to update " & vUser & ". " & vOffice & ", " & vDivision & ", " & vSection & "!")
conn.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show(ex.Message & vbNewLine & ex.StackTrace)
End Try
End Using
End Function
Your SQL has two issues:
OleDbCommands use question marks ? as the placeholder for parameters, not #parameterName (that's for SqlCommands).
Section is a reserved keyword, so it needs to be escaped: [Section].

SQL Program UPDATE Record Error

I'm working in a small SQL Database program. The programs just there to view, edit and update the database records. Everything is working remarkably well considering I've never tried something like this before. I've managed to get the Add Records, Refresh Records and Delete Records functions working flawlessly. However, I've hit a little bump when trying to UPDATE a selected record.
To clarify, the SQL Table is displayed in a list view, from this list view the end-user can select a particular-record and either edit or delete it.
The edit button opens a new form window with text fields which are automatically filled with the current information of that record.
The code for the edit record form is:
Private Sub frmEdit_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
intDB_ID_Selected = CInt(frmMain.lvRec.SelectedItems(0).Text)
Call dispCaption()
Call dispInfo() 'Display the info of the selected ID
End Sub
Private Sub dispInfo()
SQL = "Select * from PersonsA " & _
"where Members_ID=" & intDB_ID_Selected & ""
With comDB
.CommandText = SQL
rdDB = .ExecuteReader
End With
If rdDB.HasRows = True Then
rdDB.Read()
Me.midtxt.Text = rdDB!Members_ID.ToString.Trim
Me.gttxt.Text = rdDB!Gamer_Tag.ToString.Trim
Me.sntxt.Text = rdDB!Screenname.ToString.Trim
Me.fntxt.Text = rdDB!First_Name.ToString.Trim
Me.lntxt.Text = rdDB!Last_Name.ToString.Trim
Me.dobtxt.Text = rdDB!DoB.ToString.Trim
Me.dobtxt.Text = rdDB!DoB.ToString.Trim
Me.emailtxt.Text = rdDB!E_Mail_Address.ToString.Trim
Me.teamptxt.Text = rdDB!Position.ToString.Trim
Me.ugctxt.Text = rdDB!Cautions.ToString.Trim
Me.recordtxt.Text = rdDB!Record.ToString.Trim
Me.eventatxt.Text = rdDB!Event_Attendance.ToString.Trim
Me.Mstattxt.Text = rdDB!Member_Status.ToString.Trim
End If
rdDB.Close()
End Sub
Private Sub dispCaption()
End Sub
Private Sub cmdUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdUpdate.Click
Call disControl()
'Validation
If invalidUpdateEntry() = True Then
Call enaControl()
Exit Sub
End If
'Prompt the user if the record will be updated
If MsgBox("Are you sure you want to update the selected record?", CType(MsgBoxStyle.YesNo + MsgBoxStyle.DefaultButton2 + MsgBoxStyle.Question, MsgBoxStyle), "Update") = MsgBoxResult.Yes Then
'Update query
SQL = "Update PersonsA" & _
"SET Members_ID='" & Me.midtxt.Text.Trim & "'," & _
"Gamer_Tag='" & Me.gttxt.Text.Trim & "'," & _
"Screenname='" & Me.sntxt.Text.Trim & "'," & _
"First_Name='" & Me.fntxt.Text.Trim & "'," & _
"Last_Name='" & Me.lntxt.Text.Trim & "'," & _
"DoB='" & Me.dobtxt.Text.Trim & "'," & _
"E_Mail_Address='" & Me.emailtxt.Text.Trim & "'," & _
"Position='" & Me.teamptxt.Text.Trim & "'," & _
"U_G_Studio='" & Me.ugptxt.Text.Trim & "'," & _
"Cautions='" & Me.ugctxt.Text.Trim & "'," & _
"Record='" & Me.recordtxt.Text.Trim & "'," & _
"Event_Attendance='" & Me.eventatxt.Text.Trim & "'," & _
"Member_Status='" & Me.Mstattxt.Text.Trim & "'" & _
"WHERE Members_ID='" & intDB_ID_Selected & "'"
Call execComDB(SQL) 'Execute the query
Me.Close()
'*** Refresh the list
SQL = "Select * from PersonsA "
Call frmMain.dispRec(SQL)
'--- End of refreshing the list
Exit Sub
Else
Call enaControl()
End If
End Sub
As I've said, I've been able to do everything else using an extremely similar method, but when I try to UPDATE the record I get an error saying
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Incorrect syntax near 'Members_ID'.
I know it's this line that's the problem
"WHERE Members_ID='" & intDB_ID_Selected & "'"
Call execComDB(SQL) 'Execute the query
But referencing 'intDB_ID_Selected' has always worked before, and it's been set-up on the update form records load as intDB_ID_Selected = CInt(frmMain.lvRec.SelectedItems(0).Text)
I know this is a huge thread but if anyone could steer me in the right direction WITHOUT telling me to re-write the entire statement I'd be forever grateful.
EDIT1: I fixed the comma before the WHERE clause, but I'm still getting the same error.
Missing a space between
"Update PersonsA " & _
"SET Members_ID= ....
and (as already pointed out) a comma not needed before the WHERE
Said that, do a favor to yourself and to your users. Do not use string concatenation to build a sql command. Use always a parameterized query.
Just as an example
SQL = "Update PersonsA SET Members_ID=#id, Gamer_Tag=#tag, Screenname=#screen," & _
"First_Name=#fname,Last_Name=#lname,DoB=#dob,E_Mail_Address=#email," & _
"Position=#pos,U_G_Studio=#studio,Cautions=#caution,Record=#rec," & _
"Event_Attendance=#event, Member_Status=#stat " & _
"WHERE Members_ID=#id"
SqlCommand cmd = new SqlCommand(SQL, connection)
cmd.Parameters.AddWithValue("#id", Me.midtxt.Text.Trim)
..... so on for the other parameters defined above ....
cmd.ExecuteNonQuery();
Change "Member_Status='" & Me.Mstattxt.Text.Trim & "'," & _
to "Member_Status='" & Me.Mstattxt.Text.Trim & "'" & _
Looks like it was just an extra rogue comma!
On any error like this, use debugging provided with Visual Studio. Inspect the value of SQL, paste into MS SQL Management Studio - it has syntax highlight, and you should be able to spot the error easily.
To prevent further issues (including SQL injection vulnerability), separate this query into an embedded resource, and use parameters. Then it's easy to view, maintain (you can copy/paste between SQL Mgmt Studio and VS), and ultimately use it in code.
A side note, you don't need to use Call in VB.NET, just put a method name with parenthesis.

VBA string length problem

I have an Access application where everytime a user enters the application, it makes a temp table for that user called 'their windows login name'_Temp. In one of my reports I need to query using that table, and I can't just make a query and set it as the recourdsource of the report, since the name of the table is always different.
What I tried then was to programatically set the recordset of the report by running the query and setting the form's recordset as the query's recordset. When I tried this, it kept giving me an error about the query.
I tried to debug, and I found that the string variable isn't able to contain the whole query at once. When I ran it with break points and added a watch for the string variable, it shows me that it cuts off the query somewhere in the middle.
I've experienced this problem before, but that was with an UPDATE query. Then, I just split it into two queries and ran both of them separately. This one is a SELECT query, and there's no way I can split it. Please help!
Thank you
Heres what I've tried doing:
ReturnUserName is a function in a module that returns just the login id of the user
Private Sub Report_Open(Cancel As Integer)
Dim strQuery As String
Dim user As String
user = ReturnUserName
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse INNER JOIN (" & user & "_Temp INNER JOIN tblEmpCourses ON " & _
user & "_Temp.EmpNumber = EmpNo) ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin ON " & user & "_Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber" & _
"WHERE (((" & user & "_Temp.EmpNumber) = [Forms]![Reports]![txtEmpID].[Text])) " & _
"ORDER BY CourseName;"
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim rsCmd As ADODB.Command
Set rsCmd = New ADODB.Command
rsCmd.ActiveConnection = CurrentProject.Connection
rsCmd.CommandText = strQuery
rs.Open rsCmd
Me.Recordset = rs
rs.Close
End Sub
This what strQuery contains when I add a breakpoint on rsCmd.CommandText = strQuery:
SELECT myusername_Temp.EmpNumber, [FName]
& ' ' & [LName] AS [Employee Name],
CourseName, DateCompleted,
tblEmp_SuperAdmin.[Cost Centre] FROM
(tblCourse INNER JOIN (myusername_Temp
INNER JOIN tblEmpCourses ON
myusername_Temp.EmpNumber = EmpNo) ON
tblCourse.CourseID=
(It's all one line, but I've written it like this because the underscores italicize the text)
And the error I get says Run Time Error: Join not Supported.
Not quite what I was hoping for, but guessing, for:
strQuery = "long query goes here"
Try:
strQuery = "some long query goes here "
strQuery = strQuery & "more query goes here "
BASED ON NEW INFORMATION:
strQuery = "SELECT " & user & "_Temp.EmpNumber, [FName] & ' ' & [LName] AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM (tblCourse " & _
"INNER JOIN tblEmpCourses ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN (Temp INNER JOIN tblEmp_SuperAdmin " & _
"ON Temp.EmpNumber = tblEmp_SuperAdmin.EmpNumber) " & _
"ON Temp.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE " & user & "_Temp.EmpNumber = " & [Forms]![Reports]![txtEmpID] & _
" ORDER BY CourseName;"
Note that in VBA:
& [Forms]![Reports]![txtEmpID].[Text] &
That is, the reference to the form must go outside the quotes so you get the value.
NEW INFORMATION #2
Your best bet would be to add these tables to the Access query design window and create the joins that you want, then switch to SQL view and use the string generated for you. I do not believe that the string is too long, only that the SQL is incorrect. The SQL I posted above should work, but it may not be what you want.
You can programmatically create a querydef that fits the user. So, when your report is called, you
Delete LoginName_Query_Temp (CurrentDb.QueryDefs.Delete), if it already exists.
Create the querydef (CurrentDB.CreateQueryDef), using LoginName_Temp as the table name.
Set the RecordSource of your Report to LoginName_Query_Temp.
Open the report.
I don't see what purpose the table myusername_Temp serves here. Is that where the name fields are? If so, avoid the join entirely:
Dim lngEmpNumber As Long
Dim strName As String
Dim strSQL As String
lngEmpNumber = Forms!Reports!txtEmpID
strName = DLookup("[FName] & ' ' & [LName]", "myusername_Temp", "EmpNumber=" & lngEmpNumber
strSQL = "SELECT " & Chr(34) & strName & Chr(34) & " AS [Employee Name], " & _
"CourseName, DateCompleted, tblEmp_SuperAdmin.[Cost Centre] " & _
"FROM tblCourse " & _
"INNER JOIN tblEmpCourses " & _
"ON tblCourse.CourseID = tblEmpCourses.CourseID) " & _
"INNER JOIN tblEmp_SuperAdmin " & _
"ON tblEmp_SuperAdmin.EmpNumber = tblEmpCourses.EmpNo " & _
"WHERE tblEmp_SuperAdmin.EmpNumber = " & lngEmpNumber & _
" ORDER BY CourseName;"
Now, the parentheses may need to be changed in the join (I always do my equi-joins in the Access QBE and let it take care of the getting the order and parens correct!), and my assumptions about the purpose of the temp table may be wrong, but I don't see it being used for anything other than as an intermediate link between tables, so I guessed it must be there to provide the name fields.
If that's wrong, then I'm at a loss as to why the temp table needs to be there.
Also, in your second post you referred to the control on the form as:
Forms!Reports!txtEmpID.Text
...the .Text property of Access controls is accessible only when the control has the focus. You could use the .Value property, but since that's the default property of Access controls, you should just stop after the name of the control:
Forms!Reports!txtEmpID
...you'll see this is how I did it in my suggested code.
I find the idea of your name-based temp table to be highly problematic to begin with. Temp tables don't belong in a front end, and it's not clear to me that it is actually a temp table. If it's temp data, put it in a shared table and key the record(s) to the username. Then you don't have to worry about constructing the table name on the fly.