vb.net : Input array is longer than the number of columns in this table - vb.net

i have follow code in my vb.net project
the connection to the sql db is fine & ok , only when i try to fill the listbox i get a error
Public Class Form1
Private myTable As New DataTable()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
GetSerialPortNames()
FillListBox()
'------------
myTable.Columns.Add("naam", GetType(String))
myTable.Columns.Add("waarde", GetType(Integer)) '<<<< change the type of this column to what you actually need instead of integer.
ListBox1.DisplayMember = "naam"
ListBox1.ValueMember = "waarde"
ListBox1.DataSource = myTable
End Sub
and
Private Sub FillListBox()
Dim naam As String
Dim stringConn As String
Dim stringCmd As String
Dim myConn As MySqlConnection
Dim myCmd As MySqlCommand
'Frame your query here.
stringCmd = "SELECT id,naam,voornaam FROM deelnemers WHERE finger = FALSE ORDER BY naam "
'Frame your connection string here.
stringConn = "********************************************"
'Get your connection here.
myConn = New MySqlConnection(stringConn)
'Get a command by using your connection and query.
myCmd = New MySqlCommand(stringCmd, myConn)
'Open the connection.
myConn.Open()
'create a reader to store the datum which will be returned from the DB
Dim myReader As MySqlDataReader
'Execute your query using .ExecuteReader()
myReader = myCmd.ExecuteReader()
'Reset your List box here.
ListBox2.Items.Clear()
While (myReader.Read())
'Add the items from db one by one into the list box.
naam = myReader.GetString(1) & " " & myReader.GetString(2)
'ListBox2.Items.Add((naam))
myTable.Rows.Add(naam, myReader.GetString(0))
End While
'Close the reader and the connection.
myReader.Close()
myConn.Close()
End Sub
i get error on follow line
myTable.Rows.Add(naam, myReader.GetString(0))
with follow description : Input array is longer than the number of columns in this table.
someone who see ??

I suspect that your myTable datatable does not have any columns...
Try changing:
While (myReader.Read())
'Add the items from db one by one into the list box.
naam = myReader.GetString(1) & " " & myReader.GetString(2)
'ListBox2.Items.Add((naam))
myTable.Rows.Add(naam, myReader.GetString(0))
End While
to this:
Dim row As DataRow
While (myReader.Read())
'Add the items from db one by one into the list box.
row = myTable.NewRow()
row("naam") = myReader.GetString(1) & " " & myReader.GetString(2)
row("waarde") = myReader.GetString(0)
myTable.Rows.Add(row)
End While
you should still get an error, but at least this way you'll know what columns are missing...
update
Also, change this:
FillListBox()
'------------
myTable.Columns.Add("naam", GetType(String))
myTable.Columns.Add("waarde", GetType(Integer)) '<<<< change the type of this column to what you actually need instead of integer.
to this:
'------------
myTable.Columns.Add("naam", GetType(String))
myTable.Columns.Add("waarde", GetType(Integer)) '<<<< change the type of this column to what you actually need instead of integer.
FillListBox()

Related

How to feed results of SQL statement into a GridView, not the SQL statement itself?

This has got to be close, but it's been a long day and I'm tired now so I can;t really see what the problem is. Basically, I have a table in SQL Server with 2 columns; one has the names of reports and the other has some SQL Scripts that I want to pass into a GridView, based on what a user selects from a ListBox. Here is my code.
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
Dim sqlConn As New SqlClient.SqlConnection("Data Source=EXCEL-PC\SQLEXPRESS;Initial Catalog=Test;Integrated Security=True")
sqlConn.Open()
Dim cmd As New SqlClient.SqlCommand("Select ReportName From [Table_1] order by ReportName", sqlConn)
Dim dsColumns As New DataSet
Dim daAdapter As New SqlClient.SqlDataAdapter(cmd)
daAdapter.Fill(dsColumns)
If dsColumns.Tables(0).Rows.Count > 0 Then
ListBox1.Items.Clear()
For i As Integer = 0 To dsColumns.Tables(0).Rows.Count - 1
ListBox1.Items.Add(dsColumns.Tables(0).Rows(i)(0).ToString())
Next
End If
Catch ex As Exception
End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim connetionString As String
Dim SqlStr As String
Dim connection As SqlConnection
Dim adapter As SqlDataAdapter
Dim ds As New DataSet
Dim myItem As String
connetionString = "Data Source=EXCEL-PC\SQLEXPRESS;Initial Catalog=Test;Integrated Security=True"
connection = New SqlConnection(connetionString)
'Dim iIndex As Integer = ListBox1.SelectedIndex
myItem = ListBox1.SelectedItem
SqlStr = "select SqlScript from [Table_1] Where ReportName = '" & myItem & "'"
Try
connection.Open()
adapter = New SqlDataAdapter(SqlStr, connection)
adapter.Fill(ds)
connection.Close()
DataGridView1.DataSource = ds.Tables(0)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
End Class
I guess the problem is passing the SQL to the GridView. When I select the first Item, I see this in my GridView.
SELECT [OrderID]
,[CustomerID]
,[EmployeeID]
,[OrderDate]
,[RequiredDate]
,[ShippedDate]
,[ShipVia]
,[Freight]
,[ShipName]
,[ShipAddress]
,[ShipCity]
,[ShipRegion]
,[ShipPostalCode]
,[ShipCountry]
FROM [Test].[dbo].[Orders]
That's pretty close, but I want to get that SQL fed into the GridView, and get the results of the SQL displayed in the GridView, not eh SQL statement itself.
This is what I see now.
I want to see something more like this.
Finally, I am curious to know of the GridView can be made dynamic, so if I stretch out the window the GridView shows more columns. Now, if I stretch out the form window, the GridView stays static.
You need to actually run the retrieved Sql statement:
sqlstr = "select SqlScript from [Table_1] Where ReportName = '" & myItem & "'"
Try
connection.Open()
Dim cmd As New SqlCommand(sqlstr, connection)
Dim sqlstr_report As String = CStr(cmd.ExecuteScalar())
cmd.Dispose()
adapter = New SqlDataAdapter(sqlstr_report, connection)
adapter.Fill(ds)
connection.Close()
DataGridView1.DataSource = ds.Tables(0)
Use the .Anchor property of the DataGridView to make it resize with the form

VB.net/MS Access Monthly Donations System Assistance

I'm doing a project for my Database Management subject. I cannot figure out how to add an amount to a previously added amount. For now, I'm only able to update the amount. Here's the code. I'm sorry if I cannot explain it well.
I have 2 forms. My first form allows me to enter a last name and retrieve the data to my list view.
My second form lets me retrieve the data I entered in my first form and it will show up on a separate list view with a "Last Name | Amount" tab.
I have two textboxes. One for last name set to readonly to disable editing, and another for the amount I want to enter.
After entering an amount, let's say 20, it will update on the listview and my database as 20.
The problem is that when I enter a new amount for the same last name, let's say 30, the 30 will replace the 20 but it should be 50 because 20+30 = 50.
I understand the logic and I have tried adding another textbox for addition but I simply do not know the codes for it.
Imports System.Data.OleDb
Public Class Form2
Dim conString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Israel De Leon\Documents\testing.accdb;"
Dim con As OleDbConnection = New OleDbConnection(conString) 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database2.accdb
Dim cmd As OleDbCommand
Dim adapter As OleDbDataAdapter
Dim dt As DataTable = New DataTable()
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'SET LISTVIEW PROPERTIES
ListView1.View = View.Details
ListView1.FullRowSelect = True
'Construct Columns
ListView1.Columns.Add("Last Name", 100)
ListView1.Columns.Add("Amount", 100)
End Sub
Private Sub UpdateLV(lname As String)
'Updates last name and amount entered into the database
Dim sql As String = "UPDATE Table1 SET LastName='" + TextBox1.Text + "',Amount='" + TextBox2.Text + "' WHERE LastName='" + lname + "'"
cmd = New OleDbCommand(sql, con)
'OPEN CON, EXECUTE, UPDATE, CLOSE
Try
con.Open()
adapter = New OleDbDataAdapter(cmd)
adapter.UpdateCommand = con.CreateCommand()
adapter.UpdateCommand.CommandText = sql
If (adapter.UpdateCommand.ExecuteNonQuery() > 0) Then
MsgBox("Successfully Updated")
End If
con.Close()
Retrieve()
ClearBox()
Catch ex As Exception
MsgBox(ex.Message)
con.Close()
End Try
End Sub
Private Sub Retrieve()
ListView1.Items.Clear()
'SQL STM
Dim sql As String = "SELECT * FROM Table1 "
cmd = New OleDbCommand(sql, con)
'OPEN CON, RETRIEVE, FILL LISTVIEW
Try
con.Open()
adapter = New OleDbDataAdapter(cmd)
adapter.Fill(dt)
'LOOP THROUGH DT
For Each row In dt.Rows
Populate(row(0), row(1)) 'Index of database row
Next
'CLEAR DATATABLE
dt.Rows.Clear()
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
con.Close()
End Try
End Sub
Private Sub Populate(lname As String, aamount As String)
'ROW ARRAY
Dim row As String() = New String() {lname, aamount}
Dim item As ListViewItem = New ListViewItem(row)
'ADD TO ROWS COLLECTION
ListView1.Items.Add(item)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Retrieve()
End Sub
Private Sub ListView1_MouseClick(sender As Object, e As MouseEventArgs) Handles ListView1.MouseClick
Dim llname As String = ListView1.SelectedItems(0).SubItems(0).Text
Dim amounts As String = ListView1.SelectedItems(0).SubItems(1).Text
TextBox1.Text = llname
TextBox2.Text = amounts
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim amounts As String = ListView1.SelectedItems(0).SubItems(0).Text
UpdateLV(amounts)
End Sub
Private Sub ClearBox()
TextBox1.Text = ""
TextBox2.Text = ""
End Sub
End Class
Mathematical operation should not be done using strings. This is a real basic principle that many VB.NET programmers don't think enough thanks to the forgiveness allowed by Option Strict Off in the VB.NET project settings.
If you are just starting a new project in VB.NET don't use this setting but switch it ASAP to On. This will give you an halt when you try to use strings as they were numbers and force you to do the appropriate conversion and checking on the values provided.
So your code that updates the amount rewritten
Private Sub UpdateLV(lname As String)
' Get the amount as a number (decimal for currency is the best)
Dim addAmt As Decimal
if Not decimal.TryParse(textbox2.Text, addAmt) Then
MessageBox.Show("Insert a valid amount please")
return
End If
' Sanity check
if addAmt <= 0 Then
MessageBox.Show("Amount should be > 0")
return
End If
'Updates last name and amount entered into the database
Dim sql As String = "UPDATE Table1 SET LastName=#name
,Amount=Amount+#amt
WHERE LastName=#oldname"
cmd = New OleDbCommand(sql, con)
Try
con.Open()
' Using an adapter here is wrong. You use directly the command
cmd.Parameters.Add("#name", OleDbType.VarWChar).Value = textBox1.Text
cmd.Parameters.Add("#amt", OleDbType.Decimal).Value = addAmt
cmd.Parameters.Add("#oldname", OleDbType.VarWChar).Value = lName
If (cmd.ExecuteNonQuery() > 0) Then
MsgBox("Successfully Updated")
End If
con.Close()
Retrieve()
ClearBox()
Catch ex As Exception
MsgBox(ex.Message)
con.Close()
End Try
End Sub
Something else is not clear in your code. What is the purpose of changing also the LastName here? Finally do not keep a global connection object. Instead create it when you need it and destroy it afterward with Using statement. It will be better for your memory footprint and for your database

ListBox index changed shows wrong value from SQLite database

I am coding a VB.NET program, which uses SQLite as a database.
My problem is when the form is loading it is displaying all values from a particular column (questions in my case) from the database to the ListBox. Then if the user clicks on any item (ListBox index change), the corresponding value from the database (answer) displays in a RichTextBox. This works as expected.
When the user types something in a TextBox and clicks the search Button, it is expected to show the questions from the database according to TextBox.Text as a tag column in the database to the same ListBox. This also works fine.
The problem begins when the ListBox index changes now. If the search result is only one item in the ListBox, the index will be zero and the RichTextBox shows the first item of the database insted of the corresponding value of the ListBox item.
My code is here:
Sub showData()'''this shows questions when form loads
connect()
Dim da As New SQLiteDataAdapter("select * from elect", connection)
'Dim dt As New DataTable
Dim ds As New DataSet
da.Fill(ds, "elect")
Dim mySelectQuery As String = "select * from elect"
Dim sqConnection As New SQLiteConnection(connection)
Dim sqCommand As New SQLiteCommand(mySelectQuery, sqConnection)
'sqConnection.Open()
Try
Dim sqReader As SQLiteDataReader = sqCommand.ExecuteReader()
' Always call Read before accessing data.
Do While sqReader.Read()
Dim sName = sqReader.Item("question")
ListBox1.Items.Add(sName)
Loop
' always call Close when done reading.
sqReader.Close()
' Close the connection when done with it.
Finally
connection.Close()
End Try
End Sub
Public Sub NavigateRecords()
page1.Clear()''page is rich text box
connect()
Dim da As New SQLiteDataAdapter("select * from elect", connection)
'Dim dt As New DataTable
Dim ds As New DataSet
da.Fill(ds, "elect")
Dim mySelectQuery As String
mySelectQuery = "select * from elect"
Dim sqConnection As New SQLiteConnection(connection)
Dim sqCommand As New SQLiteCommand(mySelectQuery, sqConnection)
Dim num As Integer = Me.inc = Conversions.ToInteger(ListBox1.SelectedIndices.ToString)
MsgBox(num)
Me.inc = Conversions.ToInteger(ListBox1.SelectedIndex.ToString)
If (Me.inc > -1) Then
Dim ans As String = Conversions.ToString(ds.Tables.Item("elect").Rows.Item(Me.inc).Item(2))
page1.Text = (ans)
End If
End Sub
Private Sub search()
connect()
Dim da As New SQLiteDataAdapter("select * from elect", connection)
'Dim dt As New DataTable
Dim ds As New DataSet
da.Fill(ds, "elect")
Dim mySelectQuery As String = ("select * from elect WHERE tag like'%" & txtSearch.Text & "%' ")
Dim sqConnection As New SQLiteConnection(connection)
Dim sqCommand As New SQLiteCommand(mySelectQuery, sqConnection)
Try
Dim sqReader As SQLiteDataReader = sqCommand.ExecuteReader()
' Always call Read before accessing data.
Do While sqReader.Read()
Dim sName = sqReader.Item("question")
ListBox1.Items.Add(sName)
Loop
If ListBox1.Items.Count = 0 Then
MsgBox("Nothing Found ")
showData()
End If
' always call Close when done reading.
sqReader.Close()
' Close the connection when done with it.
Finally
connection.Close()
End Try
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
page1.Visible = True
ListBox1.Visible = False
Label1.Visible = False
NavigateRecords()
End Sub

VB.NET-A way to insert rows into datagrid or datatable

Hi once again am stuck in middle where i need some pointer.... I need a way fill the datagrid in a for loop...
Dim rs As SqlCommand
Dim dt As New DataTable
For Each line As String In RichTextBox1.Lines
query = "myquery '" & RichTextBox1.Lines(i).ToString & "'"
rs = New SqlCommand(query, Module1.dtsrv_conn)
dt.load(rs.Executereader)
If i < 1 Then
DataGridView1.DataSource = dt
Else
datagridview1.rows.Add(rs.ExecuteReader)
End If
i = i + 1
Next
many lines of text will be entered in RichTextBox and each line need to be compared with values in database and the resulted table need to be shown in datagrid... I tried adding the newly queried row to datagrid directly but it throws exception so i tried to add new row to datatable and load the datagrid later but i cant find a way....
If I understand your question which isn't very clear, the user is entering values that you want to query against rows in your database and if they exist, display some corresponding data or message.
It sounds like what you want to do is bind your datagrid to a datasource, in my example an in-memory datatable, then intercept the data binding via DataGridView1.CellFormatting to compare/modify your data accordingly.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sqlConnection As SqlConnection
Dim sqlConnectionString As String = "YourConnectionString"
Dim sqlDataAdapter As SqlDataAdapter
Dim dataTable As New DataTable
Dim sqlCommand As SqlCommand
Dim sqlString As String
Try
sqlString = "SELECT * FROM YourTable" 'if user input values are filters, loop through and append them in WHERE clause
sqlConnection = New SqlConnection(sqlConnectionString)
sqlCommand = New SqlCommand(sqlString, sqlConnection)
sqlConnection.Open()
sqlDataAdapter = New SqlDataAdapter(sqlCommand)
sqlDataAdapter.Fill(dataTable)
sqlConnection.Close()
DataGridView1.DataSource = dataTable
Catch ex As Exception
'Handle error
End Try
End Sub
Private Sub DataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
If Me.DataGridView1.Columns(e.ColumnIndex).Name = "YourColumnNameToCompare" Then
If e.Value IsNot Nothing Then
'do your comparison to user input text here and if necassary change the value like so..
For Each line In RichTextBox1.Lines
If line = e.Value Then
e.Value = "Value modified"
Exit For
End If
Next
e.FormattingApplied = True
End If
End If
End Sub

Showing all fields in listbox from database, vb.net

I'm trying to make a list box to show all the fields of a particular table in an Access database. I have a few tables, and the idea would be to have each table loaded by a different button (and the items in the box cleared). One trick is that tables aren't all the same size. How do I get all the fields to show up for each table. What I have now is only showing one field:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;data source='C:\dummy_data.accdb';"
Dim conn As New OleDbConnection(connString)
Dim sql As String = "SELECT * FROM Customers"
Dim cmd As New OleDbCommand(sql, conn)
conn.Open()
Dim reader As OleDbDataReader = cmd.ExecuteReader()
ClientList.Items.Clear()
While reader.Read()
ClientList.Items.Add(reader(0).ToString())
End While
reader.Close()
conn.Close()
End Sub
If you are not averse to using a DataGridView instead of a ListView, you could do it this way:
Dim connString As String = "Provider=Microsoft.Jet.OLEDB.4.0;data source='PathToMyDatabase';"
Dim sql As String = "SELECT * FROM Tメイン;"
Dim dt As DataTable
With New OleDbDataAdapter(sql, connString)
Dim ds As New DataSet()
.Fill(ds)
dt = ds.Tables(0)
End With
Me.DataGridView1.DataSource = dt
I do not have 'ACE.OLEDB' on my computer, so had to use the JET provider instead, but it should work the same way.
I should add that you can use this method to retrieve the data from the DB, but there is no easy way as far as I understand to bind a DataTable to a ListView (see this MSDN question for example) and you would have to loop through the columns in your DataTable first and add the column headers to your ListView and then loop through the rows and add the data.
UPDATE:
To answer your questiona s to how to export data from the DataGridView I remembered that I wrote code to do that a little while back.
Private Function ExportToExcelFile(ByVal FileName As String) As Boolean
With New Excel.Application
With .Workbooks.Add()
For Each sheet As Worksheet In .Worksheets
If sheet.Index > 1 Then
Call sheet.Delete()
End If
Next
With CType(.Worksheets(1), Worksheet).Range("A1")
For Each column As DataGridViewColumn In Me.dgvData.Columns
.Offset(0, column.Index).Value = column.HeaderText
For Each row As DataGridViewRow In Me.dgvData.Rows
.Offset(row.Index + 1, column.Index).Value = row.Cells(column.Index).Value
Next
Next
End With
Call .SaveAs(FileName)
End With
Call .Quit()
End With
End Function
I hope this will help to get you started.
Using a Listview control, the following code should do the trick. For simplicity I defined only 4 customer fields - you will need to define them according to your table field defintions:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ClientList.View = View.Details
ClientList.FullRowSelect = True
ClientList.Columns.Add("ID", 120)
ClientList.Columns.Add("Name", 120)
ClientList.Columns.Add("Address", 140)
ClientList.Columns.Add("Email", 100)
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;data source=C:\dummy_data.accdb;"
ClientList.Items.Clear()
Using conn As New Data.OleDb.OleDbConnection(connString)
conn.Open()
Dim sql As String = "SELECT * FROM Customers"
Using cmd As New Data.OleDb.OleDbCommand(sql, conn)
Dim lvi As ListViewItem
Using oRDR As Data.OleDb.OleDbDataReader = cmd.ExecuteReader
While oRDR.Read()
lvi = ClientList.Items.Add(oRDR.GetValue(0).ToString)
For i = 1 To oRDR.FieldCount - 1
lvi.SubItems.Add(oRDR.GetValue(i).ToString)
Next
End While
End Using
End Using
conn.Close()
End Using
End Sub