how to read a random entity in a database - vb.net

I was just wondering how I would display a random entity in an access column.
Imports System.Data.OleDb
Public Class ReviseFlashcards
Dim connection As New OleDb.OleDbConnection(
"provider=microsoft.ACE.OLEDB.12.0;Data Source=flashcard login.accdb")
Dim dt As New DataTable
Dim dataadapter As OleDb.OleDbDataAdapter
'contains the current row number
Dim rownumber As Integer = 0
'Data table to contain all the records
Private Sub ReviseFlashcards_Load(sender As Object, e As EventArgs) _
Handles MyBase.Load
Dim sqlstring As String = "select * from flashcards"
connection.Open()
dataadapter = New OleDb.OleDbDataAdapter(sqlstring, connection)
dt.Clear()
dataadapter.Fill(dt)
txtFront.Text = dt.Rows(0)(2)
txtBack.Text = dt.Rows(0)(3)
connection.Close()
End Sub
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) _
Handles btnDisplay.Click
End Sub
End Class
The current code displays the first row in the database which is shown below. I was wondering if there was a way to display a random row by clicking a button with the front and back matching each other.
The access database

Add a random generator to the form. Make shure to declare it as Shared, so that this generator will be created only once. This ensures that it generates unique random number sequencess (see: Why isn't this Random number generation code working?).
Private Shared rand As New Random()
Then create a row index by respecting the actual row count:
Dim index = rand.Next(dt.Rows.Count) ' generates index in the range 0 .. Count - 1
txtFront.Text = dt.Rows(index)(2).ToString()
txtBack.Text = dt.Rows(index)(3).ToString()

Related

vb.net CheckedListbox get value from database

I am populating a CheckedListBox from a MsAccess database table. The table consists of two fields, Terms and RegX. I want to display Terms but when I submit I want to get the value form the RegX field.
Public Function GetMyTable() As DataTable
' Create new DataTable instance.
Dim table As New DataTable
Dim strSql As String = "SELECT * FROM Keywords ORDER BY Terms ASC"
Dim cmd As New OleDbCommand(strSql, con)
Using dr As OleDbDataReader = cmd.ExecuteReader
table.Load(dr)
End Using
Return table
End Function
Private Sub SearchInDoc_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt1 As DataTable = GetMyTable()
If dt1.Rows.Count > 0 Then
For i As Integer = 0 To dt1.Rows.Count - 1
CheckedListBox1.Items.Add(CStr(dt1.Rows(i).Item("Terms")), False)
Next
End If
CheckedListBox1.CheckOnClick = True
End Sub
I dont know how to return the value of RegX when I click my Submit button
If you want to keep together the information about "Terms" and "RegX" then you should use the DataSource property of the CheckedListBox setting it with the datatable retrieved and then specify what column should be showed in the list.
Private Sub SearchInDoc_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt1 As DataTable = GetMyTable()
CheckedListBox1.DataSource = dt1
CheckedListBox1.DisplayMember = "Terms"
CheckedListBox1.CheckOnClick = True
End Sub
Now in your submit button you could add code like this to retrieve the RegX field
Sub Submit_Click(sender As Object, e As EventArgs) Handles Submit.Click
For Each row As DataRowView In CheckedListBox1.CheckedItems
Console.WriteLine(row("RegX"))
Next
End Sub
Each element in the CheckedListBox is a DataRowView taken from the table and you can extract the information about the RegX field simply indexing that DataRowView with the name of the column.
In the example above only the checked items are subject to the loop enumeration. If you want to traverse all the items in the CheckedListBox use CheckedListBox1.Items

Indicate combobox values with a specific ids?

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

Running a quiz for the inputted number

I'm quite new to programming so excuse my lack of knowledge.
I'm trying to create a quiz for my project and am having trouble with it. Currently, I'm trying to make the quiz run until the number of questions is the same as the desired amount the user inputs in a Combobox from the previous form. Whilst this does partially work, the problem is that it is really slow and freezes when you click the button the second time.
Imports System.Data.OleDb
Public Class ArithmeticQuestions
Dim NoQ = ArQOP.NoQ
Dim dr As OleDbDataReader
Dim cm As New OleDbCommand
Dim cn As New OleDbConnection
Dim n As Integer = 1
Private Sub ArithmeticQuestions_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Hide()
RadioButton1.Hide()
RadioButton2.Hide()
RadioButton3.Hide()
RadioButton4.Hide()
SkipQues.Hide()
NxtQues.Hide()
End Sub
Sub Questions()
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=login.accdb"
cn.Open()
cm.CommandText = "SELECT Questions FROM MCQ WHERE QuestionNumber ='" & n & "'"
cm.Connection = cn
dr = cm.ExecuteReader
dr.Read()
Label1.Text = dr.Item("Questions")
cn.Close()
End Sub
Private Sub NxtQues_Click(sender As Object, e As EventArgs) Handles NxtQues.Click
n = n + 1
Do
Call Questions()
Loop Until n = NoQ
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles StartQuiz.Click
Label1.Show()
RadioButton1.Show()
RadioButton2.Show()
RadioButton3.Show()
RadioButton4.Show()
SkipQues.Show()
NxtQues.Show()
StartQuiz.Hide()
Call Questions()
End Sub
End Class
Any help would be appreciated.
I am guessing that NoQ is the number of questions the user requested.
Keep you database objects local to the method where they are used so you can control that they are closed and disposed. Using...End Using blocks take care of this for you even if there is an error. You can pass the connection string directly to the constructor of the connection and the command text and connection directly to the constructor of the command.
Always use Parameters. I had to guess at the OleDbType. Check your database for the correct type and adjust the code accordingly. It appears that you are retrieving a single piece of data so you can use .ExecuteScalar to get the first column of the first row of the result set.
In the button code I just incremented the question number and checked if against the maximum number of questions.
Dim NoQ = ArQOP.NoQ
Dim n As Integer
Private Sub Questions()
Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=login.accdb"),
cmd As New OleDbCommand("SELECT Questions FROM MCQ WHERE QuestionNumber = #QuestionNumber;", cn)
cmd.Parameters.Add("#QuestionNumber", OleDbType.Integer).Value = n
cn.Open()
Label1.Text = cmd.ExecuteScalar.ToString
End Using
End Sub
Private Sub NxtQues_Click(sender As Object, e As EventArgs) Handles NxtQues.Click
n += 1
If n <= NoQ Then
Questions()
End If
End Sub

Removing a row from a datatable

I have a program that asks the user a series of questions that are collected from a database and stored in a datatable.
I have a system that chooses two random numbers, one to determine which question and one to determine what order the answers are displayed. I want questions to remain in the datatable until the user gets it correct, and afterwards that question cannot come up again.
My datatable is called DT, and there's a line of code:
DT.Rows.RemoveAt(QNumber)
Which sounds like it should remove the row selected. However I have a question regarding this.
If for example QNumber was 2, and so row 2 was deleted. Would this then move everything from row 3 in to row 2, and then everything from row 4 to row 3 and so on, or would this just make row 2 blank, and so break my code?
Since you didn't post any context are some test snippets:
Button1_Click loads a table
Button2_Click "processes" each row and optionally deletes the row.
In your case "process" would mean: display the question and loop until you get an answer.
In your case Button2 code would determine which record to load, probably using .Select() on the datatable that returns the "question" to ask, and eventually delete.
Dim da As SqlDataAdapter
Dim ds As DataSet
Dim dt As DataTable
Dim con As New System.Data.SqlClient.SqlConnection()
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Using con As New System.Data.SqlClient.SqlConnection()
con.ConnectionString = "Data Source=APCD03;Initial Catalog=OIStest;Integrated Security=True"
Dim rdr As Data.SqlClient.SqlDataReader
con.Open()
Dim cmd As New SqlCommand("SELECT [DBLinked] as PK ,[TEBackupDate] FROM [OISTest].[dbo].[_DBLink]", con)
rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
dt = New DataTable
dt.Load(rdr)
rdr.Close()
End Using
Catch ex As Exception
MsgBox(ex, ex.Message)
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each row As DataRow In dt.Rows
If Not row.RowState = DataRowState.Deleted Then
If MsgBox("Delete this row, PK: " & row("PK"), vbYesNo) = MsgBoxResult.Yes Then
row.Delete()
End If
End If
Next
End Sub
Button3 demos selecting a specific row to process and delete:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim rows() As DataRow = dt.Select("PK='test row'")
If rows.Length = 0 Then
MsgBox("row was deleted already")
Else
MsgBox(rows(0)(0)) ' display PK
If MsgBox("Delete " & rows(0)(0), vbYesNo) = MsgBoxResult.Yes Then
rows(0).Delete()
End If
End If
End Sub
Note that rows(0) is the first record of the result from the select - not the record index in the overall table.

Issue with Comobox on DataGridView

I am using VB.NET to pull some data from an SQL database into a Datagridview.
I then want the user to be able to modify the information and save it back to the database, which I have working fine.
What I need to be able to do now is to restrict the values, but way of a combobox for the field Tarrif.
I have configured a DataSource called Tarrif1 and I am using the below code.
I have a couple of issues/questions.
Firstly the dropdown shows a single value of "System.Data.DataViewManagerListItemTypeDescriptor" not the Tarrif1 values.
Secondly, I now have 2 columns on my datatable called Tarrif, the original database one and the one I have added - How can I get the ComboBox to right back to the appropriate Tarrif database field.
Here is my code:
Imports System.Data.SqlClient
Imports System.Data.Common
Public Class ViewCustomersForm
Dim ds As DataSet = New DataSet()
Dim connStr As String = "server=barry-laptop\SQLEXPRESS; database=BillingReferenceData; integrated security=yes"
Dim sql As String = "SELECT * FROM Customers"
Dim conn As SqlConnection = New SqlConnection(connStr)
Dim comm As SqlCommand = New SqlCommand(Sql, conn)
Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm)
Private Sub ViewCustomersForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'---open the connection and fill the dataset---
conn.Open()
dataadapter.Fill(ds, "Customers_table")
conn.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "Customers_table"
'---create a combobox column---
Dim comboBoxCol As New DataGridViewComboBoxColumn
'---set the header---
comboBoxCol.HeaderText = "Tarrifs"
'---data bind it---
comboBoxCol.DataSource = Tarrifs1
'comboBoxCol.DisplayMember = "Tarrif" // when I add these rows the new Tarrif column is not visible
'comboBoxCol.ValueMember = "Tarrif" // when I add these rows the new Tarrif column is not visible
'---add a combobox column to the DataGridView control---
DataGridView1.Columns.Add(comboBoxCol)
End Sub
Private Sub Button_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim sqlCmdBuilder As New SqlCommandBuilder(dataadapter)
sqlCmdBuilder.GetUpdateCommand()
dataadapter.Update(ds.Tables("Customers_table"))
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
End Sub
End Class
Hope that makes sense. Any help greatly appreciated.
A few things in this code:
dataadapter.Fill(ds, "Customers_table")
conn.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "Customers_table"
'---create a combobox column---
Dim comboBoxCol As New DataGridViewComboBoxColumn
'---set the header---
comboBoxCol.HeaderText = "Tarrifs"
'---data bind it---
comboBoxCol.DataSource = Tarrifs1
First, I'm not sure what happens whenever the code attempts to fill a DataSet that already has data in it. In my code, I never assume, so I always reinitialize it each time unless I need it:
ds = new DataSet()
Next, you are setting the DataSource for comboBoxCol as Tarrifs1, but I do not see that defined anywhere. You might want to look into that.
Finally, about the SQL: Dim sql As String = "SELECT * FROM Customers" I don't know what columns are in your Customers table. Is Tarrif an actual column?
I figured half my issue out.
I configured a second data connection to pull the Tarrif drop down from the Tarrifs table and display this as part of the customer data table.
My outstanding issues now, is that I need to write the select Tarrif value back to the Customers table.
All the other updated values save, just not sure how to write the Tarrif dropdown back to my SQL table
Here is my latest code.
Imports System.Data.SqlClient
Imports System.Data.Common
Public Class ViewCustomersForm
Dim ds As DataSet = New DataSet()
Dim connStr As String = "server=barry-laptop\SQLEXPRESS; database=BillingReferenceData; integrated security=yes"
Dim sql As String = "SELECT [Customer ID] ,[Customer Name] ,[Address] ,[City] ,[County] ,[Post Code] FROM [BillingReferenceData].[dbo].[Customers]"
Dim conn As SqlConnection = New SqlConnection(connStr)
Dim comm As SqlCommand = New SqlCommand(Sql, conn)
Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm)
Dim con As New System.Data.SqlClient.SqlConnection("server=barry-laptop\SQLEXPRESS; database=Test; integrated security=yes")
Dim strSQL As String = "SELECT * FROM Tarrifs"
Dim da As New System.Data.SqlClient.SqlDataAdapter(strSQL, con)
Private Sub ViewCustomersForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'---open the connection and fill the dataset---
conn.Open()
dataadapter.Fill(ds, "Customers_table")
conn.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "Customers_table"
'---create a combobox column---
Dim comboBoxCol As New DataGridViewComboBoxColumn
'---set the header---
comboBoxCol.HeaderText = "Tarrifs"
'---data bind it---
da.Fill(ds, "Tarrifs")
comboBoxCol.DataSource = ds.Tables("Tarrifs")
comboBoxCol.DisplayMember = "Tarrif"
comboBoxCol.ValueMember = "Tarrif"
'---add a combobox column to the DataGridView control---
DataGridView1.Columns.Add(comboBoxCol)
End Sub
Private Sub Button_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim sqlCmdBuilder As New SqlCommandBuilder(dataadapter)
sqlCmdBuilder.GetUpdateCommand()
dataadapter.Update(ds.Tables("Customers_table"))
dataadapter.Update(ds.Tables("Tarrifs"))
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
End Sub
End Class