datarow variable assign to dataset's table newrow - vb.net

I'm trying to define a datarow to hold values and then add it to data set
indgv: datagridview with values in it
dsdetails: a dataset with a table named details
If indgv.Rows.Count > 0 Then
Dim dr As DataRow
dr = dsdetails.Tables("details").NewRow
For Each row As DataGridViewRow In indgv.Rows
dr("mat") = row.Cells("icode").Value
dr("dateoftrans") = Me.DateTimePicker1.Value
dr("numoftrans") = transnum.Text
dr("type") = 1
dr("doc") = doctyp.SelectedValue
dr("amount") = row.Cells("iamo").Value
dsdetails.Tables("details").Rows.Add(dr)
Next
adpdetails.Update(dsdetails, "details")
End If
running this causes the following error
Object reference not set to an instance of an object.
how to rephrase the declaration with 'New' to avoid the problen
BTW : when using new as the following
Dim dr As New DataRow = dsdetails.Tables("details").NewRow
it shows design time error
Type 'dsdetails.Tables' is not defined.

Try this code:
If indgv.Rows.Count > 0 Then
Dim tbl As DataTable = dsdetails.Tables("details")
Dim dr As DataRow
For Each row As DataGridViewRow In indgv.Rows
dr = tbl.NewRow 'Create a new row inside the loop!
dr("mat") = row.Cells("icode").Value
dr("dateoftrans") = Me.DateTimePicker1.Value
dr("numoftrans") = transnum.Text
dr("type") = 1
dr("doc") = doctyp.SelectedValue
dr("amount") = row.Cells("iamo").Value
tbl.Rows.Add(dr)
Next
adpdetails.Update(tbl)
End If

If all you need is to copy rows from one table to another, DataTable class has a Copy method you may want to use. It works like this:
Dim dtCopy As New DataTable()
dtCopy = dt.Copy()
If you have a datagridview control bound to a table, you could also use this form:
Dim dtCopy As New DataTable()
dtCopy = DirectCast(dataGridViewX1.DataSource, DataTable).Copy()
The Copy method will copy the datatable structure and the data.
If you want to copy the structure only without the data you could use Clone method.

Related

Temp table has no information but original table does

I have a datatable that has all the data in it but when my VB.net program runs it and I make a temptable, the temptable has no info. WHat am I doing wrong?
Public Sub HTSCode()
Dim TempTable As New DataTable
Dim DV As DataView
TempTable = RatesDataSet.HTS
DV = TempTable.DefaultView
DV.Sort = "HTS Code NA"
TempTable = DV.ToTable
For Each Row As DataRow In TempTable.Rows
'doesnt get to this point cause there are no rows.
Next
End Sub
I am attaching pictures 1 of my datatable before I run it so there is info there and the second is when running it shows it empty. I am now even getting the data directly from the table and not a copy of it or temptable anymore.
The answer is your problem lies elsewhere. Using this sample to simulate your code, I can't ever get an object with no rows
Public Class ds
Public ReadOnly Property HTS As DataTable
Get
Dim dt As New DataTable()
dt.Columns.AddRange(
{
New DataColumn("HTS Code", GetType(Integer)),
New DataColumn("HTS Code NA", GetType(Integer))
})
For i = 0 To 4
Dim row = dt.NewRow()
row("HTS Code") = i
row("HTS Code NA") = 10 - i
dt.Rows.Add(row)
Next
Return dt
End Get
End Property
End Class
Dim RatesDataSet = New ds
Dim TempTable As DataTable
Dim DV As DataView
TempTable = RatesDataSet.HTS
Console.WriteLine(TempTable.Rows.Count)
DV = TempTable.DefaultView
Console.WriteLine(DV.Count)
DV.Sort = "HTS Code NA"
Console.WriteLine(DV.Count)
TempTable = DV.ToTable
Console.WriteLine(TempTable.Rows.Count)
Console.WriteLine("HTS Code NA:")
For Each Row As DataRow In TempTable.Rows
Console.WriteLine(Row("HTS Code NA"))
Next
Output
5
5
5
5
HTS Code NA:
6
7
8
9
10
I think it was my dumbness I never linked the table to that form. As soon as I did that the table was filled and works. Sorry and thanks

value of type integer cannot be converted to datatable vn.net

i am trying to create tree view and some error i can not fix it
Sub CREATENODE()
Dim TRN As New TreeNode
Dim DT As New DataTable
DT.Clear()
DT = ACCOUNTTableAdapter.TREE_ACCOUNT()
For I As Integer = 0 To DT.Rows.Count - 1
If DT.Rows(I)(9).ToString() = "00000000-0000-0000-0000-000000000000" Then
TRN = New TreeNode(DT.Rows(I)(3).ToString() + " " + DT.Rows(I)(4).ToString())
TRN.Tag = DT.Rows(I)(1).ToString()
If DT.Rows(I)(7).ToString() <> "0" Then
TRN.ImageIndex = 0
TRN.SelectedImageIndex = 0
Else
TRN.ImageIndex = 1
TRN.SelectedImageIndex = 1
End If
TreeView1.Nodes.Add(TRN)
End If
Next
''For Each NODE As TreeNode In TreeView1.Nodes
'' CHELD(NODE)
'Next
End Sub
This is nonsense
Dim TRN As New TreeNode
Dim DT As New DataTable
DT.Clear()
DT = ACCOUNTTableAdapter.TREE_ACCOUNT()
You create a New TreeNode and then inside the loop you overwrite it with another New one. Just put the Dim inside the loop after the if.
Dim TRN = New TreeNode($"{row(3)} {row(4)}")
You create a brand new DataTable. Then you clear it when it can't possibly have anything in it. Then you throw it away and assign a different DataTable to it.
Just do
Dim DT = ACCOUNTTableAdapter.TREE_ACCOUNT()
I have simplified your code by using a For Each loop. Also, I used and interpolated string indicated by the $ preceding the string. Variables can be inserted in place surrounded by braces { }.
As far as the actual problem, you need to create an instance of your table adapter with the New keyword. Then call the appropriate method. A simple application will just use .GetData.
Private Sub CREATENODE()
Dim DT = (New ACCOUNTTableAdapter).TREE_ACCOUNT() 'See what intellisense offers. It may be just .GetData
For Each row As DataRow In DT.Rows
If row(9).ToString() = "00000000-0000-0000-0000-000000000000" Then
Dim TRN = New TreeNode($"{row(3)} {row(4)}")
TRN.Tag = row(1)
If row(7).ToString() <> "0" Then
TRN.ImageIndex = 0
TRN.SelectedImageIndex = 0
Else
TRN.ImageIndex = 1
TRN.SelectedImageIndex = 1
End If
TreeView1.Nodes.Add(TRN)
End If
Next
End Sub
Hint: Why not put the entire row in the Tag property. You will have access to all the fields by casting the Tag back to a DataRow.

letting user type and add value to an already bound combobox

I have one combobox in my app that gets populated with a dozen or so items from SQL SERVER. I am currently trying to allow user to be able to type in a new value into the combobox and save it to a table in SQL SERVER. I'm looking for something along the lines of a DropDownStyle of DropDown and DropDownList. Basically I'm hoping to let the user type in the combobox, however if the value is not there, i want to be able to give them an option of saving it (probably on lost focus). I'm wondering what would be a good way of doing something like that.
On lost focus should I basically go through each item that is currently in the drop down and check it against the value entered?
EDIT:
Sql="SELECT IDvalue, TextName from TblReference"
Dim objconn As New SqlConnection
objconn = New SqlConnection(conn)
objconn.Open()
Dim da As New SqlDataAdapter(sql, objconn)
Dim ds As New DataSet
da.Fill(ds, "Name")
If ds.Tables("Name").Rows.Count > 0 Then
Dim dr As DataRow = ds.Tables("Name ").NewRow
ds.Tables("Name").Rows.InsertAt(dr, 0)
With c
.DataSource = ds.Tables("Name")
.ValueMember = " IDvalue "
.DisplayMember = " TextName "
End With
End If
You are already adding a fake/blank row to a table, you can do the same thing for a new item.
' form level datatable var
Private cboeDT As DataTable
Initializing:
cboeDT = New DataTable
Dim sql = "SELECT Id, Descr FROM TABLENAME ORDER BY Descr"
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cboeDT.Load(cmd.ExecuteReader())
' probably always need this even
' when there are no table rows (???)
Dim dr = cboeDT.NewRow
dr("Id") = -1 ' need a way to identify it
dr("Descr") = ""
cboeDT.Rows.InsertAt(dr, 0)
End Using
End Using
cboeDT.DefaultView.Sort = "Descr ASC"
cboE.DataSource = cboeDT
cboE.DisplayMember = "Descr"
cboE.ValueMember = "Id"
Note Users tend to have a preference as to the order of these things. The simple creatures tend to prefer alphabetical over a DB Id they may never see. To accommodate them, the DefaultView is sorted so that any new rows added will display in the correct order.
Add new items in the Leave event (much like Steve's):
Private Sub cboE_Leave(sender ...
' if it is new, there will be no value
If cboE.SelectedValue Is Nothing Then
' alternatively, search for the text:
'Dim item = cboeDT.AsEnumerable().
' FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
' cboE.Text, True) = 0)
'If item Is Nothing Then
' ' its new...
Dim newid = AddNewItem(cboE.Text)
Dim dr = cboeDT.NewRow
dr("Id") = newid
dr("Descr") = cboE.Text
cboeDT.Rows.Add(dr)
' fiddling with the DS looses the selection,
' put it back
cboE.SelectedValue = newid
End If
End Sub
If you want to search by text:
Dim item = cboeDT.AsEnumerable().
FirstOrDefault(Function(q) String.Compare(q.Field(Of String)("Descr"),
cboE.Text, True) = 0)
If item Is Nothing Then
' its new...
...
Inserting will vary a little depending on the actual db. A key step though is to capture and return the ID of the new item since it is needed for the CBO:
Private Function AddNewItem(newItem As String) As Int32
Dim sql = "INSERT INTO MY_TABLE (Descr) VALUES (#v); SELECT LAST_INSERT_ID();"
Dim newId = -1
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(sql, dbcon)
dbcon.Open()
cmd.Parameters.Add("#v", MySqlDbType.String).Value = newItem
' MySql provides it in the command object
If cmd.ExecuteNonQuery() = 1 Then
newId = Convert.ToInt32(cmd.LastInsertedId)
End If
End Using
End Using
Return newId
End Function
As noted MySql provides the LastInsertedID as a command object property. In SQL SERVER, tack ...";SELECT LAST_INSERT_ID();" to the end of your SQL and then:
newId = Convert.ToInt32(cmd.ExecuteScalar())
This is not conceptually very different from Steve's answer, except it uses the DataTable you build rather than collections which makes it (very) slightly simpler.
The way I do this, is on window load I perform a new SQL query to get the list of values in the table, and load them into a combobox.
Then once focus is lost, it then checks what's currently typed into the combobox against the current values already loaded. If it doesn't exist, then it's not in SQL. Something like the following...
Dim found As Boolean = False
For i As Integer = 0 To comboBox.Items.Count - 1
Dim value As String = comboBox.Items(i).ToString()
If comboBox.Text = value Then
found = True
End If
Next
If found = False Then
'the item doesn't exist.. add it to SQL
Else
'the item exists.. no need to touch SQL
End If
First thing I would do is to build a simple class to hold your values through a List of this class
Public Class DataItem
Public Property IDValue As Integer
Public Property TextName as String
End Class
Now, instead of building an SqlDataAdapter and fill a dataset, work with an SqlDataReader and build a List(Of DataItem)
' Class global...
Dim allItems = new List(Of DataItem)()
Sql="SELECT IDvalue, TextName from TblReference"
' Using to avoid leaks on disposable objects
Using objconn As New SqlConnection(conn)
Using cmd As New SqlCommand(Sql, objconn)
objconn.Open()
Using reader = cmd.ExecuteReader()
While reader.Read()
Dim item = new DataItem() With { .IDValue = reader.GetInt32(0), .TextName = reader.GetString(1)}
allItems.Add(item)
End While
End Using
if allItems.Count > 0 Then
allItems.Insert(0, new DataItem() With {.IDValue = -1, .TextValue = ""}
Dim bs = new BindingList(Of DataItem)(allItems)
c.DataSource = bs
c.ValueMember = "IDvalue"
c.DisplayMember = "TextName"
End If
End Using
End Using
Now the code that you want to add to your Leave event for the combobox
Sub c_Leave(sender As Object, e As EventArgs) Handles c.Leave
If Not String.IsNullOrEmpty(c.Text) Then
Dim bs = DirectCast(c.DataSource, BindingList(Of DataItem))
if bs.FirstOrDefault(Function(x) x.TextName = c.Text) Is Nothing Then
Dim item = new DataItem() With { .IDValue = -1, .TextName = c.Text}
bs.Add(item)
' here add the code to insert in the database
End If
End If
End Sub

Insert headers of a datatable VB.NET

I need your help for my code vb
In fact, i created an new datatable and i want to copy the headers from another datatable
here is my code
Dim name(de.Tables(0).Columns.Count) As String
Dim p As Integer = 0
For Each column As DataColumn In de.Tables(0).Columns
name(p) = column.ColumnName
p += 1
Next
Dim m As Integer = 0
For m = 0 To de.Tables(0).Columns.Count - 1
dt.Columns(m).ColumnName = name(p)
Next
If you only want to "copy" the schema of a DataTable(so the columns and constraints) without it's content(DataRows) you can use DataTable.Clone:
Dim clonedTable As DataTable = originalTable.Clone()
If you also want to copy the DataRows you have to use DataTable.Copy.
Try this one
Dim dt As New DataTable()
Dim name(de.Tables(0).Columns.Count) As String
For Each column As DataColumn In de.Tables(0).Columns
dt.Columns.Add(New DataColumn(column.ColumnName))
Next

Adding row in DataTable

I'm doing a project in vb and I'm trying to add all the rows in dataTable name dt to a new dataTable name dtNew but i dont want duplicate rows to be added in dtNew instead adding the count if its duplicate. someone help me please.
here is a sample dataTable name dt as you can see apple is duplicate
here is my code.
Dim dtNew As DataTable = New DataTable '---> I Created new DataTable
'---> Created 3 columns
dtNew.Columns.Add("TYPE", Type.GetType("System.String"))
dtNew.Columns.Add("NAME", Type.GetType("System.String"))
dtNew.Columns.Add("COUNT", Type.GetType("System.Int32"))
For Each dtRow As DataRow In dt.Rows ' ---> loop all the rows in dt DataTable
Dim newRow As DataRow = dtNew.NewRow
newRow("TYPE") = dtRow("TYPE")
newRow("NAME") = dtRow("NAME")
newRow("COUNT") = dtRow("COUNT")
'check if dtNew DataTable has no row
If Not dtNew Is Nothing AndAlso dtNew.Rows.Count = 0 Then
'add new row
dtNew.Rows.Add(newRow)
Else
' I want to check first all the rows in dtNew DataTable
' if its existed, and if it's not then add new row
For Each dtNewRow As DataRow In dtNew.Rows
If ((dtNewRow("TYPE") = "VEGETABLE" OrElse _
dtNewRow("TYPE") = "FRUIT") And _
dtNewRow("NAME") <> newRow("NAME")) Then
'insert row
dtNew.Rows.InsertAt(newRow, dtNew.Rows.Count)
'error: Collection was modified; enumeration operation might not be executed.
End If
Next
End If
Next
For Each row As DataRow In dt.Rows
Dim type = CStr(row("Type"))
Dim name = CStr(row("Name"))
Dim existingRows = dtNew.Select(String.Format("Type = '{0}' AND Name = '{1}'",
type,
name))
If existingRows.Length = 0 Then
'No match so create a new row.
Dim newRow = dtNew.NewRow()
newRow("Type") = type
newRow("Name") = name
newRow("Count") = row("Count")
dtNew.Rows.Add(newRow)
Else
'Match found so update existing row.
Dim newRow = existingRows(0)
newRow("Count") = CInt(newRow("Count")) + CInt(row("Count"))
End If
Next
As the tables have the same schema, you could even simplify the If block to this:
dtNew.ImportRow(row)
That would only be a problem if row had a RowState other than Unchanged and you didn't want to import that too.