Sometimes when you working with the large data, you might want to display the data in pivot table / cross tab. Crystal report have a very nice wizard to make our life easier to create cross tab, but not in vb.net
For example you have data table like Table CompanyDetail populated from the SQL Select Query below
company_code | PAY_AMOUNT | tax_period_month |
---|---|---|
777 | 3000,0000 | 05 |
777 | 2000,0000 | 08 |
777 | 1000,0000 | 11 |
1010000 | 4000,0000 | 11 |
777 | 5000,0000 | 11 |
And you want to display into this order:
company_code | 05 | 08 | 11 |
---|---|---|---|
777 | 3000,0000 | 2000,0000 | 6000,0000 |
1010000 | 4000,0000 |
So Here is the step to convert Data Table data into pivot table
Step1. Create this function:
ColumnX = Is the Column that you want to make cross tab (In this example is tax_period_month)
ColumnY = Is the column that will be put in the left column (company_code)
ColumnZ = Is the total value from combining columnX and columnY (PAY_AMOUNT)
Function GetInversedDataTable(ByVal table As DataTable, ByVal columnX As String, ByVal columnY As String, ByVal columnZ As String, ByVal nullValue As String, ByVal sumValues As Boolean) As DataTable 'Create a DataTable to Return Dim returnTable As New DataTable() If columnX = "" Then columnX = table.Columns(0).ColumnName End If 'Add a Column at the beginning of the table returnTable.Columns.Add(columnY) 'Read all DISTINCT values from columnX Column in the provided DataTale Dim columnXValues As New List(Of String)() For Each dr As DataRow In table.Rows Dim columnXTemp As String = dr(columnX).ToString() If Not columnXValues.Contains(columnXTemp) Then 'Read each row value, if it's different from others provided, add to the list of values and creates a new Column with its value. columnXValues.Add(columnXTemp) returnTable.Columns.Add(columnXTemp) End If Next 'Verify if Y and Z Axis columns re provided If columnY <> "" AndAlso columnZ <> "" Then 'Read DISTINCT Values for Y Axis Column Dim columnYValues As New List(Of String)() For Each dr As DataRow In table.Rows If Not columnYValues.Contains(dr(columnY).ToString()) Then columnYValues.Add(dr(columnY).ToString()) End If Next 'Loop all Column Y Distinct Value For Each columnYValue As String In columnYValues 'Creates a new Row Dim drReturn As DataRow = returnTable.NewRow() drReturn(0) = columnYValue 'foreach column Y value, The rows are selected distincted Dim rows As DataRow() = table.[Select]((columnY & "='") + columnYValue & "'") 'Read each row to fill the DataTable For Each dr As DataRow In rows Dim rowColumnTitle As String = dr(columnX).ToString() 'Read each column to fill the DataTable For Each dc As DataColumn In returnTable.Columns If dc.ColumnName = rowColumnTitle Then 'If Sum of Values is True it try to perform a Sum 'If sum is not possible due to value types, the value displayed is the last one read If sumValues Then Try drReturn(rowColumnTitle) = Convert.ToDecimal(drReturn(rowColumnTitle)) + Convert.ToDecimal(dr(columnZ)) Catch drReturn(rowColumnTitle) = dr(columnZ) End Try Else drReturn(rowColumnTitle) = dr(columnZ) End If End If Next Next returnTable.Rows.Add(drReturn) Next Else Throw New Exception("The columns to perform inversion are not provided") End If 'if a nullValue is provided, fill the datable with it If nullValue <> "" Then For Each dr As DataRow In returnTable.Rows For Each dc As DataColumn In returnTable.Columns If dr(dc.ColumnName).ToString() = "" Then dr(dc.ColumnName) = nullValue End If Next Next End If Return returnTable End Function
Step 2: Add gridview to the page and create connection to database to set data table:
Dim conn As SqlConnection = Nothing Try Dim connString As String = "Data Source=;Initial Catalog=;Integrated Security=True" conn = New SqlConnection(connString) Dim query As String = "select company_code, PAY_AMOUNT, tax_period_month from ttSSP0 order by tax_period_month" Dim cmd As SqlCommand = New SqlCommand(query, conn) conn.Open() Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection) Dim dt As DataTable = New DataTable() Dim dt2 As DataTable = New DataTable() dt.Load(dr) dt2 = GetInversedDataTable(dt, "tax_period_month", "company_code", "PAY_AMOUNT", "", True) GridView1.DataSource = dt2 GridView1.DataBind() Catch ex As SqlException ' handle error Catch ex As Exception ' handle error Finally conn.Close() End Try
Very nice solution I really appericiate it. I want to add Grand Totals at both column and row level your more help will be a high end thanks
By: Ryasat Ali on August 7, 2009
at 4:36 am
what about gridview in aspx? can you provide the code because mine, the value not appear.. sorry my english not so good…
By: ida on August 13, 2009
at 9:05 am
Hi there,
The above example is using gridview, this is the code
GridView1.DataSource = dt2
GridView1.DataBind()
By: Red Souldier on September 3, 2009
at 11:54 pm
The original author of GetInversedDataTable is felipesabino in the article at http://www.codeproject.com/KB/recipes/CsharpPivotTable.aspx
By: Fred on August 22, 2009
at 3:30 am
This is a beautiful piece of code. Thank you for posting it. It was exactly what I needed.
To make it run in ASP.net 2.0, make these changes in both the function and the sub procedure:
1. Replace List with ArrayList. Thus,
Dim columnYValues As New List(Of String)()
becomes
Dim columnYValues As New ArrayList
2. Replace DataTable, DataRow, and DataColumn with Data.DataTable, Data.DataRow, and Data.DataColumn.
3. Replace CommandBehavior.CloseConnection with System.Data.CommandBehavior.CloseConnection.
That oughta do it.
Thanks again for posting this!
By: Markw707 on September 3, 2009
at 6:58 pm
This is the best solution i found for now. Searched and tested a lot of code, but this one is the best.
Thanks for sharing it with ‘the world’
By: johan on December 16, 2009
at 8:57 am
Really Very Wonderful Solution!!!
By: Jegan on January 12, 2010
at 3:04 pm
thanx!!! a great article…
i just would like to ask..
in my project i need to replace the column z or sum value into the textbox…
do you have any idea??
By: muni on April 6, 2010
at 5:16 am
Im not sure about that, but maybe you could make the table datagrid column into the textbox first in edit template. Since this coding is only datatable, so i think it should not be a problem.
Thanks
By: Red Souldier on April 6, 2010
at 5:33 am
Thanks
However can you provide the same in C#?
By: Bilal on August 20, 2010
at 9:41 am
you can use this website http://www.developerfusion.com/tools/convert/vb-to-csharp/ to convert from vb.net to c#. Although is not 100% accurate but im sure you can see which is not corrected from the conversion code
By: Red Souldier on August 20, 2010
at 9:46 am