透視Datatable

作者: 麒麟  來源: 博客園  發布時間: 2010-01-13 09:56  閱讀: 2028 次  推薦: 0   原文鏈接   [收藏]  

  源代碼:/Files/zhuqil/PivotDataTable.zip 

  現在,以表格的形式顯示的數據是任何應用程序的重要組成部分。但有時你需要以數據行格式顯示大量的數據。如果行數巨大,它變得非常難以分析。在這種情況下,您可能希望使用其他格式統計你的數據,如: charts, graphs, groups, pivots等 。本文將介紹一種使用適當的聚合函數的方式來透視你的數據,它可以很容易提高您的報表功能。

  下面的截圖是在GridView中顯示的數據透視功能。(關于數據透視還可以參考:ASP.NET實現類似Excel的數據透視表

  為了簡化方案,我把表的結果分三個區域顯示:RowField, DataField, 和ColumnFields,除了這些,Pivot類提供一些供您來選擇的聚合函數來綁定的數據。可提供的選項有:

  • Count: 返回匹配的數據數量
  • Sum: 返回匹配的數據總和(為了得到總和,將DataField的類型必須轉換為decimal類型)
  • First: 返回匹配的數據第一項
  • Last: 返回匹配的數據最后一項
  • Average: 返回匹配的數據平均(為了得到平均值,將DataField的類型必須轉換為decimal類型)
  • Max: 返回匹配的數據最大值
  • Min: 返回匹配的數據最小值
  • Exists: 如果有匹配的數據,返回“true”,否則“false”

      代碼主要包含了一個名字為"Pivot"的類,在它的構造函數中創建DataTable。 ColumnFields 是一個字符串數組參數,它允許你透視多列數據。這個類還包含了一個實際透視你數據的PivotData() 方法。

    代碼
    public DataTable PivotData(string RowField, string DataField, 
           AggregateFunction Aggregate, 
    params string[] ColumnFields)
    {
        DataTable dt 
    = new DataTable();
        
    string Separator = ".";
        var RowList 
    = (from x in _SourceTable.AsEnumerable() 
            select 
    new { Name = x.Field<object>(RowField) }).Distinct();
        var ColList 
    = (from x in _SourceTable.AsEnumerable() 
                       select 
    new { Name = ColumnFields.Select(n => x.Field<object>(n))
                           .Aggregate((a, b) 
    => a += Separator + b.ToString()) })
                           .Distinct()
                           .OrderBy(m 
    => m.Name);

        dt.Columns.Add(RowField);
        
    foreach (var col in ColList)
        {
            dt.Columns.Add(col.Name.ToString());
        }

        
    foreach (var RowName in RowList)
        {
            DataRow row 
    = dt.NewRow();
            row[RowField] 
    = RowName.Name.ToString();
            
    foreach (var col in ColList)
            {
                
    string strFilter = RowField + " = '" + RowName.Name + "'";
                
    string[] strColValues = 
                  col.Name.ToString().Split(Separator.ToCharArray(), 
                                            StringSplitOptions.None);
                
    for (int i = 0; i < ColumnFields.Length; i++)
                    strFilter 
    += " and " + ColumnFields[i] + 
                                 
    " = '" + strColValues[i] + "'";
                row[col.Name.ToString()] 
    = GetData(strFilter, DataField, Aggregate);
            }
            dt.Rows.Add(row);
        }
        
    return dt;
    }

      首先,該函數通過獲取RowList的Distinct的值,確定行的成員;通過獲取ColList的Distinct值,確定列的成員。然后,創建datatable的列。然后根據所提供的聚合函數,遍歷每一行和獲取匹配值到相應的單元格上。調用GetData()函數,檢索匹配值。

    代碼
    private object GetData(string Filter, string DataField, AggregateFunction Aggregate)
    {
        
    try
        {
            DataRow[] FilteredRows 
    = _SourceTable.Select(Filter);
            
    object[] objList = 
             FilteredRows.Select(x 
    => x.Field<object>(DataField)).ToArray();

            
    switch (Aggregate)
            {
                
    case AggregateFunction.Average:
                    
    return GetAverage(objList);
                
    case AggregateFunction.Count:
                    
    return objList.Count();
                
    case AggregateFunction.Exists:
                    
    return (objList.Count() == 0? "False" : "True";
                
    case AggregateFunction.First:
                    
    return GetFirst(objList);
                
    case AggregateFunction.Last:
                    
    return GetLast(objList);
                
    case AggregateFunction.Max:
                    
    return GetMax(objList);
                
    case AggregateFunction.Min:
                    
    return GetMin(objList);
                
    case AggregateFunction.Sum:
                    
    return GetSum(objList);
                
    default:
                    
    return null;
            }
        }
        
    catch (Exception ex)
        {
            
    return "#Error";
        }
        
    return null;
    }

    這個函數首先過濾到DataRow []數組中匹配RowField和ColumnFields數據 ,然后調用相應的聚合函數。

      如何使用代碼:

      代碼使用起來很簡單。創建一個Pivot類的實例,然后使用要求的參數調用PivotData方法。PivotData()方法返回DataTable,他可直接作為GridView的數據源。

    代碼
    DataTable dt = ExcelLayer.GetDataTable("_Data\\DataForPivot.xls""Sheet1$");
    Pivot pvt 
    = new Pivot(dt);

    grdPivot.DataSource 
    = pvt.PivotData("Designation""CTC"
       AggregateFunction.Max, 
    "Company""Department""Year");
    grdPivot.DataBind();

    示例中使用的數據庫是一個Excel Sheet ,放在示例應用程序的根文件夾下的“_Data”文件夾中。

        該MergeHeader函數創建合并頭部的單元格,并提供了一個簡化的外觀。

    代碼
    private void MergeHeader(GridView gv, GridViewRow row, int PivotLevel)
    {
        
    for (int iCount = 1; iCount <= PivotLevel; iCount++)
        {
            GridViewRow oGridViewRow 
    = new GridViewRow(00
              DataControlRowType.Header, DataControlRowState.Insert);
            var Header 
    = (row.Cells.Cast<tablecell>()
                .Select(x 
    => GetHeaderText(x.Text, iCount, PivotLevel)))
                .GroupBy(x 
    => x);

            
    foreach (var v in Header)
            {
                TableHeaderCell cell 
    = new TableHeaderCell();
                cell.Text 
    = v.Key.Substring(v.Key.LastIndexOf(_Separator) + 1);
                cell.ColumnSpan 
    = v.Count();
                oGridViewRow.Cells.Add(cell);
            }
            gv.Controls[
    0].Controls.AddAt(row.RowIndex, oGridViewRow);
        }
        row.Visible 
    = false;
    }

      該函數為每個PivotLevel創建新行,和相應的合并。 PivotLevel這里是列上的軸完成的數量。

      Header從一個數組中得到所有的列值,對GetHeaderText()返回的重復的值進行分組,根據HeaderText的重復數量,設置新創建的單元格的ColumnSpan屬性。將單元格添加到GridViewRow中。最后添加GridViewRow到GridView。GetHeaderText() 函數根據PivotLevel返回header text.

      例如,假設一個透視表,完成三個ColumnField: Company, Department, 和Year。GridView的初始化時候,頭部將擁有Company.Department。PivotLevel 1是Year。 GetHeaderText()將返回Company。對于PivotLevel 2,GetHeaderText()將返回Company.Department。對于PivotLevel 3,GetHeaderText()將返回Company.Department.Year,等等...

      以下是GridView的截圖,包含三個層次透視數據:

      代碼幫助您合并你想要的格式GridView的頭單元格。對于初學者,在ExcelLayer.GetDataTable()方法將是一個從Excel表中的中獲得數據例子。

      目前,代碼只在DataTable中透視數據。該代碼將得到加強,將來透視IListSource或ICollection派生的任何對象。

      參考原文:http://www.codeproject.com/KB/aspnet/PivotDataTable.aspx

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()