My main goal is to code navigation buttons to control records of a vb.net project connected with Microsoft Access Database. The four buttons included are First record, Last record, Next record and Previous record. The errors showing say "ShowData" and "CurrentRow" are not declared.
CurrentRow shows the following error correction options:
ShowData shows the following error correction options:
'to navigate to first record
Private Sub btn_first_Click(sender As Object, e As EventArgs) Handles btn_first.Click
CurrentRow = 0
ShowData(CurrentRow)
End Sub
'to navigate to last record
Private Sub btn_last_Click(sender As Object, e As EventArgs) Handles btn_last.Click
CurrentRow = Dst.Tables("Purchases_file").Rows.Count - 1
ShowData(CurrentRow)
End Sub
'to navigate to previous record
Private Sub btn_previous_Click(sender As Object, e As EventArgs) Handles btn_previous.Click
If CurrentRow <> 0 Then
CurrentRow -= 1
ShowData(CurrentRow)
Else
MsgBox("First record is reached!", MsgBoxStyle.Exclamation)
End If
End Sub
'to navigate to next record
Private Sub btn_next_Click(sender As Object, e As EventArgs) Handles btn_next.Click
If CurrentRow = Dst.Tables("Purchases_file").Rows.Count - 1 Then
MsgBox("Last record is reached!", MsgBoxStyle.Exclamation)
Else
CurrentRow += 1
ShowData(CurrentRow)
End If
End Sub
According to the error you get you did not declare CurrentRow before using it in the methods. Put
Private CurrentRow as Integer
in your class. ShowData calls the method to retrieve the data from the database. It should be something like this:
Private Sub ShowData(byval row as integer)
'code to get the data in the database
End Function
If the variable and method exist in another class of the project you need to reference them via their class. For example:
ClassName.CurrentRow
ClassName.ShowData(CurrentRow)
My Roasters table has field names of Name, City, and Zip. They are bond to labels on the BindingNavigator form and also a DataGridView. The BindingNavigator provides the buttons you describe.
Imports System.Data.SqlClient
Public Class BindingNavigator
Dim WithEvents bindSrc As New BindingSource
Private Sub BindingNavigator_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = LoadData1()
bindSrc.DataSource = dt
BindingNavigator1.BindingSource = bindSrc
lblItem.DataBindings.Add(New Binding("Text", bindSrc, "Name"))
lblDescription.DataBindings.Add(New Binding("Text", bindSrc, "City"))
lblPrice.DataBindings.Add(New Binding("Text", bindSrc, "Zip"))
DataGridView1.DataSource = bindSrc
End Sub
Private Function LoadData1() As DataTable
Dim dt As New DataTable
Using conn As New SqlConnection(My.Settings.CoffeeConnection),
cmd As New SqlCommand("Select Top 10 * From Roasters;", conn)
conn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
End Class
Related
I have two forms: frmMain and frmProduct
In the main form frmMain, I have a Datagridview1 and the buttons: tsbInsert_click, tsbAlter_click and tsbConsult_click.
When I open the main form frmMain, there is still no row in the Datagridview1 and when I click on any of the tsbAlter_click or tsbConsult_click buttons, the code displays the message "Select a product", which is correct , because there is still no product created in the register.
When I click on the tsbInsert_click button, the code opens the frmProduct to insert a record in the register and then returns to the main form frmMain, which, in the line of the Datagridview1, shows the record that was included.
The problem is that when I include a record in the register, the Datagridview1 ALWAYS returns with the state of the selected row, and the condition If DGProducts.CurrentRow Is Nothing is never true again ... so when I click on tsbAlter_click or tsbConsult_click, the "Select a product" message no longer appears and it should have since I didn't select any rows in Datagridview1.
frmMain Code:
Public Class frmMain
Private Sub tsbInsert_Click(sender As Object, e As EventArgs) Handles tsbInsert.Click
Using frm As New frmProduct("Insert", "")
frm.ShowDialog()
If frm.txtPrdCod.Text <> "" Then
DGProducts.Rows.Add(Campo(0), Campo(1), Campo(2))
End If
End Using
End Sub
Private Sub tsbAlter_Click(sender As Object, e As EventArgs) Handles tsbAlter.Click
If DGProducts.CurrentRow Is Nothing Then
MessageBox.Show("Select a product")
Exit Sub
End If
Dim codProd As String = DGProducts.CurrentRows.Cells("prdCod").Value
Using frm As New frmProduct("Alter", codProd)
frm.ShowDialog()
With DGProducts.Rows(DGProds.CurrentCell.RowIndex)
.Cells("prdCod").Value = Field(0)
.Cells("prdName").Value = Field(1)
.Cells("prdManufac").Value = Field(2)
End With
End Using
End Sub
Private Sub DGProducts_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DGProducts.CellEnter
With DGProducts.Rows(DGProducts.CurrentCell.RowIndex)
Campo(0) = .Cells("prdCod").Value
Campo(1) = .Cells("prdName").Value
Campo(2) = .Cells("prdManufac").Value
End With
End Sub
End Class
frmProduct code:
Public Class frmProduct
Private Sub frmProduct_Load(sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If _operation = "Alter" Then
txtPrdCod.Text = Campo(0)
txtPrdName.Text = Campo(1)
txtManufct.Text = Campo(2)
Else
txtPrdCod.Text = ""
txtPrdName.Text = ""
txtManufct.Text = ""
Enf If
End Sub
Dim _operation As String
Dim _codProd As String
Public Sub New(operation As String, codProd As String)
InitializeComponent()
Select Case operation
Case "Insert"
_operation = operation
Case "Alter"
_operation = operation
_codProd = codProd
Case Else
MessageBox.Show("Invalid option!")
Close()
End Select
End Sub
Private Sub tsbRecord_Click(sender As Object, e As EventArgs) Handles tsbRecord.Click
Field(0) = txtPrdCod.Text
Field(1) = txtPrdName.Text
Field(2) = txtManufct.Text
Me.Close()
End Sub
End Class
How do I make it so that when I add a product to the register, Datagridview1 DOES NOT return with the line in the SELECTED state and the message "Select a product" appears when I don't select a line from Datagridview1?
The command DGProducts.Rows.Add(Field(0), Field(1), Field(2)), automatically changes the value DGProducts.SelectedRows.Count to 1, so I set DGProducts.CurrentCell = Nothing after command DGProducts.Rows.Add in code:
Private Sub tsbInsert_Click(sender As Object, e As EventArgs) Handles tsbInsert.Click
Using frm As New frmProduct("Insert", "")
frm.ShowDialog()
If frm.txtPrdCod.Text <> "" Then
DGProducts.Rows.Add(Campo(0), Campo(1), Campo(2))
DGProducts.CurrentCell = Nothing
End If
End Using
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
Helo:
How to overcome the problem of [RowChanged] event within the [DataTable] in the [DataGridView].
Explanation: You have created a column in the dataTable to find out which rows have been modified, in order to facilitate the knowledge of these rows to update them in the database, but the problem in the event(Row_Changed), can not be explained by more words in the code, see the column of (ISCHANGE) after modifying any row and cover the The Save button you find takes the value True and then False;
Public Class Class1
Public Table As DataTable
Sub New()
Table = New DataTable
Table.Columns.Add("IsChange", System.Type.GetType("System.Boolean"))
Table.Columns.Add("TeacherName", System.Type.GetType("System.String"))
Table.Columns("IsChange").DefaultValue = False
Dim dr As DataRow = Table.Rows.Add
dr("TeacherName") = "X1"
dr = Table.Rows.Add
dr("TeacherName") = "X2"
dr = Table.Rows.Add
dr("TeacherName") = "X3"
dr = Table.Rows.Add
AddHandler Table.RowChanged, New DataRowChangeEventHandler(AddressOf Row_Changed)
End Sub
Sub New(SourceDataTable As DataTable)
'Import DataTable
Table = SourceDataTable
End Sub
Public Sub Save()
GotoChange = False 'disable the event (Row_Changed)
For ALoop As Integer = 0 To Table.Rows.Count - 1
'=======================================
'Here Code Save To DataBase
'
'
'=======================================
Table(ALoop)("IsChange") = False 'RowChanged =False
Next
GotoChange = True 'Enabled the event (Row_Changed)
End Sub
Dim GotoChange As Boolean = True 'This variable is to disable the event (Row_Changed)
Private Sub Row_Changed(ByVal sender As Object, ByVal e As DataRowChangeEventArgs)
If Not GotoChange Then Exit Sub
If e.Action = DataRowAction.Add Or e.Action = DataRowAction.Change Then
If CBool(e.Row("IsChange")) = False Then
MsgBox("IsChange")
e.Row("IsChange") = True 'If [True] this means that the row has been changed
End If
End If
End Sub
End Class
Form Code :
Change Any Row Then Button Save:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim A As New Class1
Me.DataGridView1.DataSource = A.Table
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim A As New Class1(Me.DataGridView1.DataSource)
'Change Value Any Row Then Button Save
'Here Problem: Show Column(IsChang) After Save
'The value First (False) Then (True)
A.save()
End Sub
End Class
I want to type something in my txtSearchCriteria textbox and when I hit the Perform Search button it displays all the records it finds into the other textboxes I have in my form. I am using a localdb file with a dataset in Visual Studio 2012. So far I have everything working except the search button. Here is my entire code in my project.
'Import Namespaces for SQL
Imports System.Data
Imports System.Data.SqlClient
Public Class Form1 Dim objCurrencyManager As CurrencyManager
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Loads data into the 'CustomersDataSet.Customers' table.
Me.CustomersTableAdapter.Fill(Me.CustomersDataSet.Customers)
'Controls Record Number Movement
objCurrencyManager = CType(Me.BindingContext(CustomersBindingSource), CurrencyManager)
'Display the current record number
Position()
'Display a tool tip at the bottom of screen
lblToolStripLabel1.Text = "Ready To Compute Data"
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
'Used try catch block to validate all fields to ensure proper use of form and to display error if required fields are missing user imput
Try
Me.Validate()
Me.CustomersBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.CustomersDataSet)
lblToolStripLabel1.Text = "Record Saved" 'Display that record has been saved
Catch ex As Exception
MsgBox(ex.Message)
End Try
Position()
End Sub
Private Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click
'code to update an existing record and display that redord was updated successfully
Try
Me.Validate()
Me.CustomersBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.CustomersDataSet)
lblToolStripLabel1.Text = "Record Updated" 'display record updated
Catch ex As Exception
MsgBox(ex.Message)
End Try
Position()
End Sub
Private Sub dtnDelete_Click(sender As Object, e As EventArgs) Handles dtnDelete.Click
' Removes the current record and displays the new position in the database
Me.CustomersBindingSource.RemoveCurrent()
Position()
End Sub
Private Sub btnMoveFirst_Click(sender As Object, e As EventArgs) Handles btnMoveFirst.Click
'Moves the current record to the begining of the dataset. The First Record
Me.CustomersBindingSource.MoveFirst()
Position()
End Sub
Private Sub btnMovePrevious_Click(sender As Object, e As EventArgs) Handles btnMovePrevious.Click
'moves to the previous record and displays the position
Me.CustomersBindingSource.MovePrevious()
Position()
End Sub
Private Sub btnMoveNext_Click(sender As Object, e As EventArgs) Handles btnMoveNext.Click
'Moves to the next record in the dataset
Me.CustomersBindingSource.MoveNext()
Position()
End Sub
Private Sub btnMoveLast_Click(sender As Object, e As EventArgs) Handles btnMoveLast.Click
'Moves to the last Record in the Dataset
Me.CustomersBindingSource.MoveLast()
Position()
End Sub
Private Sub Position()
'This code displays the positio of the current record the user is viewing and shows it out of the number of recors that are held in the dataset
txtRecordPosition.Text = objCurrencyManager.Position + 1 & " Of " & objCurrencyManager.Count()
End Sub
Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
'Clears the form for user imput, Created a new record and adds the current date to CustomerDate field and adds the next CustomerNumber available.
Me.CustomersBindingSource.AddNew()
txtCustomerNumber.Text = Me.CustomersBindingSource.Count + 1
txtCustomerDate.Text = Date.Today.ToShortDateString
End Sub
Private Sub btnPerformSort_Click(sender As Object, e As EventArgs) Handles btnPerformSort.Click
'Code to Sort by different field within the dataset
Select Case cboField.SelectedIndex
Case 0 'CustomerNumber
CustomersBindingSource.Sort = "CustomerNumber"
Case 1 'First Name
CustomersBindingSource.Sort = "FirstName"
Case 2 'Last Name
CustomersBindingSource.Sort = "LastName"
Case 3 'City
CustomersBindingSource.Sort = "City"
Case 4 'Province
CustomersBindingSource.Sort = "Province"
End Select
btnMoveFirst_Click(Nothing, Nothing)
lblToolStripLabel1.Text = "Records Sorted"
End Sub
Private Sub btnPerformSearch_Click(sender As Object, e As EventArgs) Handles btnPerformSearch.Click
'This will take the user imput from the txtSearchCriteria textbox and return all records that have the criteria
End Sub
End Class
Here is a sample to query database assuming you are connecting to sql server.
Private Sub BindGrid()
Dim constr As String = ConfigurationManager.ConnectionStrings("<your connection string name>").ConnectionString
Using con As New SqlConnection(constr)
Using cmd As New SqlCommand()
cmd.CommandText = "SELECT ContactName, City, Country FROM Customers WHERE ContactName LIKE '%' + #ContactName + '%'"
cmd.Connection = con
cmd.Parameters.AddWithValue("#ContactName", txtSearch.Text.Trim())
Dim dt As New DataTable()
Using sda As New SqlDataAdapter(cmd)
sda.Fill(dt)
gvCustomers.DataSource = dt
gvCustomers.DataBind()
End Using
End Using
End Using
End Sub
To explain at first step we are declaring connection string then we are opening SqlConnection object and then we are querying the database table ContactName based on the txtSearch value inputted.Next we are filling the dataset and binding the grid.
I suggest you to read this msdn article on sql connection.
hi I have a form that find, or should I say filter, the items in a listbox using a textbox. I have a textbox used for searching and a listbox populated with items from database. Now, say listbox items include apple, banana, berry, cashew, lemon, mango, peanut. If I typed 'b' on the textbox, listbox only show banana and berry..if I typed 'ba' then listbox only show banana but if I typed 'be' then it shows berry and so on. I already got this working (with the code marked as commented in the txtSearch event). My problem is that how can I bring the items in the listbox back when the user strike the backspace? Because, say I have banana and berry in the listbox now, when I erased the text that I typed in the textbox it should list back all the items again so that if I want to search another item it will be filtered again. thanks in advance.
Code Update
Public Class Glossary
Private Sub Glossary_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call List()
Refreshlist()
End Sub
Private Sub List()
Dim myCmd As New MySqlCommand
Dim myReader As MySqlDataReader
Dim myAdptr As New MySqlDataAdapter
Dim myDataTable As New DataTable
Call Connect()
With Me
STRSQL = "Select word from glossary"
Try
myCmd.Connection = myConn
myCmd.CommandText = STRSQL
myReader = myCmd.ExecuteReader
If (myReader.Read()) Then
myReader.Close()
myAdptr.SelectCommand = myCmd
myAdptr.Fill(myDataTable)
lstword.DisplayMember = "word"
lstword.ValueMember = "word"
If myDataTable.Rows.Count > 0 Then
For i As Integer = 0 To myDataTable.Rows.Count - 1
lstword.Items.Add(myDataTable.Rows(i)("word"))
Next
End If
End If
'lstword.Items.Clear()
'lstword.Items.AddRange(word.Where(Function(word) word.ToString().Contains(txtSearch.Text)).ToArray())
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
myReader = Nothing
myCmd = Nothing
myConn.Close()
Call Disconnect()
End With
End Sub
Dim word As List(Of Object)
Private Sub Refreshlist()
lstword.Items.Clear()
lstword.Items.AddRange(word.Where(Function(word) word.ToString().Contains(txtSearch.Text)).ToArray())
End Sub
Private Sub txtSearch_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearch.TextChanged
lstword.Items.Clear()
lstword.Items.AddRange(word.Where(Function(word) word.ToString().Contains(txtSearch.Text)).ToArray())
Refreshlist()
'Call List()
'lstword.BeginUpdate()
'Try
' ' keep track of the "non-searched items" '
' Dim word As New List(Of Object)
' lstword.SelectedIndices.Clear()
' If txtSearch.Text.Length > 0 Then
' For index As Integer = 0 To lstword.Items.Count - 1
' Dim item As String = lstword.Items(index).ToString()
' If item.IndexOf(txtSearch.Text, StringComparison.CurrentCultureIgnoreCase) >= 0 Then
' lstword.SelectedIndices.Add(index)
' Else
' ' this item was not searched for; we will remove it '
' word.Add(index)
' End If
' Next
' ' go backwards to avoid problems with indices being shifted '
' For i As Integer = word.Count - 1 To 0 Step -1
' Dim indexToRemove As Integer = word(i)
' lstword.Items.RemoveAt(indexToRemove)
' Next
' End If
'Finally
' lstword.EndUpdate()
'End Try
End Sub
End Class
The first step is to store the items in off-screen memory. For instance:
Dim words As List(Of Object)
Then when you refresh the list box, only populate it with the items from that in-memory list which match the current criteria:
lstword.Items.Clear()
lstword.Items.AddRange(
words.FindAll(
Function(word) Return word.ToString().Contains(txtSearch.Text)
).ToArray()
)
Or, using LINQ:
lstword.Items.Clear()
lstword.Items.AddRange(
words.Where(
Function(word) word.ToString().Contains(txtSearch.Text)
).ToArray()
)
UPDATE
Since you seem to be having trouble getting it working, and it's hard to say what's wrong with your code without actually seeing it, here's a complete working example:
Public Class Form1
Dim words As New List(Of Object)(New String() {"apple", "banana", "berry", "cashew", "lemon", "mango", "peanut"})
Private Sub RefreshList()
lstword.Items.Clear()
lstword.Items.AddRange(
words.Where(
Function(word) word.ToString().Contains(txtSearch.Text)
).ToArray()
)
End Sub
Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChanged
RefreshList()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
RefreshList()
End Sub
End Class
UPDATE 2
I tried using your code with my recommended suggestions and it worked fine. Here's the code that worked for me. Try it and let me know if it doesn't work for you:
Public Class Glossary
Private Sub Glossary_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
List()
Refreshlist()
End Sub
Private Sub List()
word.AddRange(New String() {"apple", "banana", "berry", "cashew", "lemon", "mango", "peanut"})
End Sub
Private word As New List(Of Object)()
Private Sub Refreshlist()
lstword.Items.Clear()
lstword.Items.AddRange(word.Where(Function(word) word.ToString().Contains(txtSearch.Text)).ToArray())
End Sub
Private Sub txtSearch_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearch.TextChanged
Refreshlist()
End Sub
End Class
If that works, then all you need to do is change the List method to load from the database instead of being a hard-coded list.
Get your initial list off the database, pop it in a List class e.g List.
The use your search text to select all the matching items and put them in the list box. Blank search text you just put all of them in.
You might want to have a look at Foreach and List.FindAll as well.