I have a SQL Server Compact database created through VS 2010 (Local Database File option).
On form load (CategoryForm) I load the values from the database into the DataGridView1. I also add an extra ButtonColumn programmatically that I use for the Delete part.
The problem is this:
On initial form load, the first time I press delete on any row, it works. If i press it again it does not work.
The second time i click the button, the printed text I get on my Msgbox, is the Text of button! (delete) (screenshot included) p.s As mentionted below, when I comment-out the extra stuff, I get the correct values returned.
What I tried:
Commented out everything SQL-related, left only the part where I get the RowIndex and the value at the specific cell at that index. I print them both on MsgBox. The values I get are correct. For example, 0 index and value test for first row with text test.
Below is my progress as well as screenshots:
CellContentClick method:
Private Sub DataGridView1_CellContectClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim i As String
'If e.ColumnIndex = 1 Then
'If e.RowIndex >= 0 And e.RowIndex <= DataGridView1.Rows.Count - 1 Then
i = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString
MsgBox(e.RowIndex)
MsgBox(i)
SQLStringDelete = "DELETE FROM Category WHERE categoryname = '" & i & "'"
SQLConn.ConnectionString = ConnString 'Set the Connection String
SQLConn.Open() 'Open the connection
SQLCmd.Connection = SQLConn 'Sets the Connection to use with the SQL Command
SQLCmd.CommandText = SQLStringDelete 'Sets the SQL String
SQLCmd.ExecuteNonQuery() 'Executes SQL Command
'Create Adapter
Dim DataAdapter As SqlCeDataAdapter = New SqlCeDataAdapter("SELECT categoryname FROM Category", SQLConn)
'Create DataSet
Dim Dataset As New DataSet
'fill the datset
DataAdapter.Fill(Dataset)
'attach dataset to the datagrid
With DataGridView1
.DataSource = Dataset.Tables(0)
.Columns(0).HeaderText = ""
.Columns(0).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End With
DataAdapter = Nothing
Dataset = Nothing
SQLConn.Close() 'Close the connection
End Sub
Form_Load method:
Private Sub CategoryForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SQLConn.ConnectionString = ConnString 'Set the Connection String
SQLConn.Open() 'Open the connection
'Create Adapter
Dim DataAdapter As SqlCeDataAdapter = New SqlCeDataAdapter("SELECT categoryname FROM Category", SQLConn)
'Create DataSet
Dim Dataset As New DataSet
'fill the datset
DataAdapter.Fill(Dataset)
'attach dataset to the datagrid
With DataGridView1
.DataSource = Dataset.Tables(0)
.Columns(0).HeaderText = ""
.Columns(0).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
End With
DataAdapter = Nothing
Dataset = Nothing
SQLConn.Close()
With buttonColumn
.Name = "DeleteButtonColumn"
.HeaderText = ""
.Text = "Delete"
.UseColumnTextForButtonValue = True
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
.Width = 50
End With
If DataGridView1.Columns.Count = 1 Then
DataGridView1.Columns.Add(buttonColumn)
End If
End Sub
Screenshots:
Turns out that the columns where autoregenerating causing column re-arrangement on each the second click. Just set DataGridView1.AutoGenerateColumns = false in both the form load and event and it works.
Related
I'm trying to synchronize the reading of a SQL Server table with 2 columns (nom_unité and cout_unité).
The first column (nom_unité) will be populated into a combobox and I want the second column (cout_unité) to be synchronized into a label with the first combobox (meaning, when I change the combobox value, the label should change too refering to the table).
I can do this with 2 comboboxes :
Dim connection As New SqlConnection("Data Source=xxx")
Dim dt As New DataTable
Dim sqlquery As String
connection.Open()
sqlquery = "select * from liste_unités"
Dim SQL As New SqlDataAdapter(sqlquery, connection)
SQL.Fill(dt)
Dim cmd As New SqlCommand(sqlquery, connection)
ComboBoxC1L1.DataSource = dt
ComboBoxC1L1.DisplayMember = "nom_unité"
ComboBox1.DataSource = dt
ComboBox1.DisplayMember = "cout_unité"
but I do not know how to do it with a label (instead of ComboBox1).
I believe I can achieve it with something like that :
Dim sqlcmd As New SqlCommand("select * from liste_unités", connection)
Dim myreader As SqlDataReader
myreader = sqlcmd.ExecuteReader()
myreader.Read()
If myreader.HasRows Then
Label1.Text = myreader.Item("cout_unité").ToString
End If
but this is only reading the first row and not changing the label value when changing the first combobox selected value.
How to do it the easiest and most efficient way ?
Thank you :)
As you have assigned the datasource of the combobox to a datatable which contains the information you need, you can get that information when the value of the combobox changes.
I started a new Windows Forms project and put a combobox (named "cbNomUnité") and a label (named "lblCoutUnité") on Form1 and used this code:
Imports System.Data.SqlClient
Public Class Form1
Dim connStr As String = "Server=.\SQLEXPRESS;Database=Testing;Trusted_Connection=true;"
Sub PopulateCB()
Dim sql = "SELECT nom_unité, cout_unité FROM liste_unités"
Dim dt As New DataTable
Using conn As New SqlConnection(connStr),
da As New SqlDataAdapter(sql, conn)
da.Fill(dt)
End Using
cbNomUnité.DataSource = dt
cbNomUnité.DisplayMember = "nom_unité"
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbNomUnité.SelectedIndexChanged
Dim cb = DirectCast(sender, ComboBox)
If cb.SelectedIndex >= 0 Then
Dim val = DirectCast(cb.SelectedItem, DataRowView).Row.Field(Of String)("cout_unité")
lblCoutUnité.Text = val
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PopulateCB()
End Sub
End Class
To get a program that does this:
(Refresh the page to see the animation again.)
I have designed a SQL Server database app in which I fetch data from database and then insert in text boxes. I use a function to fetch data in data table from database and then I populate textboxes. I have to use this coding again and again:
If Dt.Rows.Count > 0 Then
TxtCust_Id.Text = Dt.Rows(0).Item(0)
TxtCust_City.Text = Dt.Rows(0).Item(1)
TxtCust_Area.Text = Dt.Rows(0).Item(2)
Else
TxtCust_Id.Text = String.Empty
TxtCust_City.Text = String.Empty
TxtCust_Area.Text = String.Empty
End if
Text boxes names changes according to query tables. My question is. Is it possible to make a function or procedure to populate data in text boxes from datatable using loops or any other method? Thanks in advance.
Shared Function ExecuteSelectDt(ByVal SelectCommand As String) As DataTable
Cmd = New SqlClient.SqlCommand
Sda = New SqlDataAdapter
' Dt = New DataTable
Try
DBConnection() ' Database connection details
Sda = New SqlDataAdapter(SelectCommand, Con)
Dim dt2 As New DataTable
Sda.Fill(dt2)
CloseConnection()
Return dt2
Catch ex As Exception
CloseConnection()
MsgBox(ex.Message)
Return dt
End Try
End Function
Private Sub TxtCust_Name_Leave(sender As Object, e As EventArgs) Handles TxtCust_Name.Leave
SQuery = "select Cust_Id, Cust_City, Cust_Area from TBLCustommers where Cust_Name= '" & TxtCust_Name.Text & "'"
Dt = Nothing
Dt = BM_Class_Liberary.SQLSereverDB.ExecuteSelectDt(SQuery)
If Dt.Rows.Count > 0 Then
TxtCust_Id.Text = Dt.Rows(0).Item(0)
TxtCust_City.Text = Dt.Rows(0).Item(1)
TxtCust_Area.Text = Dt.Rows(0).Item(2)
Else
TxtCust_Id.Text = String.Empty
TxtCust_City.Text = String.Empty
TxtCust_Area.Text = String.Empty
End if
End Sub
'create and populate list
dim txtBoxes as new List(of TextBox)();
for each ctrl as Control in Form.Controls
if ctrl.GetType() Is GetType(TextBox) then txtBoxes.Add(ctrl)
next
' then do this when you get DataTable
dim theRow as DataRow = dt.Rows(0); ' whatever logic you have to getting needed row
for each col as DataColumn in dt.Columns
' use system.linq
txtBoxes.First(function(tb) tb.Name = col.ColumnName).Text = theRow(col.ColumnName).ToString()
next
Note, when theRow(col.ColumnName) is DBNull.Value, ToString will return string.Empty, which is fine because .Text can't have Nothing
Also, I used First because I did it with the premise that each column has text box.
Or, using the dictionary. Even better, I think
'create and populate dictionary
dim txtBoxes as new Dictionary(of string, TextBox)();
for each ctrl as Control in Form.Controls
if ctrl.GetType() Is GetType(TextBox) then txtBoxes.Add(ctrl.Name, ctrl)
next
' then do this when you get DataTable
dim theRow as DataRow = dt.Rows(0); ' whatever logic you have to getting needed row
for each col as DataColumn in dt.Columns
txtBoxes(col.ColumnName).Text = theRow(col.ColumnName).ToString()
next
I've tried to add relation, to show the data on combobox and datagridview. I've tried this code below
Private Sub LoadSemester()
Me.OpenConn()
Dim dSet As New DataSet
Dim sql1 As String = "SELECT * FROM tbl_semester"
Dim comm1 As New SqlClient.SqlCommand(sql1, cnn)
Dim daSemester As SqlClient.SqlDataAdapter
Dim sql2 As String = "SELECT * FROM tbl_mk"
Dim comm2 As New SqlClient.SqlCommand(sql2, cnn)
Dim daMK As SqlClient.SqlDataAdapter
daMK = New SqlClient.SqlDataAdapter(comm2)
dSet.Clear()
daMK.Fill(dSet, "tbl_mk")
daSemester = New SqlClient.SqlDataAdapter(comm1)
dSet.Clear()
daSemester.Fill(dSet, "tbl_semester")
dSet.Relations.Add("relation", dSet.Tables("tbl_semester").Columns("id_pk"), dSet.Tables("tbl_pk").Columns("id_pk"))
With cmbSemester
.DataSource = dSet.Tables("tbl_semester")
.DisplayMember = "semester"
.ValueMember = "id_semester"
.SelectedIndex = 0
End With
'my datagridview here
End Sub
But it displayed nothing. But when I deleted the 'dSet.Relations.Add("relation", dSet.Tables("tbl_semester").Columns("id_pk"), dSet.Tables("tbl_pk").Columns("id_pk"))' the combobox showed the data.
I figured out maybe the problem is the dSet.Relation code. FYI, I am using SQLServer 2005 and VS Express 2012.
I need to list all the tables in the list box from the database.mdb file. Not the contents of the tables just the tables name using Microsoft.Jet.OLEDB.4.0
I'm new to vb.net, please help.
this is what i have so far.. and i keep getting errors
Dim dbpath As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
dbpath = New Uri(dbpath).LocalPath
TextBox1.Text = dbpath + "\database.mdb"
Dim userTables As DataTable = Nothing
Dim connection As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection()
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; data source =" textbox1.text
' We only want user tables, not system tables
Dim restrictions() As String = New String(4) {}
restrictions(3) = "Table"
connection.Open()
' Get list of user tables
userTables = connection.GetSchema("Tables", restrictions)
connection.Close()
' Add list of table names to listBox
Dim i As Integer
For i = 0 To userTables.Rows.Count - 1 Step i + 1
ListBox1.Items.Add(userTables.Rows(i)(2).ToString())
Next
You can use the following code segment to display the list of tables in a .mdb file Click Here to get reference
Dim userTables As DataTable = Nothing
Dim connection As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection()
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;//your database path"
' We only want user tables, not system tables
Dim restrictions() As String = New String(4) {}
restrictions(3) = "Table"
connection.Open()
' Get list of user tables
userTables = connection.GetSchema("Tables", restrictions)
connection.Close()
' Add list of table names to listBox
Dim i As Integer
For i = 0 To userTables.Rows.Count - 1 Step i + 1
ListBox1.Items.Add(userTables.Rows(i)(2).ToString())
Next
seem this the right answer
Dim userTables As DataTable = Nothing
Dim connection As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection()
Dim source As String
source = TextDBPath.Text
connection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + source
Dim restrictions() As String = New String(3) {}
restrictions(3) = "Table"
connection.Open()
' Get list of user tables
userTables = connection.GetSchema("Tables", restrictions)
connection.Close()
' Add list of table names to listBox
Dim i As Integer
For i = 0 To userTables.Rows.Count - 1 Step i + 1
cbox.items.add(userTables.Rows(i)(2).ToString())
Next
So far I have this, which doesn't work. I think I'm off on the wrong path here. Basically I'm trying to transfer all of the items of a list box to separate columns of an Access DB named CalcOps, with the columns of "NumOne, Operator, NumTwo, Result). The list box can currently have 10 total list items, all of which should be transferred when the button is clicked (ButtonDBSave). The list box items are put together from separate text boxes and the operator that is clicked on is transferred to the list box via Listbox.tag. Not getting any errors...or anything else.
Private Sub ButtonDBSave_Click(sender As Object, e As EventArgs) Handles ButtonDBSave.Click
Dim con As New OleDb.OleDbConnection
Dim dbProvider As String
Dim dbSource As String
dbProvider = "Provider=Microsoft.ACE.OLEDB.12.0"
dbSource = "Data Source=|DataDirectory|\CalcDB.accdb"
con.ConnectionString = dbProvider & dbSource
Dim arr As New List(Of String)
Dim cmdText As String = "INSERT INTO NumOne ()"
Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand(cmdText)
cmd.CommandType = CommandType.Text
con.Open()
With cmd.Parameters
.Add("#NumOne", OleDb.OleDbType.VarChar).Value = NumOne.Text
End With
End Sub