Is paging in DataGridView possible in VB.NET?
I've successfully connected to a database and is able to import the data into the DataGrid, but the problem is that the table i have is huge with over 10mil rows. So showing in all in one view is either slowing down the loading time, or if i choose to add more columns of data the application will turn out to be an error.
For example, this line would work
cmd.CommandText = "SELECT primaryTitle, startYear, runtimeMinutes, genres, FROM Basics"
but this line would throw me an error called System.OutOfMemoryException
cmd.CommandText = "SELECT primaryTitle, startYear, runtimeMinutes, genres, directors, writers FROM Basics, Crew"
Any help would be appreciated.
This is my current code. The only thing i've done is importing the data into the DataGridView, nothing more since i can't proceed anymore.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As New SqlClient.SqlConnection
con.ConnectionString = "Data Source=DESKTOP-7SOUE1N\SQLEXPRESS;Initial Catalog=IMDb MOVIE DATABASE SYSTEM;Integrated Security=True"
con.Open()
Dim cmd As New SqlClient.SqlCommand
cmd.Connection = con
cmd.CommandText = "SELECT primaryTitle, startYear, runtimeMinutes, genres, directors, writers FROM Basics, Crew"
Dim rdr As SqlClient.SqlDataReader = cmd.ExecuteReader
Dim dt As New DataTable
dt.Load(rdr)
rdr.Close()
DataGridView1.DataSource = dt
con.Close()
End Sub
End Class
Yes, certainly is. This is how I usually do it.
Prerequisities:
DataGridView DataGridView1
ToolStrip ToolStrip1
TextBox PageNo
Label PageCount
Button btnPageBack
Button btnPageNext
Label TotalShown
Label OutOfTotalRecords
(some labels like "Page", " from ", "Total shown ", " out of ", " records")
Dim RowsPerPage as Int16 = 40 ' set
This is how the ToolStrip bellow DataGridView footer looks in designer:
Fetching or updating the list SQL (wrapped in LoadListOfRecords() sub):
"SELECT
...
ORDER BY " & dgwSortCol & " " & dgwSortOrder & " " &
OFFSET " & ((IIf(Me.PageNo.Text = "", 1, CInt(Me.PageNo.Text)) - 1) * RowsPerPage) & "
ROWS FETCH NEXT " & RowsPerPage & " ROWS ONLY; "
You might skip ORDER at first. But notice OFFSET xx ROWS, which tells where in database it should start to read records (by how many records to offset it from beginning) and FETCH NEXT xx ROWS ONLY, which tells how many rows to read and load to a "page". I skipped stuff like creating DataSet, reading DataTable, assigning it to DataGridView's DataSource and such.
Button Back (I won't put Next, it's nearly identical, just changed limiting condition and iteration):
Private Sub btnPageBack_Click(sender As System.Object, e As System.EventArgs) Handles btnPageBack.Click
If CInt(Me.PageNo.Text) > 1 Then
Me.PageNo.Text = CInt(Me.PageNo.Text) - 1
End If
Call LoadListOfRecords()
End Sub
Manual entry of page number (go to particular page), following Enter key stroke:
Private Sub PageNo_KeyDown(sender As System.Object, e As System.Windows.Forms.KeyEventArgs) Handles PageNo.KeyDown
Call LoadListOfRecords()
End Sub
And that's about it. Simple, easy to use by users, works as charm, proven by time. No clutter of 3rd party controls and libraries.
Related
I have a Visual Basic 2010 application that uses a DataGridView to display a list of frequencies from a Microsoft Access 2010 database. The application uses the BindingNavigationPostionItem to allow navigation though the table.
The Move Next and Move Previous buttons move you up and down the list. The cool thing is, as you do this, I have code that sends the Frequency and Mode to my Yeasu radio and the radio then is set to that freq/mode.
This works great but, if I try to filter the DataGridView by the Service field, the ID field becomes blank and navigation does not work.
Here is the code that runs after you select what you want to filter by and you click the filter button:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim cmbox1 As String
cmbox1 = ComboBox1.Text
MyConn = New OleDbConnection
MyConn.ConnectionString = connString
ds = New DataSet
tables = ds.Tables
da = New OleDbDataAdapter("Select * from HFUtil where service = '" & cmbox1 & "'", MyConn) '
da.Fill(ds, "HFUtil")
Dim view As New DataView(tables(0))
source1.DataSource = view
DataGridView1.DataSource = view
BindingNavigator1.BindingSource = source1
DataGridView1.Refresh()
BindingNavigator1.Refresh()
'=========================================================
ListBox1.Items.Clear()
ListBox1.Text = ""
For Each dr As DataRow In ds.Tables(0).Rows
Dim sItemTemp As String
sItemTemp = String.Format("{0} {1} {2}", dr("freq"), dr("mode"), dr("desc"))
ListBox1.Items.Add(sItemTemp)
Next
ComboBox2.Items.Clear()
ComboBox2.Text = ""
For Each dr As DataRow In ds.Tables(0).Rows
Dim sItemTemp As String
sItemTemp = String.Format("{0} {1} {2}", dr("freq"), dr("mode"), dr("desc"))
ComboBox2.Items.Add(sItemTemp)
Next
End Sub
The only difference between this code and the code that runs on form load is - where clause in the data adapter.
What am I doing wrong?
I don't see in your code where you apply your filter. So, lets pretend for a second that you load your whole table into DataSet. Then next thing, you either use DataSet.DefaultView or create your custom DataView and assign this to DataSource property - you did this.
Now, all you have to do is apply row filter to the data view you use
view.RowFilter = "service = '" & cmbox1 & "'"
At this point you should only see subset of records and nothing should happen to your Id field. Because your data doesn't change.
I have suspicion, you changing your view somewhere and this is why you have problems.
I am using a while loop to populate a second combo based on the value of the first combobox selection. What is happening however, is that the loop is only displaying 1 item in the second combobox instead of about 20. If I set breakpoint on the while loop I can see that all items are being calculated but just not appearing in the combobox.
I would be grateful if someone could point my basic newbie error. Many thanks
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
While dr.Read()
If (dr.HasRows) Then
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End If
End While
cmd.Dispose()
dr.Close()
End Sub
The Text property of the combo box contains only what is displayed for the selected item. You need to add the items to the Items collection:
cmbDept.Items.Add(CStr(dr("Name")))
The combo boxes, list boxes etc. display items by calling their ToString() method. Therefore calling CStr should not even be necessary:
cmbDept.Items.Add(dr("Name"))
You are inserting a value in the SQL statement by concatenating strings. If you are just using your program for yourself, this is okay; however, on productive environments this is dangerous. Someone could enter a value that terminates the SELECT statement and introduces another malicious statement. E.g. a DELETE statement that deletes a whole table. This is called a SQL injection attack.
There are two ways to deal with this:
1) Escape the string:
sql = "SELECT * FROM Dep WHERE Cust = '" & s.Replace("'", "''") & "'"
2) Use command parameters:
sql = "SELECT * from Departments WHERE Customer = ?"
Dim cmd As New OleDbCommand(sql, oledbCnn)
cmd.Parameters.AddWithValue("#p1", cmbCustomer.Text)
If you are inserting dates this also has the advantage that you don't need to bother about date formats.
You can simplify your loop to:
While dr.Read()
cmbDept.Text = CStr(dr("Name"))
End While
There is no need to test for HasRows since dr.Read() would return False anyway if no rows were available.
You can have Dispose called automatically by VB with the Using statement:
Using cmd As New OleDbCommand(sql, oledbCnn)
'TODO: Work with cmd here.
End Using
Dispose will be called at the end of the Using block, even if an error occurs within the Using block or the Using block is left by Return or another statement.
You do not need to check if the data reader has rows every iteration, just check it before you loop.
You are not adding the items to the list, but rather setting the Text property of cmbDept, instead do this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub
Also, it is highly recommended that you use a parameterized query as to avoid a visit from Little Bobby Tables, like this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = #Customer"
Dim cmd As New OleDb.OleDbCommand
cmd.Parameters.AddWithValue("#Customer", cmbCustomer.Text)
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub
I have a created a database containing historical stock prices. On my form I have two comboboxes, ComboBox_Ticker and ComboBox_Date. When these comboboxes are filled I want to check the database and see if the respective data exists in the database. If it does I want to change the text of a label called Label_If_Present to "In Database".
My problem occurs with the change event. I want all of this to happen once I change the data in the textboxes. I have tried both the .TextChanged and .LostFocus events. The '.TextChanged' triggers the code to early and throws and error in my SQL command statement. The `.LostFocus' event doesn't do trigger my code at all.
Here is my current code:
Public databaseName As String = "G:\Programming\Nordeen Investing 3\NI3 Database.mdb"
Public con As New OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source =" & databaseName)
Public tblName As String = "Historical_Stock_Prices"
Private Sub Change_Labels(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBox_Ticker.TextChanged, ComboBox_Date.TextChanged
con.Close()
Dim dr As OleDbDataReader
con.Open()
If (File.Exists(databaseName)) Then
Dim restrictions(3) As String
restrictions(2) = tblName
Dim dbTbl As DataTable = con.GetSchema("Tables", restrictions)
If dbTbl.Rows.Count = 0 Then
Else
Dim cmd2 As New OleDb.OleDbCommand("SELECT * FROM " & tblName & " WHERE Ticker = '" & ComboBox_Ticker.Text & "' " & " AND Date1 = '" & ComboBox_Date.Text & "'", con)
dr = cmd2.ExecuteReader
If dr.Read() = 0 Then
'If record does not exist
Label_If_Present.Text = ""
Else
Label_If_Present.Text = "In Database"
End If
con.Close()
End If
Else
End If
End Sub
I have successfully implemented this concept on other forms within my project. This one is slightly different and I can't figure out why I can't get this one to work.
Handling the TextChanged event should work, however you need to set the DropDownStyle to DropDownList so that the Text property can only be a given value.
Then check to see that both comboboxes have values selected. Something like this should work:
If ComboBox_Ticker.Text <> "" AndAlso DateTime.TryParse(ComboBox_Date.Text, Nothing) Then
I am designing a windows form in vb.net 2010. It's a simple one with two controls. One is datagridview to display data in tabular form and another is a chart control which fetches data from the gridview to draw charts. I also have a combobox which helps to select the variable for which I would like to have the table or charts. In addition, there are two buttons, one labeled 'table' clicking on which populates the gridview with data from an external excel file. Another button labeled 'plot' plots the data that was imported into gridview.
Suppose I have three variables in the comboBox, 'Real GDP', consumption, investment. During the run-time, the first time I select any variable, it works fine.But during the same run, if I select another variable, then gridview can import the variable but plot fails to draw the chart. Plot can not find the variable because it is still looking for the first variable while in gridview I have the table for the second variable. It seems there is a disconnect between the gridview and plot if we select another variable after the first one is displayed.
If I close the run and rebuild and select another variable it works fine. But again during that run if I select another variable, it fails. Here is my code:
Public Class Form1
Dim MyConnection As System.Data.OleDb.OleDbConnection
Dim DtSet As System.Data.DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
Dim myStr1, myStr2, myStr3 As String
Dim msgStr, msgEnd, defValStr, defValEnd, _
title, myValStr, myValEnd As String
Public Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
myStr1 = selectVariable.SelectedItem
MsgBox("You have chosen " & myStr1)
' Defining a InputBox to enter Sample Period
' Start Period
msgStr = "Enter your Starting time period: Between 1980 and 2012"
defValStr = "1982"
title = "Define Sample Time Period"
myValStr = InputBox(msgStr, title, defValStr)
' End Period
msgEnd = "Enter your Ending time period: Between 1980 and 2012"
defValEnd = "2012"
title = "Define Sample Time Period"
myValEnd = InputBox(msgEnd, title, defValEnd)
Select Case myStr1
Case "Real GDP"
myStr2 = "xgdp"
Case "Consumption"
myStr2 = "CP"
Case "Investment"
myStr2 = "IP"
End Select
myStr3 = String.Concat("select", " ", "FY", ",", myStr2, " ", "from", " ", "[Dataset$]", " ", "where", " ", "FY>=", myValStr, " ", "and", " ", "FY<=", myValEnd)
MyConnection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='J:\Rushad\MOF\EViews Stuff\Data_Macro_Model.xls';Extended Properties=Excel 8.0;")
MyCommand = New System.Data.OleDb.OleDbDataAdapter(myStr3, MyConnection)
MyCommand.TableMappings.Add("Table", "Net-informations.com")
DtSet = New System.Data.DataSet
MyCommand.Fill(DtSet)
DataGridView1.DataSource = DtSet.Tables(0)
MyConnection.Close()
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Chart1.DataSource = DtSet
Chart1.Series.Add(myStr2)
Chart1.Series(myStr2).XValueMember = "FY"
Chart1.Series(myStr2).YValueMembers = myStr2
End Sub
End Class
You should try binding your data source to a BindingSource and binding the Binding source to your datagrid
BindingSourceExample.DataSource = DataToBind
DataGridView.DataSource = BindingSourceExample
at least this is how I would do it !
I have a datagridview with checkboxes in the first column and I want to do a loop on saving the serialnumber(s) when the users decides to check a number of checkboxes ...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim serialnumber As String = DataGridView1.CurrentRow.Cells("SerialNumber").Value
Dim siteid As String = Main.StatusBar1.Panels(2).Text
Dim connection As New SqlConnection
Dim cmd As New SqlCommand
connection.ConnectionString = "Data Source =TOBZ-PC; Initial Catalog =Glowb; Integrated Security =SSPI;"
For Each row As DataGridViewRow In DataGridView1.Rows
If row.Cells(Column1.Name).Value = True Then
connection.Open()
cmd.Connection = connection
cmd.CommandText = " insert into [equipment request](serialnumber, siteid) values('" & serialnumber & "', '" & siteid & "') "
cmd.ExecuteNonQuery()
connection.Close()
End If
Next
End Sub
the problem with this code is that it only inserts the serial number of the LAST checked checkbox and the number of entries of it depends on the number of checked checkbox ...
for example ... if I checked the rows with the serialnumber 123 and 55652341, first the row with the serial number 123 then second 55652341, only 55652341 appears in the database and it is entered twice(twice because two checkboxes are checked) ...
hope I made it clear and someone could help me ...
You need to update the SerialNumber variable inside the loop where you iterate through the rows.
serialnumber = row.Cells("SerialNumber").Value
As a side note, your loop could be more efficient if you open the connection before the loop, and close it afterwards. Opening and closing it for every iteration is going to slow things down.