Populating Combo-box2 from value selected in combo-box1 - sql

First Combo-box has student admin numbers. When a number is selected the next combo-box should reveal the list of classes for that student. However when a value is selected the second combo-box doesn't show anything.
AdminNo is stored in both Student and ClassEnrollment tables in the database.
Imports System.Data.OleDb
Public Class AddReport
Dim cn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=C:\ProjectDatabase.mdb")
Dim daa As New OleDbDataAdapter()
Dim dt As New DataTable()
Private Sub btnReturn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnReturn.Click
Me.Close()
Startup.Show()
End Sub
Private Sub AddReport_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
StudentNameAdd()
End Sub
Sub StudentNameAdd()
cn.Open()
daa.SelectCommand = New OleDbCommand("Select AdminNo from Student", cn)
daa.Fill(dt)
CBStudent.Items.Clear()
Dim r As DataRow
For Each r In dt.Rows
CBStudent.Items.Add(r(0).ToString)
Next
cn.Close()
End Sub
Private Sub CBStudent_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CBStudent.SelectedIndexChanged
dt.Reset()
Dim StudentAdminNo As Integer = CBStudent.SelectedValue
cn.Open()
daa.SelectCommand = New OleDbCommand("Select ClassCode from ClassEnrollment Where AdminNo=" & StudentAdminNo, cn)
daa.Fill(dt)
CBClass.Items.Clear()
Dim r As DataRow
For Each r In dt.Rows
CBClass.Items.Add(r(0).ToString)
Next
cn.Close()
End Sub
Any help pushing me in the right direction will be greatly appreciated.

What about binding the DataTable to the ComboBox by setting the Combobox's DataSource property to the DataTable?
EDIT: i've tested your code and it works fine if you change
Dim StudentAdminNo As Integer = CBStudent.SelectedValue
to
Dim StudentAdminNo As Integer = CBStudent.SelectedItem

Related

Visual Basic Add Row Function Not Working After Reset Function

I will clarify my question. Here is background:
Creating a Database in Visual Studio 2019 using Visual Basic
Database consists of a list of Devices and Serial Numbers etc. that I must have account of
I have search functions, filtering functions, and a few editing functions
The problem I am encountering is that once I click the reset button (supposed to reset the dataviewgrid unsaved changes back to last saved changes) the add row function no longer works. The code throws no error but simply refuses to add a new row when clicking the button (Before hitting the reset button the add row button works fine)
Here is how I populate my database using sql:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim connection As New SqlConnection("Connection String Placeholder")
Dim Table As New DataTable()
Dim Adapter As New SqlDataAdapter("SELECT * FROM TrackMain$", connection)
Adapter.Fill(Table)
DataGridView1.DataSource = Table
bind_data()
nextId = Convert.ToInt32(dt.Rows(dt.Rows.Count - 1)(0)) + 1
End Sub
I am also attempting to order my first column numerically and therefore I have the NextID value there as well and in my add row function (which may be the culprit)
Here is the add row and then reset function:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dr As DataRow = dt.NewRow()
dr(0) = nextId
dt.Rows.Add(dr)
nextId += 1
End Sub
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim connection As New SqlConnection("Connection String Placeholder")
Dim Table As New DataTable()
Dim Adapter As New SqlDataAdapter("SELECT * FROM TrackMain$", connection)
Adapter.Fill(Table)
DataGridView1.DataSource = Table
nextId = Convert.ToInt32(dt.Rows(dt.Rows.Count - 1)(0)) + 1
End Sub
If any further questions please let me know, and thank you
Edit: Here is my bind_data() Sub
Private Sub bind_data()
connection.Open()
Dim cmdTxt As String = "SELECT * FROM TrackMain$"
da = New SqlDataAdapter(New SqlCommand(cmdTxt, connection))
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(da)
da.Fill(dt)
Dim source As BindingSource = New BindingSource With {
.DataSource = dt
}
DataGridView1.DataSource = source
End Sub
Here's the whole code of my test, and the code works for me.
Private dt As DataTable = New DataTable
Private da As SqlDataAdapter
Private connection As SqlConnection = New SqlConnection("connection string")
Dim nextId As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bind_data()
nextId = Convert.ToInt32(dt.Rows(dt.Rows.Count - 1)(0)) + 1
End Sub
' Update database by DataGridView.'
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i As Integer = DataGridView1.Rows.Count - 1 To 0
Dim row As DataGridViewRow = DataGridView1.Rows(i)
If Not row.IsNewRow AndAlso row.Cells(0).Value Is Nothing Then
DataGridView1.Rows.RemoveAt(i)
End If
Next
DataGridView1.EndEdit()
da.Update(dt)
End Sub
' Add new Row.'
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim dr As DataRow = dt.NewRow()
dr(0) = nextId
dt.Rows.Add(nextId)
nextId += 1
End Sub
' Reset the dt and DataGridView.'
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim Table As New DataTable()
dt.Clear()
Dim Adapter As New SqlDataAdapter("SELECT * FROM TrueTrack", connection)
Adapter.Fill(dt)
DataGridView1.DataSource = dt
nextId = Convert.ToInt32(dt.Rows(dt.Rows.Count - 1)(0)) + 1
End Sub
Private Sub bind_data()
connection.Open()
Dim cmdTxt As String = "SELECT * FROM TrueTrack"
da = New SqlDataAdapter(New SqlCommand(cmdTxt, connection))
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(da)
da.Fill(dt)
Dim source As BindingSource = New BindingSource With {
.DataSource = dt
}
DataGridView1.DataSource = source
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
connection.Close()
End Sub
Edit:
DataBase design(cancel auto-Increment of 'Id' ):
You can refer to the following code to sort the DataGridView by 'Id'.
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Me.DataGridView1.Sort(Me.DataGridView1.Columns("Id"), ListSortDirection.Ascending)
End Sub
Then change the code to remove the DataGridView row.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If DataGridView1.Rows.Count > DataGridView1.CurrentCell.RowIndex + 1 Then
DataGridView1.Rows.RemoveAt(DataGridView1.CurrentCell.RowIndex)
End If
nextId = Convert.ToInt32(DataGridView1.Rows(DataGridView1.CurrentCell.RowIndex).Cells(0).Value) + 1
End Sub

SQL Column to TextBox (from ComboBox)

I have managed to add data into a ComboBox from a column out of my SQL table, but I need the rows from across to display in the rest of the textboxes. (I hope I have worded this correctly).
Here is my code currently:
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As New SqlConnection("Data Source=xxxx;Initial Catalog=ltLeavers;Integrated Security=True")
Dim da As New SqlDataAdapter("SELECT * FROM dbo.mytable", con)
Dim dt As New DataTable
da.Fill(dt)
ComboBox1.DisplayMember = "DISPLAY_NAME"
ComboBox1.DataSource = dt
End Sub
The above works with no issues, all of the items add into the ComboBox but I need the corresponding rows from the other two columns which are EMAIL_ADDRESS and DEPARTMENT to add into TextBoxes from what is selected in the ComboBox.
Under the SelectedIndex_Changed event of the ComboBox; Enter the following code.
Dim dt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As New SqlConnection("Data Source=xxxx;Initial Catalog=ltLeavers;Integrated Security=True")
Dim da As New SqlDataAdapter("SELECT * FROM dbo.mytable", con)
da.Fill(dt)
ComboBox1.DisplayMember = "DISPLAY_NAME"
ComboBox1.DataSource = dt
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Textbox1.Text = CStr(dt.Rows(ComboBox1.SelectedIndex)("EMAIL_ADDRESS"))
Textbox2.Text = CStr(dt.Rows(ComboBox1.SelectedIndex)("DEPARTMENT"))
End Sub
You Will need to declare the data table dt outside your form's load event so it can be visible to the SelectedIndex_Changed event of the combo box.
I suggest you to use BindingSource to get it done.
Try this:
1- Declare your variable type of BindingSource with events. Also, declare your dataset will be used for data.
Dim WithEvents BS As New BindingSource
Dim ds As New DataSet
2- In your Form Load Event, query your data and bind it with both Binding Source and your ComboBox control.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As New SqlConnection("Data Source=xxxx;Initial Catalog=ltLeavers;Integrated Security=True")
Dim da As New SqlDataAdapter("SELECT * FROM dbo.mytable", con)
da.Fill(ds, "myPopulatedTable")
ComboBox1.DisplayMember = "id"
ComboBox1.DataSource = ds.Tables("myPopulatedTable")
'Here the new code'
BS.DataSource = ds
BS.DataMember = "myPopulatedTable"
End Sub
3- Add a Sub Procedure to display your data into other text boxes controls.
Private Sub DISPLAYRECORD(Optional ByVal table As String = "myPopulatedTable")
TextBox1.Text = ds.Tables(table).Rows(Me.BS.Position)("column1").ToString
TextBox2.Text = ds.Tables(table).Rows(Me.BS.Position)("column2").ToString()
TextBox2.Text = ds.Tables(table).Rows(Me.BS.Position)("column3").ToString()
End Sub
4- In the PositionChanged event of your Binding Source, call that sub procedure (above)
Private Sub BS_PositionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles BS.PositionChanged
DISPLAYRECORD()
End Sub
5- Finally, to sync your data with ComboBox selection, you need to change the position of that Binding Source according to the ComboBox index selection
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
BS.Position = ComboBox1.SelectedIndex
End Sub

Datagridview and access database only updates after clicking a different row

I am reading an access database and populating the info in datagridview. My form has a DGV, and 3 buttons.
Button one copies the selected row to a datetimepicker control.
Button two copied the updated datetimepicker value back to the DVG
Button three does an update (writes the info back to the database).
My issue is that the info only gets updated in the database if I select a different row before hitting button three. I am not getting any error message in either case.
Below is my code. The database only has 2 columns (name and DOB - which is date/time).
Public Class Form1
Dim dbConn As New OleDb.OleDbConnection
Dim sDataset As New DataSet
Dim sDataAdapter As OleDb.OleDbDataAdapter
Dim sql As String
Dim iTotalRows As Integer
Dim sShipTypeFilter As String
Dim sBuildingFilter As String
Dim sCustSuppFilter As String
Dim sStatusFilter As String
Dim sDayFilter As String
Dim dv As New DataView
Sub myDBConn()
dbConn.ConnectionString = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\terry\Documents\Database1.accdb"
Debug.Print("Start:" & DateAndTime.Now.ToString)
dbConn.Open()
sql = "select * from TableX"
sDataAdapter = New OleDb.OleDbDataAdapter(Sql, dbConn)
sDataAdapter.Fill(sDataset, "MyTable")
dbConn.Close()
iTotalRows = sDataset.Tables("MyTable").Rows.Count
Debug.Print("Rows from Access:" & iTotalRows)
Debug.Print("End:" & DateAndTime.Now.ToString)
End Sub
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Call myDBConn()
Debug.Print("DVG1 row count before binding:" & DataGridView1.Rows.Count)
'dv = New DataView(sDataset.Tables(0), "Shipment = 'Regular' and Building = 'CSE'", "Company DESC", DataViewRowState.CurrentRows)
dv = sDataset.Tables(0).DefaultView
Debug.Print("DataView count:" & dv.Count)
DataGridView1.DataSource = dv
Debug.Print("DVG1 Rows:" & DataGridView1.Rows.Count)
DataGridView1.Columns("DOB").DefaultCellStyle.Format = "hh:mm tt"
DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
dtp1.Value = DataGridView1.SelectedRows(0).Cells("DOB").Value
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
DataGridView1.SelectedRows(0).Cells("DOB").Value = dtp1.Value
End Sub
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
Debug.Print("switched row")
Me.Visible = False
Dim sqlcb As New OleDb.OleDbCommandBuilder(sDataAdapter)
sDataAdapter.Update(sDataset.Tables("MyTable"))
Me.Close()
End Sub
End Class
Before updating you need to Endedit. This means you need to add Endedit for the datagridview.
So this will be your code:
Debug.Print("switched row")
Me.Visible = False
Dim sqlcb As New OleDb.OleDbCommandBuilder(sDataAdapter)
Datagridview1.EndEdit()
sDataAdapter.Update(sDataset.Tables("MyTable"))
Me.Close()
EDIT1:
Dim dt As New DataTable
dbConn.Open()
sDataset.Tables.Add(dt)
sDataAdapter = New OleDbDataAdapter("Select * from TableX", dbConn)
sDataAdapter.Update(dt)
dbConn.Close()
I figured it out - thanks Stef for putting me on the right track.
My DGV is only updated programmatically (not by user edits) so I updated the code for button 2 to set the editmode, begin editing, update the selected DVG row and end editing:
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
DataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically
DataGridView1.BeginEdit(True)
DataGridView1.SelectedRows(0).Cells("DOB").Value = dtp1.Value
DataGridView1.EndEdit()
End Sub
After doing this modification - my datadapter.update command works!!

Accessing data from ms access and displaying in grid view

I am not able to display any data in grid view,Its a blank datagrid
The connection is open and everything is fine but data is not getting displayed!! I am a newbie
Imports System.Data.OleDb
Class Form2
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
con.Open()
Dim dvginfo As DataGridView
Dim table As New DataTable("Address")
Dim da As New OleDbDataAdapter("Select * FROM Address", con)
Dim dtrow As DataTable
da.Fill(table)
If table.Rows.Count = 0 Then
Return
End If
For Each dtrow In table.Rows
dvginfo.Rows.Add()
dvginfo.Rows(dvginfo.RowCount - 1).Cells("colFirstname").Value = dtrow("Firstname").ToString()
dvginfo.Rows(dvginfo.RowCount - 1).Cells("colLastname").Value = dtrow("Lastname").ToString()
dvginfo.Rows(dvginfo.RowCount - 1).Cells("colDOB").Value = Convert.ToDateTime(dtrow("DOB").ToString())
Next
dvginfo.ClearSelection()
con.Close()
End Sub
End Class
Try this...
Imports System.Data.OleDb
Class Form2
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
con.Open()
Dim dvginfo As DataGridView
Dim table As New DataTable("Address")
Dim da As New OleDbDataAdapter("Select * FROM Address", con)
Dim dtrow As DataTable
da.Fill(table)
dvginfo.DataSource = table
con.Close()
End Sub
End Class

DataGridView and BindingSource timer issue

I have a DataGridview that displays the data and a TextBox that allows me to filter the BindingSource with an SQL query to display the data based on the input string. This is all working fine apart from once I have filtered the DataGridView the timer function I have is resetting it back so all the data is being displayed again. The timer is set on a 1000ms basis, so it will show the filtered result for a second, then revert back.
Heres my code:
Imports System.Data.OleDb
Public Class Form1
Dim duraGadgetDB As String = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\Dave\Documents\duraGadget.mdb;"
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.Columns(5).Width = 300
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
insert.Show()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
Private Sub txtSearchOnSku_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearchOnSku.TextChanged
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
Dim dsView As New DataView
Dim bs As New BindingSource()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
dsView = ds.Tables(0).DefaultView
bs.DataSource = dsView
bs.Filter = "skuNo LIKE'" & txtSearchOnSku.Text & "*'"
DataGridView1.DataSource = bs
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
End Class
Can anyone tell me how to stop this happening?
Assuming you mean that, if you have entered a value in your text box to filter your results, that you then don't want you timer to fire and unfilter them...
You can either, check the contents of the TextBox in the Timer1_Tick routine;
If txtSearchOnSku.Text <> "" Then Exit Sub
Or you can disable your timer in the txtSearchOnSku_TextChanged routine;
If txtSearchOnSku.Text <> "" Then
Timer1.Stop
Else
Timer1.Start
End If
Or, if you want to update your results once a second, based on you search, you can include the Filtering code in your Timer1_Tick routine.
As a quick point, you have alot of repeated code there. It may be worthwhile refactoring the repeated code out into another sub.