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
Related
I am using SQL Server 2016 Visual studio 2017.
Need to fill checkedlistbox2, from my database, based on the value of the SelectedItem of Checkedlistbox1.
I am filling checkedlistbox1 on Form.Load as below:
This code is working.
Private Sub fillChkboxList()
Dim conn As New SqlConnection("Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX")
Dim sda As New SqlDataAdapter("select DepartmentName, DepartmentID from DepartmentMain where active=1 order by DepartmentName", conn)
Dim dt As New DataTable
sda.Fill(dt)
CheckedListBox1.DataSource = dt
CheckedListBox1.DisplayMember = "DepartmentName"
CheckedListBox1.ValueMember = "DepartmentID"
End Sub
Here I am trying to use a method to fill Checkedlistbox2, which I am calling in the ItemCheck event handler of Checkedlistbox1:
Below Code is not giving required results
Public Function fillChkboxListSub()
Dim i As Integer
Dim conn1 As New SqlConnection("Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX")
With CheckedListBox2
For i = 0 To CheckedListBox1.Items.Count - 1 Step i + 1
If CheckedListBox1.GetItemCheckState(i) = CheckState.Checked Then
Dim xx As String = (CType(CheckedListBox1.Items(i), DataRowView))("DepartmentID")
Dim sqlstr2 As String = "select SubName,SubDeptID from DepartmentSub where active=1 and DepartmentID in ('" & xx & "') order by SubName"
Dim command2 As New SqlCommand(sqlstr2, conn1)
Dim adpt2 As New SqlDataAdapter(command2)
adpt2.SelectCommand = command2
adpt2.Fill(dt2)
CheckedListBox2.DataSource = dt2
CheckedListBox2.DisplayMember = "SubName"
CheckedListBox2.ValueMember = "SubDeptID"
End If
Next
End With
End Function
This function I am calling on:
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
fillChkboxListSub()
End Sub
I am not getting the result.
If I check the (DepartmentName) in checkedlistbox1, SubDeptName should load in checkedlistbox2. If I deselect the same in checkedlistbox1, it should be deleted or removed from checkedlistbox2Please help with working code example.
Thanks in Advance
Most database objects need to be disposed. Connections, Commands, and DataReaders have a Dispose method that must be called to release unmanaged resources that they use. It is made easy for us with Using...End Using blocks that ensure that Dispose is called even if there is an error.
The order of setting the DataSource, DisplayMember, and ValueMember is important. Setting DataSource should be last line. If you set ValueMember before DataSource no action is triggered. If you set Datasource first, the box will bind value member for you. Then, you're going to set a new ValueMember (the one you want) and box will have to re-wire binding. So, if you set DataSource last, bindings will happen only once.
You can use the CheckedItems collection to loop through. Add eacn item to a list. After the loop use Join with a comma separator to prepare the In clause for the sql string. I used an interpolated string to build the sql string indicated by the preceding $. Variables can then be inserted in line surrounded by { } .
Private CnString As String = "Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX"
Private Sub fillChkboxList1()
Dim dt As New DataTable
Using conn As New SqlConnection(CnString),
cmd As New SqlCommand("select DepartmentName, DepartmentID from DepartmentMain where active=1 order by DepartmentName", conn)
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
CheckedListBox1.DisplayMember = "DepartmentName"
CheckedListBox1.ValueMember = "DepartmentID"
CheckedListBox1.DataSource = dt
End Sub
Public Sub fillChkboxList2()
Dim lst As New List(Of Integer)
For Each item In CheckedListBox1.CheckedItems
Dim drv = DirectCast(item, DataRowView)
Dim DepId As Integer = CInt(drv("DepartmentId"))
lst.Add(DepId)
Next
Dim DepIdString = String.Join(",", lst)
Dim sql As String = $"select SubName,SubDeptID from DepartmentSub where active=1 and DepartmentID in ({DepIdString}) order by SubName"
Debug.Print(sql) 'See if your select string looks correct.
Dim dt As New DataTable
Using cn As New SqlConnection(CnString),
cmd As New SqlCommand(sql, cn)
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
CheckedListBox2.DisplayMember = "SubName"
CheckedListBox2.ValueMember = "SubDeptID"
CheckedListBox2.DataSource = dt
End Sub
all. I am facing an issue on how to pass the dynamic parameter value from SQL query, that will be entered by the user into the textbox, to the SQL command to search on the parameter value on the datagridview datatable.
For my project, a textbox will be provided for the user to key in the SQL query dynamically to search on the database data. If the user keys in SQL query like
select *
from table
where a = #a
The user can search on #a parameter value; if the user keys in SQL query like
select *
from table
where a = #a and b = #b
The user can search the #a and #b parameter values by using textbox, which means that the parameter number that had been entered by the user needs to be calculated, retrieved, passed to the SQL command and allow the user to filter on the parameter by using textbox provided.
However, currently, due to the #a parameter and #b parameter will be key in by the user dynamically during runtime, so I faced difficulty to declare/define the parameter name on the cmd.Parameters.AddWithValue() statement.
Can anyone help me to solve my problem by providing me some solutions on codes? I had been stuck on this issue for a few days already. Thank you for all the help!
The code I had tried:
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
Sql = TextBox4.Text
Try
'open database
Dim con As New SqlConnection(dbstring)
con.Open()
Dim cmd As New SqlCommand(Sql, con)
If param IsNot Nothing Then
For Each para As SqlParameter In param
'cmd.Parameters.Add(para)
For m As Integer = 0 To param.Count - 1
cmd.Parameters.Add(New SqlParameter With {.ParameterName = para.ParameterName(m),
.Value = para.Value(m),
.SqlDbType = SqlDbType.NVarChar,
.Size = 99})
Next
cmd.ExecuteNonQuery()
Next
End If
Using sda = New SqlDataAdapter()
sda.SelectCommand = cmd
cmd.CommandText = Sql
Sql = cmd.ExecuteScalar()
Using ds As DataSet = New DataSet()
sda.Fill(ds)
con.Close()
DataGridView1.DataSource = ds.Tables(0)
End Using
End Using
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Screenshot of Window App Formhad been provided as a reference.
To avoid SQL Injection, im usally doing like this:
Dim text1 As String = "text1"
Dim objComm As SqlCommand = New SqlCommand
objComm.Parameters.AddWithValue("#text1", text1)
objComm.CommandText = "SELECT * FROM TABLE WHERE Text1 = #text1"
I am not sure why you would want the user to write Select statements. I assume this query is on a single table where you know the field names, types and field sizes where applicable. I made up the these items. You will have to check your database to get the correct information.
I used Optional parameters in case you have other datatypes like Booleans or numbers where you can supply the defaults. To pass no value for the parameter just leave a blank but insert the appropriate commans.
Private Function GetSearchResults(Optional FirstName As String = "", Optional LastName As String = "") As DataTable
Dim dt As New DataTable
Using con As New SqlConnection(dbstring),
cmd As New SqlCommand()
Dim sb As New StringBuilder
sb.Append("Select * From SomeTable Where 1 = 1")
If FirstName <> "" Then
cmd.Parameters.Add("#a", SqlDbType.NVarChar, 100).Value = FirstName
sb.Append(" And FirstName = #a")
End If
If LastName <> "" Then
cmd.Parameters.Add("#b", SqlDbType.NVarChar, 100).Value = LastName
sb.Append(" And LastName = #b ")
End If
sb.Append(";")
Debug.Print(sb.ToString)
cmd.CommandText = sb.ToString
cmd.Connection = con
con.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Alternative useage:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt = GetSearchResults(TextBox1.Text, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim dt = GetSearchResults(, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim dt = GetSearchResults(TextBox1.Text, )
DataGridView1.DataSource = dt
End Sub
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
Fist column of listview is populated from database (database column name KONTO - only values that starts with 2020-), second column of the listview should be populate from corresponding items to KONTO from same database column NAZIV into second column of the listview.
Description is in column NAZIV in databsase
I've been experimenting with this all day and didn't have any success.
Here is the code I have so far :
ListView1.View = System.Windows.Forms.View.Details
ListView1.Columns.Add("COL1", 100, HorizontalAlignment.Left) 'KONTO
ListView1.Columns.Add("COL2", 160, HorizontalAlignment.Left) 'NAZIV
Dim FilePath As String = "W:\GLAVNI\KOR14\"
Dim DBF_File As String = "MATIKGL"
Dim ColName As String = "KONTO"
'Dim naz As String
Using con As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FilePath & _
" ;Extended Properties=dBASE IV")
con.Open()
Using cmd As New OleDbCommand("SELECT * FROM MATIKGL ORDER BY KONTO, NAZIV", con)
Using reader As OleDbDataReader = cmd.ExecuteReader()
If reader.HasRows Then
While (reader.Read())
Me.ListView1.Items.Add(reader("KONTO"))
'LOOP BELOW SELECTS ALL ITEMS THAT STARTS WITH 2020-
For i = 0 To ListView1.Items.Count - 1
If ListView1.Items(i).ToString.Contains("2020-") Then
Else
ListView1.Items.Remove(ListView1.Items(i))
End If
Next
End While
Else
End If
End Using
End Using
con.Close()
End Using
Thanks.
UPDATE
To be more clear, here is the screen from database.
Only items starting with 2020- (1) should populate first column of listview, and second column should be populated with "2020-" description from column NAZIV (2).
Each LV Item has a collection of SubItems associated with it. The subItems show as columns in the Details view:
Dim lvi As ListViewItem ' scratch var for adding items
Dim tmp As String
Using cmd As New OleDbCommand("SELECT * FROM MATIKGL ORDER BY KONTO, NAZIV", con)
Using reader As OleDbDataReader = cmd.ExecuteReader()
If reader.HasRows Then
While (reader.Read())
' Db rdr returns Object, cast to string
tmp = reader.Item("KONTO").ToString
' no need to loop - just use the scratch vars
' only adding if it contains 2020
If tmp.Contains("2020-") Then
lvi = New ListViewItem
lvi.Text = tmp
' add the sub item
lvi.SubItems.Add(reader("NAZIV").toString)
ListView1.Items.Add(lvi)
End If
End While
End If
End Using
you can get rid of the tmp var using reader.Item("KONTO").ToString.Contains("2020")...the above is for clarity
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.