Datatable second row to first row - asp.net

In My Datatable iam getting 2 rows like
Name Age City
A 20 c
B 20 c
Now i need like second row shifted to First Row and vice versa
Name Age City
B 20 c
A 20 c
How can i do it.

If you want to swap two rows you can use following approach:
for (int i = 0; i < table.Rows.Count; i += 2)
{
object[] row1Items = table.Rows[i].ItemArray; // works because ItemArray creates a new object[]
table.Rows[i].ItemArray = table.Rows[i+1].ItemArray; // move second to first
table.Rows[i+1].ItemArray = row1Items; // move first to second
}
It even works with more than two, it swaps every consecutive pair of rows.

It seems like you want to sort rows in your DataTable by Name.
To achieve this, you can use the following example :
Dim dv As DataView = dt.DefaultView
dv.Sort = "Name desc" ' Where "Name" is your column name
dt = dv.ToTable()

Related

count the unique values in one column in EXCEL 2010 or R with 1 million rows

After searching the forum, I did not find a good solution for this question. If I missed it, please tell me.
I need to count the unique values in one column in EXCEL 2010.
The worksheet has 1 million rows and 10 columns. All cell values are string or numbers.
I used the solution at Count unique values in a column in Excel
=SUMPRODUCT((A2:A1000000<>"")/COUNTIF(A2:A100000,A2:A1000000&""))
But, it runs so long time that the EXCEL is almost frozen. And, it generates 25 processes in Win 7.
Are there more efficient ways to do it?
Also, in the column, all values have for format of
AX_Y
here, A is a character, X is an integer, Y is an integer from 1 to 10.
For example, A5389579_10
I need to cut off the part after (including) undersocre. for the example,
A5389579
This is what I need to count as unique values in all cells in one column.
For example, A5389579_10
A1543848_6
A5389579_8
Here, the unique value has 2 after removing the part after underscore.
How to do it in EXCEL VBA and R (if no efficient solution for EXCEL)?
If you want to do this by VBA, you can take advantage of the Collection object. Since collections can only contain unique values, trying to add all of your input data to a collection will result in an array of unique values. The code below takes all the variables in a selected range and then outputs an array with distinct values to an other sheet (in this case a sheet named Output).
Sub ReturnDistinct()
Dim Cell As Range
Dim i As Integer
Dim DistCol As New Collection
Dim DistArr()
Dim OutSht As Worksheet
Dim LookupVal As String
Set OutSht = ActiveWorkbook.Sheets("Output") '<~~ Define sheet to putput array
If TypeName(Selection) <> "Range" Then Exit Sub
'Add all distinct values to collection
For Each Cell In Selection
If InStr(Cell.Value, "_") > 0 Then
LookupVal = Mid(Cell.Value, 1, InStr(Cell.Value, "_") - 1)
Else
LookupVal = Cell.Value
End If
On Error Resume Next
DistCol.Add LookupVal, CStr(LookupVal)
On Error GoTo 0
Next Cell
'Write collection to array
ReDim DistArr(1 To DistCol.Count, 1 To 1)
For i = 1 To DistCol.Count Step 1
DistArr(i, 1) = DistCol.Item(i)
Next i
'Outputs distinct values
OutSht.Range("A1:A" & UBound(DistArr)).Value = DistArr
End Sub
Note that since this code writes all the distinct values to a single column in the OutSht-sheet, this will return an error if there are more than 1,048,576 distinct values in your dataset. In that case you would have to split the data to be filled into multiple output columns.
For your specific request to count, use the below in a formula like =COUNTA(GetUniques(LEFT("A1:A100000",FIND("_","A1:A100000")-1)) entered as an array formula with Ctrl+Shift+Enter.
It also accepts multiple ranges / values (e.g. GetUniques("A1:A10","B2:E4"))
Function GetUniques(ParamArray args())
Dim arg, ele, arr, i As Long
Dim c As Collection
Set c = New Collection
For Each arg In args
If TypeOf arg Is Range Then
If arg.Count = 1 Then
arr = array(arg.value)
Else
arr = arg.Value
End If
ElseIf VarType(arg) > vbArray Then
arr = arg
Else
arr = Array(arg)
End If
For Each ele In arr
On Error Resume Next
c.Add ele, VarType(ele) & "|" & CStr(ele)
On Error GoTo 0
Next ele
Next arg
If c.Count > 0 Then
ReDim arr(0 To c.Count - 1)
For i = 0 To UBound(arr)
arr(i) = c(i + 1)
Next i
Set c = Nothing
GetUniques = arr
End If
End Function
edit: added a performance optimisation for ranges (loads them at once into an array - much faster than enumerating through a range)
In R:
# sample data
df <- data.frame(x=1:1000000,
y=sample(1e6:(1e7-1),1e6,replace=T))
df$y <- paste0("A",df$y,"_",sample(1:10,1e6,replace=T))
# this does the work...
length(unique(sub("_[0-9]+","",df$y)))
# [1] 946442
# and it's fast...
system.time(length(unique(sub("_[0-9]+","",df$y))))
# user system elapsed
# 2.01 0.00 2.02
In excel 2010... in the next column add (if original data was in A:A add in B1)
= 1/COUNTIF(A:A,A1) and copy down col B to the bottom of your data. Depending on your PC it may chug away calculating for a long time, but it will work. Then copy col B & paste values over itself.
Then SUM col B

Dynamically count of similar kind of Data

I have one data table in VB page which contain bulk data.In that data table one column named as vType and values in that column is one of Pr defined values such as 'A','B','C','D' etc , which comes from one Datable.
Now I want count of each type at the end.
For ex : CountA = 20,CountB=25 and so on .
Till now I have compared Each value using If condition which is static
For each dr as dataRow in dsType.rows
If dr("vType") = 'A' Then
CountA += 1
ElseIf dr("vType") = 'B' Then
CountB +=1
Next dr
and this If condition will repeat depend upon no of types in that data table (at max 8 fix values) I want to do this in single if condition ( Dynamic if Possible) Can I Count these values and store the same into single varaible? appreciate for you prompt reply.
You can use Linq-To-DataSet and Enumerable.GroupBy + Enumerable.Count on each group:
Dim typeGroups = dsType.AsEnumerable().
GroupBy(Function(row) row.Field(Of String)("vType")).
Select(Function(g) New With{ .Type = g.Key, .Count = g.Count(), .TypeGroup = g })
Note that New With creates an anonymous type in VB.NET with custom properties. So like a class on-the-fly which you can use in the current method.
Now you can enumerate the query with For Each:
For Each typeGroup In typeGroups
Console.WriteLine("Type:{0} Count:{1}", typeGroup.Type, typeGroup.Count)
Next
I cannot use Linq, i need to use simple vb only
Then use a Dictionary:
Dim typeCounts = New Dictionary(Of String, Integer)
For Each row As DataRow In dsType.Rows
Dim type = row.Field(Of String)("vType")
If (typeCounts.ContainsKey(type)) Then
typeCounts(type) += 1
Else
typeCounts.Add(type, 1)
End If
Next
Now you have a dictionary where the key is the type and the value is the count of the rows with this type.
why not getting the pretend result from the db itself?
Like so:
select count(*), vType
from someTable
group by vType
Not so sure about your question .. but this is what I've considered ..
You can make it as Sub ..
Sub AssignIncr(ByVal ds as DataSet,byval sFi as String,byval sCrit as String,ByRef Counter as Integer)
For each dr as dataRow in ds.rows
If dr(sFi) = sCrit Then Counter += 1
Next dr
End Sub
So you may use it by ..
AssignIncr(dsType,"vType","A",CountA)

Transpose in Datatable in ASP.NET

I have DataTable with two Column as "ID", "Value" with data as:
ID Value
A 100
A 200
A 300
A 400
A 500
B -100
B -99
B -98
B -97
C 1
C 2
C 3
C 4
I want to display this in GridView as:
A B C
100-100 1
200 -99 2
300 -98 3
400 -97 4
Which is the best way to Transpose this in DataTable. It would be really helpful if any one can provide an example.
Regards
I'm fairly familiar with OSI PI data and I've done the same after pulling PI tag data into an SQL Server database.
The trick is that there needs to be another column with the Start Time or End Time so the correct rows for A, B, and C can be matched up.
Then it's just a matter of using PIVOT (SQL Server 2005+ only) to group them:
SELECT *
FROM (SELECT ts_start, ID, Value FROM DataTable) v
PIVOT( SUM(Value) FOR ID IN ([A],[B],[C]) ) AS pvt
You can use just about any aggregate you want (MAX, MIN, SUM, etc.) above, it doesn't matter as long as there's only one value for each distinct combination of tag and timestamp. Aggregation is required by PIVOT, as are the aliases v and pvt (you can name them whatever you like).
Try this function (something i've recently had to do myself). The params are:
dtTableToTranspose = the table you want to transpose (obviously)
index = the column index that has the row key (in your case it will be 0)
private static DataTable TransposeADONETDataTable(DataTable dtTableToTranspose, Int32 index)
{
DataTable dtTransposedTable = new DataTable("TransposedTable");
String colName = dtTableToTranspose.Columns[index].ColumnName.ToString();
dtTransposedTable.Columns.Add(colName);
foreach (DataRow row in dtTableToTranspose.Rows)
{
dtTransposedTable.Columns.Add(row[index].ToString());
}
Int32 colIndex = 0;
foreach (DataColumn dc in dtTableToTranspose.Columns)
{
if (colIndex != index)
{
DataRow newRow = dtTransposedTable.NewRow();
newRow[0] = dc.ColumnName;
for (Int32 destColIndex = 1; destColIndex < dtTransposedTable.Columns.Count; destColIndex++)
{
newRow[destColIndex] = dtTableToTranspose.Rows[destColIndex - 1][colIndex];
}
dtTransposedTable.Rows.Add(newRow);
}
colIndex++;
}
return dtTransposedTable;
}

Convert GridView table to Html Table but Rows should be columns and columns should be Rows

I have Dataset ds filled up with values Until now I was displaying values in GridView. Now I want that all the rows should be columns and columns should be rows.
I have 2 options: Either 1 I can directly convert grid to columns and display it, or
2 I can convert the GridView to html and then write loops to convert. I was trying the 2nd option but I cant figure out how I should do that. Below is my code:
For Each dr In dt.Rows
htmlTable = htmlTable + "<TR>"
For Each dc In dt.Columns
htmlTable = htmlTable + "<TD>" + ds.Tables(0).Columns(j).ToString() + ""
j = j + 1
Next
i = i + 1
Next
With this code I am still getting same as GridView. Please help me for converting rows to columns and vice versa.
It looks like your attempting to write an HTML table from the DataTable in the DataSet, flipping rows and columns. The code you posted has several issues, so I'm using it more as pseudo-code for my answer.
The reason you're getting the same thing (in terms of rows and columns) as the GridView is because you loop through each row, and in each row you loop through all the columns - you're not flipping columns and rows at all.
Try something like this:
Dim htmlTable As StringBuilder = new StringBuilder()
Dim numberRows As Integer = ds.Tables(0).Rows.Count - 1
Dim numberCols As Integer = ds.Tables(0).Columns.Count - 1
htmlTable.Append("<table>")
' Loop through each column first
For i As Integer = 0 To numberCols
htmlTable.Append("<tr>")
' Now loop through each row, getting the current columns value
' from each row
For j As Integer = 0 To numberRows
htmlTable.Append("<td>")
htmlTable.Append(ds.Tables(0).Rows(j)(i))
htmlTable.Append("</td>")
Next
htmlTable.Append("</tr>")
Next
htmlTable.Append("</table>")
' To get the value of the StringBuilder, call ToString()
Dim resultHtml = htmlTable.ToString()
For example, if you have a table like this:
col1 col2 col3
a b c
d e f
g h i
j k l
The result would be:
a d g j
b e h k
c f i l

Datatable's Compute Function For Rows

As we know that, with compute function of datatable we can get sum of columns.
But I want to get sum of a row of datatable.
I will explain with a example:
I have a datatable like image below: With compute function we can get the sum of each column (product). Such as for product1, 2 + 12 + 50 + 13= 77.
I want to get sum of company1 : 2 + 6 + 4 + 3 + 5 = 20
http://img123.imageshack.us/img123/1517/61519307xx5.jpg
How can I do it with asp.net 1.1?
LINQ to the rescue:
DataTable dt = WhateverCreatesDataTable();
DataRow dr = dt.Rows[0];
int sum = dt.Columns.Cast<DataColumn>().Sum(dc=>(int)dr[dc]);
For those still dragging their knuckles in the stone ages (aka pre-.Net 3.5 and LINQ):
DataTable dt = WhateverCreatesDataTable();
DataRow dr = dt.Rows[0];
int sum = 0;
foreach(DataColumn dc in dt.Columns)
sum += (int)dr[dc];
From msdn:
If you must perform an operation on
two or more columns, you should create
a DataColumn, set its Expression
property to an appropriate expression,
and use an aggregate expression on the
resulting column. In that case, given
a DataColumn with the name "total",
and the Expression property set to
this:
"Quantity * UnitPrice"
Since you want to solve this in 1.1 here is what you can do as a simple solution
DataColumn totalColumn = new DataColumn();
totalColumn.DataType = System.Type.GetType("System.Int32");
totalColumn.ColumnName = "Total";
totalColumn.Expression = "Product1 + Product2 + Product3 + Product4 + Product5";
// Populate and get the DataTable dt then add this computed column to this table
dt.Columns.Add(totalColumn);
//Now if you access the column "Total" of the table you will get the desired result.
We can use Datatable's Compute() function for the following purpose:
To find sum.
To find max value.
To find min value.
To calculate average.
Below links have detailed explaination of Datatable's compute() function:
http://codevariation.blogspot.com/2017/02/using-datatable-compute-function-in-cnet.html
Hope this will help you.
Thanks.

Resources