I have a problem with MSchart control. I have 2 fields on my database for date and time.
When I connect to my database and load X and Y values to my chart, there is no problem, but when i use search between 2 date in my query then mschart loads nothing. I'm using Text format for inDate1 and inTime1, here is my code:
Dim con As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel
Dim query As String = "SELECT inDate1,inTime1 FROM loginlog where personID=" + TextBox1.Text+" and inDate1 between "+ TextBox2.Text " and " + TextBox3.Text
Dim mycon As New OleDbConnection(con)
Dim command As New OleDbCommand(query, mycon)
mycon.Open()
chart1.DataSource = command.ExecuteReader()
chart1.Series(0).XValueMember = "inDate1"
chart1.Series(0).YValueType = ChartValueType.Time
chart1.Series(0).YValueMembers = "inTime1"
chart1.DataBind()
mycon.Close()
You really do not want to use text for dates. Instead, convert them to DateTimes (e.g. with DateTime.TryParse) and pass them as SQL parameters.The remark about passing as an SQL parameter applies to all parameters, including the personID.
So, your code could look something like:
Dim startDate As DateTime
Dim endDate As DateTime
If Not DateTime.TryParse(TextBox2.Text, startDate) Then
' there was an error parsing - do something useful
startDate = New DateTime(2000, 1, 1)
End If
If Not DateTime.TryParse(TextBox3.Text, endDate) Then
' there was an error parsing - do something useful
endDate = New DateTime(2100, 12, 31)
Else
' add a day to include it in the range selected in the SQL query
endDate = endDate.AddDays(1)
End If
Dim query As String = "SELECT inDate1, inTime1 FROM loginlog WHERE personID = #PersonID AND inDate1 BETWEEN #StartDate AND #EndDate"
Dim mycon As New OleDbConnection(con)
Dim command As New OleDbCommand(query, mycon)
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#PersonID", .OleDbType = OleDbType.VarWChar, .Value = TextBox1.Text})
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#StartDate", .OleDbType = OleDbType.Date, .Value = startDate})
command.Parameters.Add(New OleDbParameter With {.ParameterName = "#EndDate", .OleDbType = OleDbType.Date, .Value = endDate})
' now execute the query...
Related
I have an access database that stores data in a table (called DataCollection) that is logged by a Visual Studio program. I have been struggling to find a solution to how to count the number records that contain specific values in specific columns.
For example, in my database, there are two columns. One column is titled "M/Y OF LOG" and it returns dates formatted like this "1/1/2021". The other column is titled "MISSED PART", and it can return only two values, "Missed Part" or "NEATOL". Ideally, I would like to count, using Visual Studio, the number of times "Missed Part" occurs in a certain month.
Does anyone have any ideas on how the code for this may look, or if counting like this is even possible?
My connection string:
connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb"
Preview of my Access database formatting:
You will see there are many more columns than mentioned. Please ignore any columns other than "M/Y of Log" and "Missed Part"
I have these variables in my code. They will be the variables that hole the return values from the database, used as y values in graphs to display the data:
Private Function CountMissedParts() Handles MyBase.Load
Dim sql = $"SELECT COUNT(*)
FROM DataCollection
WHERE [MISSED PART] = 'Missed Part'
AND [M/Y OF LOG] = #MY_OF_LOG;"
Dim JANmyOfLog = #1/1/2021#
Dim FEBmyOfLog = #2/1/2021#
Dim MARmyOfLog = #3/1/2021#
Dim APRmyOfLog = #4/1/2021#
Dim MAYmyOfLog = #5/1/2021#
Dim JUNmyOfLog = #6/1/2021#
Dim JULmyOfLog = #7/1/2021#
Dim AUGmyOfLog = #8/1/2021#
Dim SEPmyOfLog = #9/1/2021#
Dim OCTmyOfLog = #10/1/2021#
Dim NOVmyOfLog = #11/1/2021#
Dim DECmyOfLog = #12/1/2021#
Dim count As Integer
Dim JanuaryMP As Double
Dim FebruaryMP As Double
Dim MarchMP As Double
Dim AprilMP As Double
Dim MayMP As Double
Dim JuneMP As Double
Dim JulyMP As Double
Dim AugustMP As Double
Dim SeptemberMP As Double
Dim OctoberMP As Double
Dim NovemberMP As Double
Dim DecemberMP As Double
Using connection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb"),
command As New OleDbCommand(sql, connection)
JanuaryMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = JANmyOfLog
FebruaryMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = FEBmyOfLog
MarchMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = MARmyOfLog
AprilMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = APRmyOfLog
MayMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = MAYmyOfLog
JuneMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = JUNmyOfLog
JulyMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = JULmyOfLog
AugustMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = AUGmyOfLog
SeptemberMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = SEPmyOfLog
OctoberMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = OCTmyOfLog
NovemberMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = NOVmyOfLog
DecemberMP = command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = DECmyOfLog
connection.Open()
count = command.ExecuteScalar()
' set 0,0
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(0, 0)
' other points
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(1, JanuaryMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(2, FebruaryMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(3, MarchMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(4, AprilMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(5, MayMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(6, JuneMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(7, JulyMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(8, AugustMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(9, SeptemberMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(10, OctoberMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(11, NovemberMP)
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(12, DecemberMP)
End Using
NotInEpicorCHRT.ChartAreas(0).AxisX.Minimum = 0.0
NotInEpicorCHRT.ChartAreas(0).AxisX.Maximum = 12
NotInEpicorCHRT.ChartAreas(0).AxisX.Interval = 1
NotInEpicorCHRT.ChartAreas(0).AxisY.Minimum = 0.0
NotInEpicorCHRT.ChartAreas(0).AxisY.Maximum = 45
NotInEpicorCHRT.ChartAreas(0).AxisY.Interval = 5
End Function
Dim sql = $"SELECT COUNT(*)
FROM DataCollection
WHERE [MISSED PART] = 'Missed Part'
AND [M/Y OF LOG] = #MY_OF_LOG"
Dim myOfLog = #1/01/2021#
Dim count As Integer
Using connection As New OleDbConnection("connection string here"),
command As New OleDbCommand(sql, connection)
command.Parameters.Add("#MY_OF_LOG", OleDbType.Date).Value = myOfLog
connection.Open()
count = CInt(command.ExecuteScalar())
End Using
That example uses a hard-coded date but you can get the date value from anywhere you like. A Date is a Date.
There is no need to define variable for each month, you can use loop instead.
Check the following code:
Dim count As Integer
Dim lst As List(Of Double) = New List(Of Double)
Dim sql = $"SELECT COUNT(*) FROM DataCollection WHERE [MISSED PART] = 'Missed Part' AND [M/Y OF LOG] = #MY_OF_LOG;"
Using connection As New OleDbConnection("your connection String"),
command As New OleDbCommand(sql, connection)
connection.Open()
For i As Integer = 1 To 12
command.Parameters.Clear()
Dim dtime = New DateTime(2021, i, 1).ToString("MM/dd/yyyy")
command.Parameters.AddWithValue("#MY_OF_LOG", dtime)
count = command.ExecuteScalar()
lst.Add(count)
Next
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(0, 0)
For j As Integer = 1 To lst.Count
NotInEpicorCHRT.Series("Missed Part").Points.AddXY(j, lst(j - 1))
Next
End Using
NotInEpicorCHRT.ChartAreas(0).AxisX.Minimum = 0.0
NotInEpicorCHRT.ChartAreas(0).AxisX.Maximum = 12
NotInEpicorCHRT.ChartAreas(0).AxisX.Interval = 1
NotInEpicorCHRT.ChartAreas(0).AxisY.Minimum = 0.0
NotInEpicorCHRT.ChartAreas(0).AxisY.Maximum = 45
NotInEpicorCHRT.ChartAreas(0).AxisY.Interval = 5
Well, I assume that the date column is a in fact a actual date column. That way, your display of the date does NOT matter. As a general rule, all dates are stored in a internal format - you don't care about the external.
So, all we REALLY need is the month, and year you want.
So, build a form with two text boxes. One text box has year, the other the month.
Say like this:
So, this code would prompt you for the year, then the month, and then spit out the results.
the button code can be this, and it will give a total for both Missed and NeatOL
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strSQL As String
strSQL = "SELECT abs(SUM([Missed Part] = 'Missed Part')) As MissPCount " &
"abs(SUM([Missed Part] = 'NEATOL')) As MissNCount " &
"FROM DataCollection WHERE Month([M/Y OF LOG]) = #Month " &
"AND Year([M/Y OF LOG]) = #Year"
Using cmdSQL As New OleDbCommand(strSQL,
New OleDbConnection(My.Settings.TestDB))
cmdSQL.Parameters.Add("#Month", OleDbType.Integer).Value = txtMonth.Text
cmdSQL.Parameters.Add("#Year", OleDbType.Integer).Value = txtYear.Text
cmdSQL.Connection.Open()
Dim rstTable As New DataTable
rstTable.Load(cmdSQL.ExecuteReader)
' display the reuslts in the two text boxes.
With rstTable.Rows(0)
txtNeatCount.Text = .Item("MissNCount")
txtPartCount.Text = .Item("MissPCount")
End With
End Using
End Sub
Edit:
As a follow up? It looks like you have a single column that is ALWAYS set to the 1st of the month. Give this, and that I used month() and year() functions? Well, using month() and year() is great for things like say who has a birthday this month, ( we can use month() and day() to extract the month, day and ignore the year.
HOWEVER, we should STILL include a valid date range. The reason is of course "indexing" or the so called term "sargable". The above query as written can't use indexing for the results. Thus for a large table, the posted query will run quite slow.
A better (and much faster) performing SQL query would be this, assuming there is a index on the MY/Y column. Thus, I suggest this solution:
strSQL = "SELECT abs(SUM([Missed Part] = 'Missed Part')) As MissPCount " &
"abs(SUM([Missed Part] = 'NEATOL' As MissNCount " &
"FROM DataCollection WHERE [M/Y OF LOG] = #MyDate "
Dim dtMyDate As Date = DateSerial(txtYear.Text, txtMonth.Text, 1)
Using cmdSQL As New OleDbCommand(strSQL,
New OleDbConnection(My.Settings.TestDB))
cmdSQL.Parameters.Add("#MyDate", OleDbType.DBDate).Value = dtMyDate
cmdSQL.Connection.Open()
etc. etc. etc. etc.
I think the following code will get you the data you need. Ask another question if you need the data table columns translated to the chart.
Private Sub OPCode()
Dim sql = $"SELECT [M/Y OF LOG], COUNT([Missed Part]) As Total
FROM [Data Collection]
WHERE [MISSED PART] = 'MISSED PART'
GROUP BY [M/Y OF LOG]
ORDER BY [M/Y OF LOG];"
Dim dt As New DataTable
Using cn As New OleDbConnection(My.Settings.DataCollection),
cmd As New OleDbCommand(sql, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
DataGridView1.DataSource = dt
End Sub
Dim query As String = "select * from mytable where strftime('%Y-%m-%d',tarih) between 'TextBox4.text' and 'TextBox5.text' "
Can not assign query variable ?
Datagridview result = empty
info :Datagridview date format = 2018-01-01 17:42:24
Dim btarihyil As String
btarihyil = DateTimePicker2.Value.ToString.Substring(6, 4)
Dim btarihay As String
btarihay = DateTimePicker2.Value.ToString.Substring(3, 2)
Dim btarihgun As String
btarihgun = DateTimePicker2.Value.ToString.Substring(0, 2)
TextBox4.Text = btarihyil & "-" & btarihay & "-" & btarihgun
Dim bttarihyil As String
bttarihyil = DateTimePicker3.Value.ToString.Substring(6, 4)
Dim bttarihay As String
bttarihay = DateTimePicker3.Value.ToString.Substring(3, 2)
Dim bttarihgun As String
bttarihgun = DateTimePicker3.Value.ToString.Substring(0, 2)
TextBox4.Text = btarihyil & "-" & btarihay & "-" & btarihgun
TextBox5.Text = bttarihyil & "-" & bttarihay & "-" & bttarihgun
Dim Yol As String = "Data Source=database1.s3db;version=3;new=False"
Using MyConn As New SQLiteConnection(Yol)
If (MyConn.State = ConnectionState.Closed) Then
MyConn.Open()
End If
Dim Sorgu As String = "select * from mytable where strftime('%Y-%m-%d',tarih) between 'TextBox4.text' and 'TextBox5.text' "
Using MyCmd As New SQLiteCommand(Sorgu, MyConn)
Dim Da As New SQLiteDataAdapter(MyCmd)
Dim Ds As New DataSet
Dim Dt As New DataTable
Ds.Reset()
Da.Fill(Ds)
Dt = Ds.Tables(0)
Dim Bs As New BindingSource With {.DataSource = Dt}
DataGridView1.DataSource = Bs
Bs.MoveLast()
MyConn.Close()
MyCmd.Dispose()
MyConn.Dispose()
End Using
End Using
End Sub
You are using "TextBox4.Text" and "TextBox5.Text" literally in the query. That will not pass the values of textboxes to the query. So it will result in error.
Also you need to use parameterized query to avoid syntax errors.
Also I am not sure why you are using strftime function. That function is used just for formatting.
Following the code I re-written using parameterzied query approach.
Dim Yol As String = "Data Source=database1.s3db;version=3;new=False"
Using MyConn As New SQLiteConnection(Yol)
If (MyConn.State = ConnectionState.Closed) Then
MyConn.Open()
End If
Dim Sorgu As String = "select * from mytable where tarih between #startDate and #endDate "
Using MyCmd As New SQLiteCommand(Sorgu, MyConn)
Dim startDate as new SQLiteParameter("#startDate")
startDate.Value = DateTimePicker2.Value
Dim endDate as new SQLiteParameter("#endDate")
endDate.Value = DateTimePicker3.Value
MyCmd.Parameters.Add(startDate)
MyCmd.Parameters.Add(endDate)
Dim Da As New SQLiteDataAdapter(MyCmd)
Dim Ds As New DataSet
Dim Dt As New DataTable
Ds.Reset()
Da.Fill(Ds)
Dt = Ds.Tables(0)
Dim Bs As New BindingSource With {.DataSource = Dt}
DataGridView1.DataSource = Bs
Bs.MoveLast()
MyConn.Close()
MyCmd.Dispose()
MyConn.Dispose()
End Using
End Using
This should help you resolve your issue.
Private Sub recruit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles recruit.Click
Dim query3 As String
Dim n As Integer
Dim query2 As String = "select max(stag) from agent"
con.ConnectionString = ("Data Source=DESKTOP-CTN5IJ3\SQLEXPRESS;Integrated Security=True")
Dim autono As New SqlCommand(query2, con)
con.Open()
If IsDBNull(autono.ExecuteScalar) Then
n = 7
Else
n = autono.ExecuteScalar + 5
End If
con.Close()
query3 = "insert into agent values(" + n + ",'" + ncrypt(txtssn.Text) + "','" + ncrypt(txtname.Text) + "','" + ncrypt(txtadd.Text) + "',0,0,'newbpwd')"
Dim save As New SqlCommand(query3, con)
con.Open()
save.ExecuteNonQuery()
con.Close()
End Sub
//query3 = "insert into agent values(" + n + ",'" + ncrypt(txtssn.Text) + "','" + ncrypt(txtname.Text) + "','" + ncrypt(txtadd.Text) + "',0,0,'newbpwd')" this is wher the problem is said to be
Your main problem is you are using wrong string concatenation operator. Use & instead of +.
Another approach is using string interpolation
Dim n As Integer = 101
Dim query = $"INSERT INTO table VALUES ({n})"
But if you from beginning have correctly using SqlParameters for passing values to the sql query - you will not need to concatenate strings at all.
By using SqlParameter you will keep your safe from possible Sql Injection with your current code.
Private Sub recruit_Click(sender As Object, e As EventArgs) Handles recruit.Click
Dim connectionString = _
"Data Source=DESKTOP-CTN5IJ3\SQLEXPRESS;Integrated Security=True"
Dim newId As Integer = 7
Using connection As New SqlConnection(connectionString)
Dim query As String = "select max(stag) from agent"
Using command As New SqlCommand(query, connection)
connection.Open()
Dim result = command.ExecuteScalar()
If result IsNot DbNull.Value Then
newId = DirectCast(result, Integer) + 5
End If
End Using
End Using
Using connection As New SqlConnection(connectionString)
Dim query As String = _
"insert into agent values (#Id, #SSN, #Name, #Add, 0, 0, 'newbpwd')"
Using command As New SqlCommand(query, connection)
Dim parameters As New List(Of SqlParameter) From
{
New SqlParameter With { .ParameterName = "#Id", .SqlDbType = SqlDbType.Int, .Value = newId },
New SqlParameter With { .ParameterName = "#SSN", .SqlDbType = SqlDbType.VarChar, .Value = ncrypt(txtssn.Text)},
New SqlParameter With { .ParameterName = "#Name", .SqlDbType = SqlDbType.VarChar, .Value = ncrypt(txtname.Text)},
New SqlParameter With { .ParameterName = "#Add", .SqlDbType = SqlDbType.VarChar, .Value = ncrypt(txtadd.Text)},
}
command.Parameters.AddRange(parameters)
connection.Open()
command.ExecuteNonQuery()
End Using
End Using
End Sub
In vb, you use '&' symbol rather than '+' to concatenate Strings
My way is to convert the integer to string before you insert it into a table, it works for me. e.g:
Dim n As Integer = 33
Dim s As String = n.ToString
I keep getting this error
Invalid cast from 'Boolean' to 'DateTime'
when the codes below try to execute.
I am basically trying to update my auction_item table where the "closedate < todayDate" is met.
This is where the error fires [Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)]
con.Open()
CMD = New SqlCommand("SELECT auction_item_close_date FROM auction_items WHERE (auction_item_status_id = 1)", con)
DR = CMD.ExecuteReader()
DR.Read()
Dim closedate As Date
closedate = Convert.ToDateTime(DR(0))
con.Close()
Dim todayDate As Date = DateAndTime.Today
Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)
con.Open()
If closedate < todayDate Then
SQL = "UPDATE auction_items SET auction_item_status_id = 2, auction_item_open_closed = 'closed' WHERE auction_item_close_date = '" & forupdate & "'"
CMD = New SqlCommand(SQL, con)
CMD.ExecuteNonQuery()
con.Close()
End If
The error is on this line:
Dim forupdate As Date = Convert.ToDateTime(closedate < todayDate)
closedate < todayDate returns true or false depending on whether closedate is before todayDate.
That value can not be converted to a DateTime and this is what the exception says. Maybe you need to rethink what the line is supposed to do.
Dim Con As OleDb.OleDbConnection
Dim Sql As String = Nothing
Dim Reader As OleDb.OleDbDataReader
Dim ComboRow As Integer = -1
Dim Columns As Integer = 0
Dim Category As String = Nothing
Dim oDatumMin As Date
Dim column As String
column = Replace(TxtDateMax.Text, "'", "''")
'oDatumMin = Convert.ToDateTime(TxtDateMin.Text)
oDatumMin = DtpMin.Value
Dim oPath As String
oPath = Application.StartupPath
' Select records.
Con = New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & oPath & "\trb.accdb;")
Dim cmd As New OleDb.OleDbCommand
'Dim data_reader As OleDbDataReader = cmd.ExecuteReader()
Sql = ("SELECT * FROM " & cmbvalue & " WHERE Datum>='" & oDatumMin & "'")
cmd = New OleDb.OleDbCommand(Sql, Con)
Con.Open()
Reader = cmd.ExecuteReader()
Do While Reader.Read()
Dim new_item As New ListViewItem(Reader.Item("Datum").ToString)
new_item.SubItems.Add(Reader.Item("Steleks i krpe za cišcenje-toal papir-ubrusi-domestos").ToString)
new_item.SubItems.Add(Reader.Item("TEKUCINA ZA CIŠCENJE PLOCICA").ToString)
new_item.SubItems.Add(Reader.Item("KESE ZA SMECE").ToString)
new_item.SubItems.Add(Reader.Item("OSTALO-džoger-spužva za laminat").ToString)
new_item.SubItems.Add(Reader.Item("PAPIR").ToString)
LvIzvjestaj.Items.Add(new_item)
Loop
' Close the connection.strong text
Con.Close()``
when i select table,(cmbvalue) from combobox
and when i select date from datetime picker (dtp) or in last case from texbox converted to date and time sql looks like this "SELECT * FROM Uprava WHERE Datum>='2.6.2010 10:28:14'"
and all query looks ok but am geting
Data type mismatch in criteria expression. error for date (oDatumMin) when excute
column in access is also set to date
i have no idea what else to try
I suspect this is a localisation issue. Try changing the date format to one which should be universally recognised:
SELECT * FROM Uprava WHERE Datum >='2010/06/02 10:28:14'
[What is your server locale/code page?]
Dim sql As String = "SELECT * FROM MyTable WHERE Datum >= ?"
Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand(sql)
cmd.Parameters.Add(New OleDb.OleDbParameter("#Datum", OleDb.OleDbType.Date))
cmd.Parameters("Datum").Value = oDatumMin
http://msdn.microsoft.com/de-de/library/bbw6zyha.aspx