Datatable's Compute Function For Rows - asp.net

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.

Related

Datatable second row to first row

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()

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

Sum the total in a column in datatable

I have a question. I need to sum up the total amount in a single column in datatable. How do i proceed with it?
For example
Total
2
3
4
5
9
10
i need to get a grand total of the whole column.
The most flexible way is to use Enumerable.Sum:
Int64 sum = table.AsEnumerable().Sum(r => r.Field<int>("total"));
Note that you need to add using System.Linq;.
You can also use the DataTable.Compute which syntax is not easy to remember and which is limited:
Int64 sum = (Int64) table.Compute("Sum (total)", null);
If you are you using a SQl server you can have the server calculate it and return you the sum..
SqlCommand cmd = new SqlCommand("SELECT SUM(Total) FROM MyTable", conn);
int nSum = (int)cmd.ExecuteScalar();

How to add a div after every 5 rows of data?

I'm trying to add div after a group of 5 rows of data inside Listview.
I came up with using Mod 5 = 0 but I realized the last row is missing if total row count can't divided by 5.
For example, I have 11 rows of data.
"Div" will be added after 5 and 10.
I also need to add "Div" after 11 as well. (div will display details of each group)
So, something like this
1|2|3|4|5
DIV1
6|7|8|9|10
DIV2
11|
Div3(missing)
Here is inline code I have so far
<%# IIf((Container.DisplayIndex + 6) Mod 5 = 0, "<div id='temp" + Math.Floor((Container.DisplayIndex + 6) / 5).ToString + "' style='display:none'></div>", "")%>
How do I add the last div when total # can't be divided by 5?
I have to get the total# of display index somehow...
You can compare it with the ListView.Items.Count property.
This should work:
Dim addDiv = (Container.DisplayIndex Mod 5 = 0) OrElse _
(Container.DisplayIndex + 1 = ListView1.Items.Count)
If you are using paging you should use DataItemIndex instead of DisplayIndex.
Edit: (according to your last comment)
If you need to show the total record count you have to cast the ListView's DataSource to it's correct type(f.e. a DataTable).
Dim tbl as DataTable = DirectCast(ListView1.DataSource, DataTable)
Dim totalCount as Int32 = tbl.Rows.Count
or in one line:
DirectCast(ListView1.DataSource, DataTable).Rows.Count
But this works only on databinding and not on every postback because the DataSource will be disposed at the end of the Page-Lifecycle.
the "+6" makes it look like you're guessing around how the modulo function works :)
try this:
<%# IIf(Container.DisplayIndex Mod 5 = 4 Or Container.DisplayIndex = ListView.Items.Count , "<div id='temp" + (1+Math.Floor(Container.DisplayIndex/5)).ToString + "' style='display:none'></div>", "")%>
so first (index+6)%5 == 0 is the same as index%5 == 4,
second floor((index+6)/5) results in 2 when index=4, this is not what you want.
using 1+floor(index/5) will give you the correct results --- you could even drop the "1+" if you want the index to start from 0.
(p.s. i don't know asp.net, sorry if there's compiler errors)

Linq to SQL: Group By and Sum()

I'm very new to linq so this should be pretty easy to answer, but I've had a hard time finding the answer.
I have the following LINQ statement, which performs a simple linq query and assigns the resulting values labels on an asp.net web form:
Dim db As New MeetingManagerDataContext
Dim q = From s In db.vwRoomAvailabilities _
Where s.MeetingID = lblMeetingID.Text _
Select s.AllRequestedSingles, s.AllRequestedDoubles, s.AllBookedSingles, s.AllBookedDoubles, SinglesNeeded = s.AllRequestedSingles - s.AllBookedDoubles, DoublesNeeded = s.AllRequestedDoubles - s.AllBookedDoubles
lblSinglesRequested.Text = "Singles Requested: " & q.FirstOrDefault.AllRequestedSingles
lblSinglesBooked.Text = "Singles Booked: " & q.FirstOrDefault().AllBookedSingles
lblSinglesNeeded.Text = "Singles Needed: " & q.FirstOrDefault().SinglesNeeded
lblDoublesRequested.Text = "Doubles Requested: " & q.FirstOrDefault().AllRequestedDoubles
lblDoublesBooked.Text = "Doubles Booked: " & q.FirstOrDefault().AllBookedDoubles
lblDoublesNeeded.Text = "Doubles Needed: " & q.FirstOrDefault().DoublesNeeded
Originally, there was going to be only a single row result and you can see I'm using FirstOrDefault() to grab that single value which works great. But the design has changed, and multiple rows can now be returned by the query. I need to now Group By the MeetingID above, and SUM each of the selected columns (i.e. s.AllRequestedDoubles).
I've found lots of grouping and summing samples but none seem to fit this scenario very well.
Can you help me modify the above LINQ to Sum the resulting values instead of just showing the first row result values?
Try this
From s In db.vwRoomAvailabilities
Where s.MeetingID = lblMeetingID.Text
Group by s.MeetingID
into SumAllRequestedDoubles = sum(s.AllRequestedDoubles),
SumAggregate2 = sum(s.SomeField2),
SumAggregate3 = sum(s.SomeField3)
Select SumAllRequestedDoubles, SumAggregate2, SumAggregate3
That will get you started for performing a SUM on that single column.
You'll need to project each SUM'd column into a new aliased column (like i did above).
Also, as you're new to LINQ-SQL, check out LinqPad - it will rock your world.

Resources