I'm trying to create a dynamic MySQL INSERT INTO...WHERE NOT EXIST statement by parsing the table name, array of columns, array of values and conditional column and value to a subroutine in a separate module but i keep hitting the Column count doesn't match value count at row 1 error. Below is the code:
Sub InsertRecord(ByVal tbl As String, ByVal cols() As String, ByVal params() As String, _
ByVal colCondition As String, ByVal paramCondition As String) 'As String
'Create new string of columns
Dim myCols As String = ""
For Each col As String In cols
myCols &= col & ", "
Next
Dim newCols As String = myCols.Remove(myCols.Count - 2, 2)
MsgBox(newCols)
Dim scols As String = newCols.Insert(0, "`").Replace(", ", "`, `") & "`"
MsgBox(scols)
'Create new string of parameters
Dim myParams As String = ""
For Each param In params
myParams &= param & ", "
Next
Dim newParams As String = myParams.Remove(myParams.Count - 2, 2)
MsgBox(newParams)
Dim sparams As String = newParams.Insert(0, "'").Replace(", ", "', '") & "'"
MsgBox(sparams)
'End
Dim p As String = paramCondition.Insert(0, "'") & "'"
'Try
'Dim insRemarks As String = "done"
con = New MySqlConnection("Server=localhost; Database=etms; Uid=root; Pwd=;")
comA = New MySqlCommand
'INSERT NEW RECORD.
'THIS GIVES THE ERROR
comA.CommandText = "INSERT INTO " & tbl & " (" & scols & ") SELECT * FROM (SELECT #params) AS tmp "
comA.CommandText &= "WHERE NOT EXISTS (SELECT " & colCondition & " FROM " & tbl & " WHERE " & colCondition & " = #param) limit 1"
comA.Parameters.AddWithValue("#param", p)
comA.Parameters.AddWithValue("#params", sparams)
'THIS STATIC CODE WORKS FINE.
'comA.CommandText = "INSERT INTO state (`st_state`, `ctry_Id`) SELECT * FROM (SELECT 'a', '1') AS tmp "
'comA.CommandText &= "WHERE NOT EXISTS (SELECT st_state FROM state WHERE st_state = 'a') limit 1"
comA.Connection = con
con.Open()
comA.ExecuteNonQuery()
con.Close()
'Release used up components
comA.Parameters.Clear()
comA.Dispose()
comA = Nothing
con = Nothing
MsgBox("done.")
'Return insRemarks
'Catch ex As Exception
'MsgBox(ex.Message.ToString & vbCrLf & vbCrLf & comA.CommandText.ToString)
'Return "Error"
'End Try
End Sub
As seen, i tried a lot of permutations (introducing inverted quotation marks) to no avail.
I'll be glad if someone could help out.
Related
I am working on a custom VBA script that dynamically collects user-entered form data and inserts it into a MySQL database. My problem is, to convert form field data into an SQL script, I have to use string functions; thus, all my data, including dates, gets inserted as text. I need to convert all the dates the form collects from m/d/yyyy format to yyyy-mm-dd format for my MySQL database to infer schema and load date data into DB without an error. I need to do so dynamically, meaning, the script has to work regardless of how many date fields are collected. I have:
Private Sub Submit_Button()
Dim doc as Document
Dim control As ContentControl
Dim FormDateField As Date
Dim ReportNumber As String
Dim myValues As String
Dim myFields As String
Dim conn As ADODB.Connection
Dim strSQL As String
Set doc = Application.ActiveDocument
Set conn = New ADODB.Connection
conn.open "DSN=ABCD"
For Each control In doc.ContentControls
Skip = False
If Left(control.Range.Text, 5) = "Click" Or Left(control.Range.Text, 6) = "Choose" Then
Skip = True
Else:
myFields = myFields & control.Tag
myValues = myValues & "'" & control.Range.Text & "'"
End If
If Not Skip Then
myFields = myFields & ", "
myValues = myValues & ", "
End If
Next
myFields = Left(myFields, Len(myFields) - 2)
myValues = Left(myValues, Len(myValues) - 2)
strSQL = "INSERT INTO TABLE_1 ("
strSQL = strSQL & myFields
strSQL = strSQL & ") VALUES (" & myValues
strSQL = strSQL & ")"
conn.Execute strSQL
MsgBox "Form data saved to database!"
conn.Close
End Sub
However, my program is crashing because it is trying to insert a string into the date field (the actual final form will have many date fields.) I thought if I change the date format to MySQL format, it may be able to infer schema? I tried adding
If IsDate(control.Range.Text) Then
control.Range.Text = Format(control.Range.Text, "yyyy-mm-dd")
Else FoundOne = False
End If
and I know in Excel you can do:
Application.FindFormat.NumberFormat = "m/d/yyyy"
Application.ReplaceFormat = "yyyy-mm-dd"
Any suggestions? Thank you.
Assuming all dates are in date-picker content controls, you could use:
Private Sub Submit_Button()
Dim CCtrl As ContentControl, bSv As Boolean, DtFmt As String
Dim myFields As String, myValues As String, strSQL As String
With ActiveDocument
bSv = .Saved
For Each CCtrl In .ContentControls
With CCtrl
If .ShowingPlaceholderText = False Then
Select Case .Type
Case wdContentControlDate
DtFmt = .DateDisplayFormat
.DateDisplayFormat = "YYYY-MM-DD"
myFields = myFields & .Tag & ", "
myValues = myValues & "'" & .Range.Text & "', "
.DateDisplayFormat = DtFmt
Case wdContentControlRichText, wdContentControlText, wdContentControlDropdownList, wdContentControlComboBox
myFields = myFields & .Tag & ", "
myValues = myValues & "'" & .Range.Text & "', "
Case Else
End Select
End If
End With
Next
.Saved = bSv
End With
If myFields <> "" Then
myFields = Left(myFields, Len(myFields) - 2)
myValues = Left(myValues, Len(myValues) - 2)
strSQL = "INSERT INTO TABLE_1 (" & myFields & ") VALUES (" & myValues & ")"
Dim Conn As New ADODB.Connection
With Conn
.Open "DSN=ABCD": .Execute strSQL: .Close
End With
Set Conn = Nothing
MsgBox "Form data saved to database", vbInformation
Else
MsgBox "No form data found", vbExclamation
End If
End Sub
As you noticed, Word does not have Application.FindFormat or Application.ReplaceFormat, but if you know the format is m/d/y you should be able to do this:
myValues = myValues & "'" & ymd(control.Range.Text) & "'"
Function ymd(s as String) As String
Dim v As Variant
v = VBA.split(s, "/")
ymd = Right("0000" & v(2),4) & "-" & Right("00" & v(0),2) & "-" & Right("00" & v(1),2)
End Function
Everything else (e.g. the way you add commas to the list of dates) looks fine but I have not tested.
I have 8 combo boxes in an Access database. Each combo box can either have a value or not have a value (2 options). In total, there can be 256 combinations (2^8). I am trying to create some code in VBA that loops through these combinations to determine which combination currently exists, with the ultimate goal of writing an SQL query within VBA based on that combination. So for example, let's say combo1 and combo2 both have selections, but not combo3 through combo8. If that is the combination I would like my SQL query to do a SELECT FROM query WHERE a column in db = combo1 and a column in db = combo2. Can anyone provide hints as to how I would structure my code?
Thanks!
Dim a as string, b as string
const myAND as string = "AND "
a = ""
a = "SELECT * FROM a table "
b = ""
if cbo1.value <> "" then
b = b & myAND & "AND field1 = '" & cbo1.value & "'"
end if
if cbo2.value <> "" then
b = b & myAND & "field2 = '" & cbo2.value & "'"
end if
etc for each cbo box
If b <> "" Then
' Lazy way
' a = a & "WHERE 1=1 " & b
' remove the first AND way
a = a & "WHERE 1=1 " & mid(b,len(myAND))
End if
' a now contains the SQL you need.
Dim where_condtion as String
Dim sqlquery as String
where_condtion = ""
IF combo1 <>"" then
where_condtion = where_condtion + "~fieldname~ = " & combo1
End IF
IF combo2 <>"" then
where_condtion = where_condtion + "AND ~fieldname~ = " & combo2
End IF
*
*
*
IF combo8 <>"" then
where_condtion = where_condtion + "AND ~fieldname~ =" & combo8
End IF
IF where_condtion <> "" then
sqlquery = "Select * from ~table name~ where" + where_condtion
ELSE
sqlquery = "Select * from ~table name~
End IF
sqlquery = Replace(sqlquery, "where AND ", "where ")
DoCmd.OpenQuery "sqlquery", acViewNormal, acEdit
OR
CurrentDb.OpenRecordset("sqlquery")
Am option would be a concatenated string
Code Example
Dim strSQL as String
'basic string
strSQL = "SELECT tbl.fieldA, tbl.fieldB FROM tbl "
Dim strSQLwhere as String
strSQLwhere = ""
'Combobox cmbbox1
If Not isNull(cmbbox1) And cmbbox1.ListIndex <> -1 then
strSQLwhere = strSQLwhere & "tbl.fieldToFilter1=" & cmbbox1
End if
'Combobox cmbbox2
If Not isNull(cmbbox2) And cmbbox2.ListIndex <> -1 then
iF NOT strSQLwhere = "" then
strSQLwhere = strSQLwhere & " AND "
end if
strSQLwhere = strSQLwhere & "tbl.fieldToFilter2=" & cmbbox2
End if
'And so on until cmbBox 8
'Combine all Strings
if not strSQLwhere = "" then
strSQL = strSQL & " WHERE (" & strSQLwhere & ")"
End if
'Add here further thing like ORDER BY, GROUP BY
'Show SQL sting if it is well fomratted, change string concatenation if not
debug.print strSQL
You could do the combobox if-then-(else) cases in a separate function if you are able to do that in VBA.
I am trying to use a single SQL command to do two selects I want to select related data and insert it in another table from another database, but it isn't working, I am new to this, can someone help me? Thanks in advance.
Try
If CreateAccessDatabase("C:\Users\Utilizador.Utilizador-PC\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\Doc_Vendas_Cab.mdb") = True Then
MsgBox("Database Created")
Else
MsgBox("Database Creation Failed")
End If
Dim Sql As String = "Select strCodSeccao,strAbrevTpDoc,strCodExercicio,intNumero " & _
"From Mov_Venda_Cab where dtmdata between #d1 and #d2; Union" & _
"Select Mov_Venda_Lin.Strcodartigo" & _
"from Mov_Venda_Lin,Mov_Venda_Cab where Mov_Venda_Cab.intnumero=Mov_Venda_Lin.intnumero;"
Dim data1, data2 As DateTime
data1 = DateTime.Parse(txtData1.Text)
data2 = DateTime.Parse(txtData2.Text)
data2 = data2.AddMinutes(0)
data2 = data2.AddHours(0)
data2 = data2.AddSeconds(0)
data1 = data1.AddMinutes(0)
data1 = data1.AddHours(0)
data1 = data1.AddSeconds(0)
Dim x As Integer = 0
Dim temp1, temp2, temp3, temp4, temp5 As String
Using con = New SqlConnection("Data Source=" & txtserv.Text & ";" & "Initial Catalog=" & txtBD.Text & ";" & "User ID=" & txtuser.Text & ";" & "Password=" & txtPass.Text & "")
Using cmd = New SqlCommand(Sql, con)
con.Open()
cmd.Parameters.AddWithValue("#d1", data1)
cmd.Parameters.AddWithValue("#d2", data2)
Using reader = cmd.ExecuteReader()
While reader.Read()
Dim strCodSeccao = reader("strCodSeccao").ToString()
temp1 = reader.Item(x)
temp2 = reader.Item(x + 1)
temp3 = reader.Item(x + 2)
temp4 = reader.Item(x + 3)
temp5 = reader.Item(x + 4)
Dim Con2 As New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Utilizador.Utilizador-PC\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\Doc_Vendas_Cab.mdb;Persist Security Info=True")
Con2.Open()
Dim Ole2 As String = "Insert into Mov_Venda_Cab values('" & temp1 & "','" & temp2 & "','" & temp3 & "','" & temp4 & "','" & temp5 & "');"
Dim OledbCom2 As New OleDb.OleDbCommand(Ole2, Con2)
Try
OledbCom2.ExecuteNonQuery()
Catch Ex As Exception
MsgBox(Ex)
End Try
Con2.Close()
End While
End Using
End Using
End Using
Catch Ex As Exception
MsgBox(Ex)
End Try
Your INSERT statement encloses all the values in single quotes. This will only work if the corresponding columns are all text columns (varchar, nvarchar etc.). Use command parameters instead:
Dim Ole2 As String = "Insert into Mov_Venda_Cab values(#p1, #p2, #p3, #p4, #p5);"
Dim OledbCom2 As New OleDb.OleDbCommand(Ole2, Con2)
OledbCom2.Parameters.AddWithValue("#p1", temp1)
OledbCom2.Parameters.AddWithValue("#p2", temp2)
OledbCom2.Parameters.AddWithValue("#p3", temp3)
OledbCom2.Parameters.AddWithValue("#p4", temp4)
OledbCom2.Parameters.AddWithValue("#p5", temp5)
This will work for any column type.
Also your SELECT statement lists only four columns, but you are accessing five columns in the reader.
SELECT strCodSeccao, strAbrevTpDoc, strCodExercicio, intNumero FROM ...
Other things in your code are strange as well. Your are defining two connections that are never used later.
You are adding zero hours, minutes and seconds to a date (this will not change the date). If you want the date part of the date without the time part, use the Date property instead, which returns the date component of the DateTime structure:
data1 = DateTime.Parse(txtData1.Text).Date
You are using a variable x for constant values.
You are opening and closing Con2 in the While-loop. Open it before the loop and close it after the loop. (You can do it with a Using-statement as for the other connection.)
im currently facing problem with executeScalar when i create custom ID. the error is
InvalidOperationException was unhandled by user code.
Message=Connection must be valid and open.
Below is my code :
Dim str As String = "select isnull(max(idcr_record),0)+1 from cr_record where Emplid = '" & Session("Emplid") & "'"
Dim com As New MySqlCommand()
'this line was the error
'
Dim count As Integer = Convert.ToInt32(com.ExecuteScalar())
If count = 1 Then
'insert if no record found
'
Dim cc As New MySqlCommand("insert into cr_record values (" & count & "," & Session("Emplid") & ")")
cc.ExecuteNonQuery()
Else
'update becoz record already exist
'
Dim upd As String = "update cr_record set idcr_record = " & count & " where Emplid = " & Session("Emplid") & " "
Dim cc As New MySqlCommand(upd)
cc.ExecuteNonQuery()
End If
Dim length As Integer = 0
Dim val As String = Convert.ToString(count)
length = val.Length
If length = 1 Then
val = "CR " + "00000" & Convert.ToString(count)
End If
If length = 2 Then
val = "CR " + "0000" & Convert.ToString(count)
End If
If length = 3 Then
val = "CR " + "000" & Convert.ToString(count)
End If
If length = 4 Then
val = "CR " + "00" & Convert.ToString(count)
End If
If length = 5 Then
val = "CR " + "0" & Convert.ToString(count)
End If
cr_id = "" & val
At least, you need to pass your SQL command string and SqlConnection object to SqlCommand object before you can execute the command :
Dim str As String = "select isnull(max(idcr_record),0)+1 from cr_record where Emplid = '" & Session("Emplid") & "'"
Dim conn As New MySqlConnection
conn.ConnectionString = "....."
'pass your SQL command string and MySqlConnection object to MySqlCommand
'
Dim com As New MySqlCommand(str, conn)
conn.Open()
Dim count As Integer = Convert.ToInt32(com.ExecuteScalar())
I want to run a script in my macro multiple times by changing variable values.
Below is an example of my code that I run for one value.
The line of code I would like to change is
sScript = sScript + "where m.outletid in ('" & sOutletId & "') " & vbCrLf
Sometime I want the where clause to be
where m.outletid in ('12314')
or
where m.chainid in ('411')...
Code:
Sub Report()
Dim sScript As String
Dim sServer As String
Dim sDatabase As String
Dim sTransTable As String
Dim iVal As Integer
Dim iReturnVal As Integer
Dim SheetExists As Worksheet
Dim WK_SHEET As String
sServer = Trim(UserForm1.txtServer.Value)
sDatabase = Trim(UserForm1.txtDatabase.Value)
sTransTable = Trim(UserForm1.txtTransTable.Value)
For Each SheetExists In Worksheets
If SheetExists.Name = ("Report") Then
Application.DisplayAlerts = False
Sheets("Report").Delete
Application.DisplayAlerts = True
Exit For
End If
Next SheetExists
Worksheets.Add after:=Sheets("Sheet1")
ActiveSheet.Name = ("Report")
WK_SHEET = "Report"
Sheets(WK_SHEET).Select
sOutletId = "12314"
sScript = "Select top 10 m.CustNumber, m.Name, sum(t.Transvalue) " & vbCrLf
sScript = sScript + "from " & sTransTable & " t " & vbCrLf
sScript = sScript + "where m.outletid in ('" & sOutletId & "') " & vbCrLf
sScript = sScript + "Group by m.CustNumber, m.Name " & vbCrLf
sScript = sScript + "order by sum(t.Transvalue)Desc " & vbCrLf
iReply = MsgBox(Prompt:="Do you wish to continue with the following script for Top 10 Customers?" + sScript + "", _
Buttons:=vbYesNo, Title:="Run MACRO Top 10 Reports")
If iReply = vbNo Then
End
End If
iVal = execute_sql_select(WK_SHEET, 2, 1, sServer, sDatabase, sScript)
Sheets(WK_SHEET).Name = "Outlet" & sOutletId & "Top 10 by Spend"
Now I would like to re run the above with OutletId 12315...how can I do this? Do I use some sort of loop?
You can keep list of OutletId into Array. Then get each OutletId from Array (for loop) and execute your sql script.
Pseudu code
Array listOutid = new Array[12,13,14,15];
for(int idx = 0; idx < listOutid.Length; idx++)
{
var OutletId = listOutid[idx];
//put ur sql statement and execute here..
}