Add Items to datatale per column instead of per row - vb.net

Half a day of searching made at least my data readable in a datagrid in a wpf app.
My problem is (or what in think is my problem) would be the adding of data in the columns I created.
My source of data is from a dictionary of string, list(of string) with my dictionary key as the header and the List as it's items, also the dictionary and it's content has no fixed length.
And to display my data I used the combination of DataTable and DataGrid
Here's my snippet
Dim files As New Dictionary(Of String, List(Of String))
Dim dt As New DataTable
For Each item As KeyValuePair(Of String, List(Of String)) In files
dt.Columns.Add(item.Key)
For Each file As String In item.Value
Dim dr As DataRow = dt.NewRow
dr(dt.Columns(item.Key).Ordinal) = file
dt.Rows.Add(dr)
Next
Next
DGrid.ItemsSource = dt.AsDataView
It works(somewhat), but as you all have guessed all the succeeding displayed column items after the last one starts where it ended last(looks like a stair).
so the question is do I have to change the way I store my data(dictionary) or I am missing something and this can work as there is a way to add data per column instead of rows?
UPDATE
It's not pretty and I know there is a better solution out there.
What I did first was to just render/instantiate the table and it's content
Dim dt As New DataTable
For Each item As KeyValuePair(Of String, List(Of String)) In files
dt.Columns.Add(item.Key)
For Each file As String In item.Value
Dim dr As DataRow = dt.NewRow
dr(item.Key) = Nothing
dt.Rows.Add(dr)
Next
Next
Then edit it's content:
For Each item As KeyValuePair(Of String, List(Of String)) In files
For file_index As Integer = 0 To item.Value.Count - 1
dt.Rows(file_index)(item.Key) = item.Value(file_index)
Next
Next
This is a bad solution but it works. Is there a better way?

you need to reuse existing rows for this. And add new one only when you have more items then rows.
Dim Files As New Dictionary(Of String, List(Of String))
Dim T As New DataTable, R As DataRow
For Each Pair As KeyValuePair(Of String, List(Of String)) In Files
T.Columns.Add(Pair.Key)
For i As Integer = 0 To Pair.Value.Count - 1
If i < T.Rows.Count Then
R = T.Rows(i)
Else
R = T.NewRow()
T.Rows.Add(R)
End If
R(Pair.Key) = Pair.Value(i)
Next
Next

Related

Datagridview to report viewer using parameter VB.net

I try to copy all columns in my datagridview (DGView7) to my report viewer.
I used this code, but it didn't work
Dim myAL As New ArrayList()
Dim row As List(Of String)
For i As Integer = 0 To Basicfor.DGView7.RowCount() - 1
row = New List(Of String)
For j As Integer = 0 To Basicfor.DGView7.ColumnCount() - 1
row.Add(Basicfor.DGView7.Rows(i).Cells(j).ToString)
Next j
myAL.Add(row)
Next i
Dim Params(0) As ReportParameter
Params(0) = New ReportParameter("Ref", CType(myAL.ToArray(GetType(String)), String()))
Me.ReportViewer1.RefreshReport()
It shows an error. I tried to change to this code string() -> Single(), but single is not defined
Params(0) = New ReportParameter("Ref", CType(myAL.ToArray(GetType(String)), Single()))
Can anyone resolve this? Thanks in advance
You're calling
Params(0) = New ReportParameter("Ref", CType(myAL.ToArray(GetType(String)), String()))
And wanting to pass in an array of strings(). That's my assumption at least
However you're passing an array of list of strings.
Try
Dim myStrings = myAL.Cast(Of List(Of String)).SelectMany(Function(r) r).ToArray()

DataGridViewRow numerically order

How can I sort my DataGridViewRow to numerically order?
My code:
Dim Name As New List(Of String)
Dim Price As New List(Of Integer)
For x = 0 To Math.Max(Name.Count, Price.Count)
If x < Name.Count AndAlso x < Price.Count Then
Dim row As String() = New String() {Name(x), Price(x)}
DataGridView1.Rows.Add(row)
End If
Next
Price row example:
1345
1533
4555
6744
You've got them as two separate lists... I'll take a leap and make an assumption that you need to keep the source data in that format... Having them in two lists you've currently got a dependency on their positions. So use a sortable collection to pair them up
e.g.
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Imports System.Data.Linq
Dim Name As New List(Of String)
Dim Price As New List(Of Integer)
Dim Sortable As New List(Of KeyValuePair(Of String, Integer))
'Your checking that you weren't going past the last pair was an odd one
For x = 0 To Math.Min(Name.Count, Price.Count) - 1
'Pair them up so you can sort them together not having to try to match between two lists
Sortable.Add(New KeyValuePair(Name(x), Price(x)))
Next
'now you can sort it
Sortable = (From item In Sortable Order By Convert.ToInt32(item.Key) Select item).ToList()
'now stick it in the grid view, You might be able to base the grid view on the
'DataGridView1.DataSource = Sortable
'DataGridView1.DataBind()
'depends on how it is defined/configured,
'but for now let us return to your original code....
For Each kvp As KeyValuePair(Of String, Integer) In Sortable
Dim row As String() = New String() {kvp.Key, kvp.Value.ToString("$0.00")}
DataGridView1.Rows.Add(row)
Next

List of lists in vb.net

I am trying to create lists, that are then inserted into another list.
For some reason the latter list gets overwritten each time I try to add new list item to it.
For the code below, first I want to add items to Temp list and after certain conditions have been met, add the Temp list as an item to the Comp list. After that, the cycle repeats, new and different Temp list should be created and the added to the Comp list as next item. So each item in Comp list should be different.
But in the end I get a Comp list that is filled with Temp lists that are all identical to the last Temp list added.
What am I doing wrong?
Function UniqueValueList2(ByVal InputObject As List(Of Object)) As List(Of List(Of Object))
Dim vc As Integer = InputObject.Count
Dim i As Integer = 1
Dim Temp As New List(Of Object)
Dim Comp As New List(Of List(Of Object))
Dim CurrentObj As String
Dim PrevObj As String
Temp.Add(InputObject(0))
Do While i < vc
CurrentObj = InputObject(i).fieldName
PrevObj = InputObject(i-1).fieldName
If CurrentObj = PrevObj Then
Temp.Add(InputObject(i))
Else
Comp.Add(Temp)
Temp.Clear()
Temp.Add(InputObject(i))
End If
i = i + 1
Loop
Comp.Add(Temp)
UniqueValueList2 = Comp
End Function
Temp is holding the same reference. so making changes on it will change it.And you add and modify the same List
Comp.Add(Temp) 'the same Temp List
Temp.Clear() 'You will clear the same List
Temp.Add(InputObject(i))
So How you should do :
Comp.Add(Temp) 'we add old List
Temp=New List(Of Object) 'Temp now holds reference to new List
Temp.Add(InputObject(i))
This will work:
Comp.Add(Temp.ToList())
Temp.Clear()
Temp.Add(InputObject(i))

Compare two lists 2D and determine differences VB.NET

I declare my 2D lists:
Dim _invoiceitems As New List(Of List(Of String))
Dim _dbitems As New List(Of List(Of String))
Each List is filled like this:
Example Code To fill:
_invoiceitems.Add(New List(Of String))
_invoiceitems(0).Add("Code #")
_invoiceitems(0).Add("Quantity")
Well, now i need a third list called (_changesitems) Note that this result with the differences:
be the result of subtraction of quantities if this is found (dbitems - invoiceitems).
How i can get this result?
The following code will generate the results you are looking for:
Private Function getChangesItems(ByVal invoiceItems As Dictionary(Of String, Integer), ByVal dbItems As Dictionary(Of String, Integer)) As Dictionary(Of String, Integer)
Dim changesItems As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()
Dim allCodes As List(Of String) = New List(Of String)()
allCodes.AddRange(invoiceItems.Keys)
allCodes.AddRange(dbItems.Keys)
For Each code As String In allCodes
If Not changesItems.ContainsKey(code) Then
Dim dbQuantity As Integer = 0
Dim invoiceQuantity As Integer = 0
If dbItems.ContainsKey(code) Then
dbQuantity = dbItems(code)
End If
If invoiceItems.ContainsKey(code) Then
invoiceQuantity = invoiceItems(code)
End If
Dim changeQuantity As Integer = dbQuantity - invoiceQuantity
If changeQuantity <> 0 Then
changesItems.Add(code, changeQuantity)
End If
End If
Next
Return changesItems
End Function
I used dictionaries instead of lists as was recommended by others. As long as your data only contains a code and a value, the dictionary is a better fit. If you have more columns, I would suggest creating a class that contains properties for each column and then make a list of that class type, rather than a simple 2D list of strings. Doing so would be more type-safe and easier to read.

vb.net - multi-dimension array list

I've managed to make some single dimension array lists but I can't figure out a multi dimension arraylist.
Here's what I'm trying to do:
I have a database (mdb) with 5 columns that I want each row to be in an array list.
In PHP what I'd typically do is:
$array[$field1] = array($field2,$field3,$field4,$field5);
How I do the same in vb.net so anytime I need to fetch an item for a specific for the row1 I could call it?
For a single dimension I could do the following, but I can't figure out how to add more fields to a single array row:
Dim tmpArrayX As New ArrayList
tmpArrayX.Add(field(0))
tmpArrayX.Add(field(1))
etc...
If you want to use ArrayList, just make it's items contain other ArrayLists.
Or you could use normal arrays as:
Dim multiArray(2, 2) As String
multiArray(0, 0) = "item1InRow1"
multiArray(0, 1) = "item2InRow1"
multiArray(1, 0) = "item1InRow2"
multiArray(1, 1) = "item2InRow2"
Though my personal preference would be to use List as:
Dim multiList As New List(Of List(Of String))
multiList.Add(New List(Of String))
multiList.Add(New List(Of String))
multiList(0).Add("item1InRow1")
multiList(0).Add("item2InRow1")
multiList(1).Add("item1InRow2")
multiList(1).Add("item2InRow2")
Edit: How to find row:
Dim listIWant As List(Of String) = Nothing
For Each l As List(Of String) In multiList
If l.Contains("item1InRow2") Then
listIWant = l
Exit For
End If
Next
' This allows adding rows on the fly....Tested and it works!
Dim multiList As New List(Of List(Of String))
Dim ListRow As Integer = 0
For each record in some_source
dim Country as string = record.country 'from some source
dim Date as Date = record.Date 'from some source
dim Venue as string = record.Venue 'from some source
dim Attendance as string = record.Attendance 'from some source
multiList.Add(New List(Of String))
multiList(ListRow).Add(Country)
multiList(ListRow).Add(Date)
multiList(ListRow).Add(Venue)
multiList(ListRow).Add(Rating)
multiList(ListRow).Add(Attendance)
ListRow = ListRow + 1
next