Formatting DataTable columns when adding data by rows - vb.net

I am aware of and have used column formatting for a DataTable("dt") when adding columns, as in, e.g.:
dt.Columns.Add("myColName", GetType(Double))
or
DataColumn column;
column = New DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = "MyColName";
dt.Columns.Add(column);
However, I am adding data from a double array, x(i,j), to dt, but adding by row. How would I specify GetType(Double) to ensure the columns end up as Double?
Dim workrow As DataRow
For i = 0 To MyRows - 1
workrow = dt.NewRow()
For j = 0 To MyCols - 1
workrow(j) = x(i, j)
Next
dt.Rows.Add(workrow)
Next

This was resolved by specifying column formats before data were added to the dt.
For j = 0 To dt.Columns.Count - 1
dt.Columns(j).DataType = System.Type.GetType("System.Double")
Next
Although the array was a Double, and there would be no issues, this is nevertheless a way to format columns when data are added to dt by rows (not columns).

Related

For on a dataset, get column value

I am updating some old software in VB, and fixed this, but I'd like to know how to make the second option work.
The problem is in the second For loop in the code below. I'm not sure how to get a column of a specific row.
I have not worked much with VB and not used it for 10 years or so, so bare the question.
Dim i As Integer = 0
Dim dsSettings As New DataSet
dsSettings.Locale = System.Globalization.CultureInfo.InvariantCulture
If System.IO.File.Exists("QuaData\Settings.xml") Then
dsSettings.ReadXml("QuaData\Settings.xml")
ReDim Preserve IdPrefixes(dsSettings.Tables(0).Rows.Count - 1)
For Each Row As DataRow In dsSettings.Tables(0).Rows
For Each Coll As DataColumn In dsSettings.Tables(0).Columns
IdPrefixes(i) = Row("IdPrefix").ToString()
Next
i = i + 1
Next
' Here I cannot see how I can get a column of a row -
' like Rows(1)
' I cannot select Rows(index)(column name)
For i = 0 To dsSettings.Tables(0).Rows.Count - 1
IdPrefixes(i) = dsSettings.Tables(0).Rows(i)("IdPrefix").ToString()
Next
End If

Mass data export from SQL Server to Excel in VB

I have some code that works for smaller data sets. I get an 'out of memory' error with the huge data sets I use though (800k rows, 25 columns). I was trying to figure out a way to change this to mass export column by column, or maybe split up sets of rows, instead of the whole thing at once.
Clearly it can't handle that much data. I couldn't figure out how to separate it out some. Any ideas? Thanks!
For Each dt As System.Data.DataTable In ds.Tables
' Copy the DataTable to an object array
Dim rawData(dt.Rows.Count, dt.Columns.Count - 1) As Object
' Copy the column names to the first row of the object array
For col = 0 To dt.Columns.Count - 1
rawData(0, col) = dt.Columns(col).ColumnName
Next
' Copy the values to the object array
For col = 0 To dt.Columns.Count - 1
For row = 0 To dt.Rows.Count - 1
rawData(row + 1, col) = dt.Rows(row).ItemArray(col)
Next
Next
' Calculate the final column letter
Dim finalColLetter As String = String.Empty
Dim colCharset As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim colCharsetLen As Integer = colCharset.Length
If dt.Columns.Count > colCharsetLen Then
finalColLetter = colCharset.Substring( _
(dt.Columns.Count - 1) \ colCharsetLen - 1, 1)
End If
finalColLetter += colCharset.Substring( _
(dt.Columns.Count - 1) Mod colCharsetLen, 1)
' Fast data export to Excel
Dim excelRange As String = String.Format("A1:{0}{1}", finalColLetter, dt.Rows.Count + 1)
excelSheet.Range(excelRange, Type.Missing).Value2 = rawData
excelSheet = Nothing
Next
Is there other code that manipulates the excel spreadsheet? If not, it would probably be faster to just write this out to a plane text file in CSV format. Excel will open the CSV and present it like a normal spreadsheet.

Adding two column values to listbox in vb.net

I have a table named users which has the following columns in it
User_id,user_name,user_pwd,First_Name,Middle_Name,Last_Name and user_type.
I have dataset named dst and created a table called user in the dataset. Now I want to populate listbox with user_Name, First_Name, Last_name of each and every row in the table user.
I am able to add one column value at a time but not getting how to add multiple column values of each row to listbox
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(row("User_Name"))
Next
Above code works perfectly but I also want to add First_name as well as last_name to the list box at the same time.
Use same approach as you have, but put all values you want in one string.
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
Dim sItemTemp as String
sItemTemp = String.Format("{0},{1},{2}", row("User_Name"), row("First_Name"), row("Last_Name"))
lstUsers.Items.Add(sItemTemp)
Next
String.Format() function will call .ToString() on all parameters.
In this case if row(ColumnName) is NULL value then .ToString() return just empty string
You have 2 choices:
Using the ListBox:
To use the ListBox, set the font to one that is fixed width like courier new (so that the columns line up), and add the items like this:
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(RPAD(row("User_Name"),16) & RPAD(row("First_Name"),16) & RPAD(row("Last_Name"),16))
Next
The RPAD function is defined like this:
Function RPAD(a As Object, LENGTH As Object) As String
Dim X As Object
X = Len(a)
If (X >= LENGTH) Then
RPAD = a : Exit Function
End If
RPAD = a & Space(LENGTH - X)
End Function
Adjust the LENGTH argument as desired in your case. Add one more for at least one space. This solution is less than ideal because you have to hard-code the column widths.
Use a DataGridView control instead of a ListBox. This is really the best option, and if you need, you can even have it behave like a ListBox by setting the option to select the full row and setting CellBorderStyle to SingleHorizontal. Define the columns in the designer, but no need to set the widths - the columns can auto-size, and I set that option in the code below. if you still prefer to set the widths, comment out the AutoSizeColumnsMode line.
The code to set up the grid and add the rows goes like this:
g.Rows.Clear() ' some of the below options are also cleared, so we set them again
g.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.AllCells
g.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal
g.SelectionMode = DataGridViewSelectionMode.FullRowSelect
g.AllowUserToAddRows = False
g.AllowUserToDeleteRows = False
g.AllowUserToOrderColumns = True
For Each row As DataRow In dt.Rows
g.Rows.Add(row("User_Name"), row("First_Name"), row("Last_Name"))
Next
You might solved your problem by now but other users like me might have issue with it.
Above answers given worked for me even but I found a same answer in a simple way according to what I want..
cmd = New SqlCommand("select User_Name, First_Name, Last_Name from User")
Dim dr As SqlDataReader = cmd.ExecuteReader(YourConnectionString)
If dr.HasRows Then
Do While dr.Read
lst.Items.Add(dr.Item(0).ToString & " " & dr.Item(1).ToString & " " & dr.Item(2).ToString)
Loop
End If
This worked for me, maybe wrong way but I found it simple :)
May I suggest you use a ListView control instead of Listbox?
If you make the switch, here's a sample subroutine you could use to fill it up with the data you said you want. Adapt it the way you like; there's much room for improvement but you get the general idea:
Public Sub FillUserListView(lstUsers As ListView, Dst As DataSet)
Dim columnsWanted As List(Of String) = New List(Of String)({"User_Name", "First_Name", "Last_Name"})
Dim dt As DataTable = Dst.Tables("user")
Dim columns As Integer = 0
Dim totalColumns = 0
Dim rows As Integer = dt.Rows.Count
'Set the column titles
For Each column As DataColumn In dt.Columns
If columnsWanted.Contains(column.ColumnName) Then
lstUsers.Columns.Add(column.ColumnName)
columns = columns + 1
End If
totalColumns = totalColumns + 1
Next
Dim rowObjects(columns - 1) As ListViewItem
Dim actualColumn As Integer = 0
'Load up the rows of actual data into the ListView
For row = 0 To rows - 1
For column = 0 To totalColumns - 1
If columnsWanted.Contains(dt.Columns(column).ColumnName) Then
If actualColumn = 0 Then
rowObjects(row) = New ListViewItem()
rowObjects(row).SubItems(actualColumn).Text = dt.Rows(row).Item(actualColumn)
Else
rowObjects(row).SubItems.Add(dt.Rows(row).Item(actualColumn))
End If
lstUsers.Columns.Item(actualColumn).Width = -2 'Set auto-width
actualColumn = actualColumn + 1
End If
Next
lstUsers.Items.Add(rowObjects(row))
Next
lstUsers.View = View.Details 'Causes each item to appear on a separate line arranged in columns
End Sub

Split datatable into n datatables

I need to dynamically split a datatable into multiple datatables and the number of subsequent datatables will vary. The end user will enter a value and this will determine the number of datatables that will be derived from the original. For example: the user enters 10, the original dt has 20 rows. There will be 10 dt's with 2 rows each created. However, if the original dt has 11 rows, there would be 9 dt's with 1 row and 1 dt with 2 rows created. How can I accomplish this in vb.net without hardcoding a bunch if rules? I have read through and tried the post below but it still does not get me there.
Split a collection into `n` parts with LINQ?
You can use LINQ's GroupBy:
Dim tbl1 = New DataTable
tbl1.Columns.Add("ID", GetType(Int32))
tbl1.Columns.Add("Text", GetType(String))
For rowIndex As Int32 = 1 To 11
tbl1.Rows.Add(rowIndex, "Row " & rowIndex)
Next
Dim tableCount = 10 ' what the user entered '
Dim divisor = tbl1.Rows.Count / tableCount ' needed to identify each group '
Dim tables = tbl1.AsEnumerable().
Select(Function(r, i) New With {.Row = r, .Index = i}).
GroupBy(Function(x) Math.Floor(x.Index / divisor)).
Select(Function(g) g.Select(Function(x) x.Row).CopyToDataTable())

Sorting a List based on an ArrayList within a custom Object

I am using a list to keep track of a number of custom Row objects as follows:
Public Rows As List(Of Row)()
Row has 2 properties, Key (a String) and Cells (an ArrayList).
I need to be able to sort each Row within Rows based on a developer defined index of the Cells ArrayList.
So for example based on the following Rows
Row1.Cells = ("b", "12")
Row2.Cells = ("a", "23")
Rows.Sort(0) would result in Row2 being first in the Rows list. What would be the best way of going about implementing this?
Thanks
If you implement IComparable on your Row object, you can define a custom comparison process to be able to do the sorting that you desire.
Here is an intro article to get you started.
Its similar to a DatRow with it's Columns, so you can alternative(to the IComparable solution) use the sort-ability of a DataView:
Consider creating a DataTabale on the fly with its columns as your cells.
For example:
Dim rows As New List(Of Row)
Dim row = New Row("Row 1")
Dim cell1 As New Row.Cell("b")
Dim cell2 As New Row.Cell("12")
row.Cells.Add(cell1)
row.Cells.Add(cell2)
rows.Add(row)
row = New Row("Row 2")
cell1 = New Row.Cell("a")
cell2 = New Row.Cell("23")
row.Cells.Add(cell1)
row.Cells.Add(cell2)
rows.Add(row)
Dim tbl As New DataTable()
''#are the cell count in every row equal? Otherwise you can calculate the max-count
Dim cellCount As Int32 = 2 ''#for example
For i As Int32 = 0 To cellCount - 1
Dim newCol As New DataColumn("Column " & i + 1)
tbl.Columns.Add(newCol)
Next
For rowIndex As Int32 = 0 To rows.Count - 1
row = rows(rowIndex)
Dim newRow As DataRow = tbl.NewRow
For cellIndex As Int32 = 0 To row.Cells.Count - 1
Dim cell As Row.Cell = row.Cells(cellIndex)
newRow(cellIndex) = cell.value
Next
tbl.Rows.Add(newRow)
Next
Dim view As New DataView(tbl)
view.Sort = "Column 1"
''#you can use the view as datasource or other purposes