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
Related
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
I made a Sub that will populate my combobox with loan descriptions. I want to get the loancode of the loandescription on selectedindexchanged without querying again the database. Is this possible? Or should I query the database to get the indicated loancode?
Private Sub LoanProducts()
Using cmd As New SqlClient.SqlCommand("SELECT loancode,loandescription FROM LoanProducts", gSQlConn)
Dim dt As New DataTable
Dim da As New SqlClient.SqlDataAdapter
dt.Clear()
da.SelectCommand = cmd
da.Fill(dt)
For Each row As DataRow In dt.Rows
CmbLoanAvail.Items.Add(row("loandescription"))
Next row
End Using
End Sub
Expected output:
Everytime the combobox index changed, the loancode of the selected loandescription will be displayed to a textbox.
Set DataTable to combobox .DataSource property and populate .ValueMember and .DisplayMember properties with corresponding column names.
Private Sub LoanProducts()
Dim query As String = "SELECT loancode, loandescription FROM LoanProducts"
Using command As New SqlCommand(query, gSQlConn)
Dim data As New DataTable
Dim adapter As New SqlClient.SqlDataAdapter With
{
.SelectCommand = cmd
}
adapter.Fill(data)
CmbLoanAvail.ValueMember = "loancode"
CmbLoanAvail.DisplayMember = "loandescription"
CmbLoanAvail.DataSource = data
End Using
End Sub
You can use SelectionChangeCommitted event to execute some action when user made a selection
Private Sub comboBox1_SelectionChangeCommitted(
ByVal sender As Object, ByVal e As EventArgs) Handles comboBox1.SelectionChangeCommitted
Dim combobox As ComboBox = DirectCast(sender, ComboBox)
Dim selectedCode As String = combobox.SelectedValue.ToString() // returns 'loancode'
End Sub
If you could get DB rows as strongly typed classes, you could make use of ItemSource, DisplayMember and ValueMember, which would solve your problem.
In case you presented, you can use SelectedIndex property of ComboBox. Also, you need to store resultset in some class field (preferably Pirvate one). See example code below:
Public Class Form4
Private _result As DataTable
Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable
dt.Columns.Add("col1")
dt.Columns.Add("col2")
dt.Rows.Add("val11", "val12")
dt.Rows.Add("val21", "val22")
' at this point, we got our result from DB
_result = dt
For Each row As DataRow In dt.Rows
ComboBox1.Items.Add(row("col1"))
Next
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim selectedIndex = ComboBox1.SelectedIndex
Dim selectedRow = _result(selectedIndex)
End Sub
End Class
Keep your database objects local to the method where they are used so you can ensure that they are closed and disposed. Note the comma at the end of the first Using line. This includes the command in the same Using block.
Set the DataSource, DisplayMember and ValueMember after the Using block so the user interface code doesn't run until the connection is disposed.
To get the loan code you simply access the SelectValue of the ComboBox.
Private Sub LoanProducts()
Dim dt As New DataTable
Using gSqlConn As New SqlConnection("Your connection string"),
cmd As New SqlClient.SqlCommand("SELECT loancode,loandescription FROM LoanProducts", gSqlConn)
gSqlConn.Open()
dt.Load(cmd.ExecuteReader)
End Using
ComboBox1.DataSource = dt
ComboBox1.DisplayMember = "loandescription"
ComboBox1.ValueMember = "loancode"
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
MessageBox.Show($"The Loan Code is {ComboBox1.SelectedValue}")
End Sub
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
I have created a Datagridview that displays all Data. I now want to be able to filter my data. I am using a DataSet, BindingSource and TableAdapter. I tried a few things but nothing seems to work. Currently I have a TextBox that should filter when written. When I execute and type in the box it doesnt filter or error out. Below is the code that I have. Am I missing Something?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.AllowUserToAddRows = True
DataGridView1.AllowUserToDeleteRows = True
Dim cn As SqlConnection = New SqlConnection("")
adap = New SqlDataAdapter("SELECT res_snbr, First_Name, Last_Name, Item FROM Inventory_Details", cn)
Dim builder As New SqlCommandBuilder(adap)
adap.InsertCommand = builder.GetInsertCommand()
'adap.UpdateCommand = builder.GetUpdateCommand()
'adap.DeleteCommand = builder.GetDeleteCommand()
dt = New DataTable()
adap.Fill(dt)
DataGridView1.DataSource = dt
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.TextLength > 0 Then
InventoryDetailsBindingSource.Filter = _
String.Format("res_snbr Like '%" & TextBox1.Text) & "%'"
Else
InventoryDetailsBindingSource.Filter = String.Empty
End If
End Sub
Imports System.Data.SqlClient
Public Class Form1
Dim cn As New SqlConnection("Data Source=;Initial Catalog=;Persist Security Info=True;User ID=;Password=")
Dim adap As New SqlDataAdapter("SELECT res_snbr, First_Name, Last_Name, Item FROM Inventory_Details", cn)
Dim builder As New SqlCommandBuilder(adap)
Dim dt As New DataTable
Dim InventoryDetailsBindingSource As New BindingSource
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
adap.InsertCommand = builder.GetInsertCommand()
adap.Fill(dt)
InventoryDetailsBindingSource.DataSource = dt
DataGridView1.DataSource = InventoryDetailsBindingSource
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.TextLength > 0 Then
InventoryDetailsBindingSource.Filter = String.Format("res_snbr Like '%{0}%'", TextBox1.Text)
Else
InventoryDetailsBindingSource.Filter = String.Empty
End If
End Sub
End Class
There are a number of ways to accomplish what you wish to do here, the code above is how I would do it. Among other differences, please note that the BindingSource is being used as the the DataSource for the DataGridView, and the correct use of String.Format when setting the Filter property of the BindingSource.
Cheers!
If your datasource is a datatable you can try this.
TryCast(InventoryDetailsBindingSource, DataTable).DefaultView.RowFilter = String.Format("Field = '{0}'", textBoxFilter.Text)
You can use the row filter property on the datatable as shown here.
http://www.csharp-examples.net/dataview-rowfilter/
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!!