艾伟_转载:ASP.NET实现类似Excel的数据透视表

    代码:/Files/zhuqil/Pivot.zip

    数据透视表提供的数据三维视图效果,在Microsoft Excel能创建数据透视表,但是,它并不会总是很方便使用Excel。您可能希望在Web应用程序中创建一个数据透视报表。创建一个简单的数据透视表可能是一件非常复杂的任务。所以,我打算不但为你提供一个非常有用的工具创建简单和高级的数据透视表,而且为你移除一些笼罩他们的神秘面纱。

   目标是:我们想要有能力将datatable中的二维的数据转换成三维视图。

   在大多数情况下,你会从数据库的查询数据填充数据表,例如

代码

SELECT 
    SalesPeople.FullName AS [Sales Person] 
    , Products.FullName AS [Product] 
    , SUM(Sales.SalesAmount) AS [Sale Amount] 
    , SUM(Sales.Qty) AS [Quantity] 
FROM 
    Sales 
JOIN 
    SalesPeople WITH (NOLOCK) 
    ON SalesPeople.SalesPersonID = Sales.SalesPersonID 
JOIN 
    Products WITH (NOLOCK) 
    ON Products.ProductCode = Sales.ProductCode 
GROUP BY 
    SalesPeople.FullName 
    , Products.FullName

 该查询会产生下面的数据表:


Sales Person


Product


Quantity


Sale Amount


John


Pens


200


350


John


Pencils


400


500


John


Notebooks


100


300


John


Rulers


50


100


John


Calculators


120


1200


John


Back Packs


75


1500


Jane


Pens


225


393.75


Jane


Pencils


335


418.75


Jane


Notebooks


200


600


Jane


Rulers


75


150


Jane


Calculators


80


800


Jane


Back Packs


97


1940


Sally


Pens


202


353.5


Sally


Pencils


303


378.75


Sally


Notebooks


198


600


Sally


Rulers


98


594


Sally


Calculators


80


800


Sally


Back Packs


101


2020


Sarah


Pens


112


196


Sarah


Pencils


245


306.25


Sarah


Notebooks


198


594


Sarah


Rulers


50


100


Sarah


Calculators


66


660


Sarah


Back Packs


50


2020

    正如你所看到的,这是一个二维表,它不是一个非常有用的报表。因此,我们得改变,将它变成更可读的数据表。

    数据透视表有3个面。

    X轴构成了在表格上方的大标题。Y轴构成表的左栏,Z轴构成了X轴和Y轴对应的值。简单的数据透视表将会对每一个x轴值都只有一个z轴列,高级的数据透视表将对于每个X轴的值会对应有多个Z轴的值。

    一个非常重要的一点是,Z轴的值只能是数字。这是因为Z轴值为横轴和纵轴的总额。使用一个非数值Z轴字段将抛出一个异常。

    因此,如果你注意上面的数据表,你会发现,“Sales Person”和“Product”字段可以分配到的X轴或Y轴,但不能给z轴。在“Quantity”和“Sale Amount”字段可以被分配到z轴。

    Pivot 类将数据表转换成html table。然后您可以将它输出到Web窗体上。那么,这只是实现的方法。如果你愿意,你可以根据这个类的逻辑创建一个用户控件。

代码

#region Variables 
    private DataTable _DataTable; 
    private string _CssTopHeading; 
    private string _CssSubHeading; 
    private string _CssLeftColumn; 
    private string _CssItems; 
    private string _CssTotals; 
    private string _CssTable; 
#endregion Variables 
#region Constructors 
public Pivot(DataTable dataTable) 

    Init(); 
    _DataTable = dataTable; 

#endregion Constructors

     这部分的代码是非常自我解释。 你能创建一个Pivot 对象,通过传递一个datatable作为参数。在init()方法只分配一个空字符串值给CSS变量。如果CSS的变量是一个空字符串,构造方法将使用默认的样式。每一个CSS变量都有一个相应的属性。

代码

private string FindValue(string xAxisField, string xAxisValue, string yAxisField, string yAxisValue, string zAxisField) 

    string zAxisValue = ""; 
    try 
    { 
        foreach (DataRow row in _DataTable.Rows) 
        { 
            if (Convert.ToString(row[xAxisField]) == xAxisValue && Convert.ToString(row[yAxisField]) == yAxisValue) 
            { 
                zAxisValue = Convert.ToString(row[zAxisField]); 
                break; 
            } 
        } 
    } 
    catch 
    { 
        throw; 
    } 
    return zAxisValue; 

    在FindValue(...)方法在数据表中搜索的对应x轴和y轴值的Z轴值。xAxisField是X轴字段的列名(例如“Product”),而xAxisValue是在该列的值。该yAxisField是的Y轴字段的列名(例如“Sales Person”),并yAxisValue是在该列的值。该zAxisField是列名,在其中Z轴值,是您正在寻找地(例如“Sale Amount”)。

代码

private string[] FindValues(string xAxisField, string xAxisValue, string yAxisField, string yAxisValue, string[] zAxisFields) 

    int zAxis = zAxisFields.Length; 
    if (zAxis < 1) 
        zAxis++; 
    string[] zAxisValues = new string[zAxis]; 
    //set default values 
    for (int i = 0; i <= zAxisValues.GetUpperBound(0); i++) 
    { 
        zAxisValues[i] = "0"; 
    } 
    try 
    { 
        foreach (DataRow row in _DataTable.Rows) 
        { 
            if (Convert.ToString(row[xAxisField]) == xAxisValue && Convert.ToString(row[yAxisField]) == yAxisValue) 
            { 
                for (int z = 0; z < zAxis; z++) 
                { 
                    zAxisValues[z] = Convert.ToString(row[zAxisFields[z]]); 
                } 
                break; 
            } 
        } 
    } 
    catch 
    { 
        throw; 
    } 
    return zAxisValues; 
}

    在FindValues(...)方法类似FindValue(...)方法,然而,它会返回多个z轴的值。这是用于高级的数据透视表,对应于x轴的值,您会有多个Z轴列。

代码

private void MainHeaderTopCellStyle(HtmlTableCell cell) 

    if (_CssTopHeading == "") 
    { 
        cell.Style.Add("font-family", "tahoma"); 
        cell.Style.Add("font-size", "10pt"); 
        cell.Style.Add("font-weight", "normal"); 
        cell.Style.Add("background-color", "black"); 
        cell.Style.Add("color", "white"); 
        cell.Style.Add("text-align", "center"); 
    } 
    else 
        cell.Attributes.Add("Class", _CssTopHeading); 
}

    这是CSS样式的方法之一。这在X轴上使用流行的样式(table的顶行)。如果您没有指定一个CSS类名给这个属性,该方法将使用默认的样式。 CSS类将会被应用到网页中的HTML table。

代码

///  
/// Creates an advanced 3D Pivot table. 
///  
/// The main heading at the top of the report. 
/// The heading on the left of the report. 
/// The sub heading at the top of the report. 
/// HtmlTable Control. 
public HtmlTable PivotTable(string xAxisField, string yAxisField, string[] zAxisFields) 

    HtmlTable table = new HtmlTable(); 
    //style table 
    TableStyle(table); 
    /* 
    * The x-axis is the main horizontal row. 
    * The z-axis is the sub horizontal row. 
    * The y-axis is the left vertical column. 
    */ 
    try 
    { 
        //get distinct xAxisFields 
        ArrayList xAxis = new ArrayList(); 
        foreach (DataRow row in _DataTable.Rows) 
        { 
            if (!xAxis.Contains(row[xAxisField])) 
                xAxis.Add(row[xAxisField]); 
        } 
        //get distinct yAxisFields 
        ArrayList yAxis = new ArrayList(); 
        foreach (DataRow row in _DataTable.Rows) 
        { 
            if (!yAxis.Contains(row[yAxisField])) 
                yAxis.Add(row[yAxisField]); 
        } 
        //create a 2D array for the y-axis/z-axis fields 
        int zAxis = zAxisFields.Length; 
        if (zAxis < 1) 
            zAxis = 1; 
        string[,] matrix = new string[(xAxis.Count * zAxis), yAxis.Count]; 
        string[] zAxisValues = new string[zAxis]; 
        for (int y = 0; y < yAxis.Count; y++) //loop thru y-axis fields 
        { 
            //rows 
            for (int x = 0; x < xAxis.Count; x++) //loop thru x-axis fields 
            { 
                //main columns 
                //get the z-axis values 
                zAxisValues = FindValues(xAxisField, Convert.ToString(xAxis[x]) 
                    , yAxisField, Convert.ToString(yAxis[y]), zAxisFields); 
                for (int z = 0; z < zAxis; z++) //loop thru z-axis fields 
                { 
                    //sub columns 
                    matrix[(((x + 1) * zAxis - zAxis) + z), y] = zAxisValues[z]; 
                } 
            } 
        } 
        //calculate totals for the y-axis 
        decimal[] yTotals = new decimal[(xAxis.Count * zAxis)]; 
        for (int col = 0; col < (xAxis.Count * zAxis); col++) 
        { 
            yTotals[col] = 0; 
            for (int row = 0; row < yAxis.Count; row++) 
            { 
                yTotals[col] += Convert.ToDecimal(matrix[col, row]); 
            } 
        } 
        //calculate totals for the x-axis 
        decimal[,] xTotals = new decimal[zAxis, (yAxis.Count + 1)]; 
        for (int y = 0; y < yAxis.Count; y++) //loop thru the y-axis 
        { 
            int zCount = 0; 
            for (int z = 0; z < (zAxis * xAxis.Count); z++) //loop thru the z-axis 
            { 
                xTotals[zCount, y] += Convert.ToDecimal(matrix[z, y]); 
                if (zCount == (zAxis - 1)) 
                    zCount = 0; 
                else 
                    zCount++; 
            } 
        } 
        for (int xx = 0; xx < zAxis; xx++) //Grand Total 
        { 
            for (int xy = 0; xy < yAxis.Count; xy++) 
            { 
                xTotals[xx, yAxis.Count] += xTotals[xx, xy]; 
            } 
        } 
        //Build HTML Table 
        //Append main row (x-axis) 
        HtmlTableRow mainRow = new HtmlTableRow(); 
        mainRow.Cells.Add(new HtmlTableCell()); 
        for (int x = 0; x <= xAxis.Count; x++) //loop thru x-axis + 1 
        { 
            HtmlTableCell cell = new HtmlTableCell(); 
            cell.ColSpan = zAxis; 
            if (x < xAxis.Count) 
                cell.InnerText = Convert.ToString(xAxis[x]); 
            else 
                cell.InnerText = "Grand Totals"; 
            //style cell 
            MainHeaderTopCellStyle(cell); 
            mainRow.Cells.Add(cell); 
        } 
        table.Rows.Add(mainRow); 
        //Append sub row (z-axis) 
        HtmlTableRow subRow = new HtmlTableRow(); 
        subRow.Cells.Add(new HtmlTableCell()); 
        subRow.Cells[0].InnerText = yAxisField; 
        //style cell 
        SubHeaderCellStyle(subRow.Cells[0]); 
        for (int x = 0; x <= xAxis.Count; x++) //loop thru x-axis + 1 
        { 
            for (int z = 0; z < zAxis; z++) 
            { 
                HtmlTableCell cell = new HtmlTableCell(); 
                cell.InnerText = zAxisFields[z]; 
                //style cell 
                SubHeaderCellStyle(cell); 
                subRow.Cells.Add(cell); 
            } 
        } 
        table.Rows.Add(subRow); 
        //Append table items from matrix 
        for (int y = 0; y < yAxis.Count; y++) //loop thru y-axis 
        { 
            HtmlTableRow itemRow = new HtmlTableRow(); 
            for (int z = 0 ; z <= (zAxis * xAxis.Count); z++) //loop thru z-axis + 1 
            { 
                HtmlTableCell cell = new HtmlTableCell(); 
                if (z == 0) 
                { 
                    cell.InnerText = Convert.ToString(yAxis[y]); 
                    //style cell 
                    MainHeaderLeftCellStyle(cell); 
                } 
                else 
                { 
                    cell.InnerText = Convert.ToString(matrix[(z-1), y]); 
                    //style cell 
                    ItemCellStyle(cell); 
                } 
                itemRow.Cells.Add(cell); 
            } 
            //append x-axis grand totals 
            for (int z = 0; z < zAxis; z++) 
            { 
                HtmlTableCell cell = new HtmlTableCell(); 
                cell.InnerText = Convert.ToString(xTotals[z, y]); 
                //style cell 
                TotalCellStyle(cell); 
                itemRow.Cells.Add(cell); 
            } 
            table.Rows.Add(itemRow); 
        } 
        //append y-axis totals 
        HtmlTableRow totalRow = new HtmlTableRow(); 
        for (int x = 0; x <= (zAxis * xAxis.Count); x++) 
        { 
            HtmlTableCell cell = new HtmlTableCell(); 
            if (x == 0) 
                cell.InnerText = "Totals"; 
            else 
                cell.InnerText = Convert.ToString(yTotals[x-1]); 
            //style cell 
            TotalCellStyle(cell); 
            totalRow.Cells.Add(cell); 
        } 
        //append x-axis/y-axis totals 
        for (int z = 0; z < zAxis; z++) 
        { 
            HtmlTableCell cell = new HtmlTableCell(); 
            cell.InnerText = Convert.ToString(xTotals[z, xTotals.GetUpperBound(1)]); 
            //style cell 
            TotalCellStyle(cell); 
            totalRow.Cells.Add(cell); 
        } 
        table.Rows.Add(totalRow); 
    } 
    catch 
    { 
        throw; 
    } 
    return table; 
}

    PivotTable(…) 方法,是所有神奇发生的地方。有两种重载方法,一个创建了一个简单的数据透视表,而其他(上面的方法)创建一个高级的数据透视表。唯一的区别在于,一个简单只有一个的z轴,而高级的,不止一个。

    Pivot.zip文件中包括两个解决方案。Pivot 是一个类库解决方案是。您可以编译此解决方案和在Web应用程序中引用Pivot.dll。另一个解决方案是PivotTest,它是是一个ASP.NET应用程序。这说明如何实现Pivot类。

代码

public DataTable DataTableForTesting 

    get 
    { 
        DataTable dt = new DataTable("Sales Table"); 
        dt.Columns.Add("Sales Person"); 
        dt.Columns.Add("Product"); 
        dt.Columns.Add("Quantity"); 
        dt.Columns.Add("Sale Amount"); 
        dt.Rows.Add(new object[] { "John", "Pens", 200, 350.00 }); 
        dt.Rows.Add(new object[] { "John", "Pencils", 400, 500.00 }); 
        dt.Rows.Add(new object[] { "John", "Notebooks", 100, 300.00 }); 
        dt.Rows.Add(new object[] { "John", "Rulers", 50, 100.00 }); 
        dt.Rows.Add(new object[] { "John", "Calculators", 120, 1200.00 }); 
        dt.Rows.Add(new object[] { "John", "Back Packs", 75, 1500.00 }); 
        dt.Rows.Add(new object[] { "Jane", "Pens", 225, 393.75 }); 
        dt.Rows.Add(new object[] { "Jane", "Pencils", 335, 418.75 }); 
        dt.Rows.Add(new object[] { "Jane", "Notebooks", 200, 600.00 }); 
        dt.Rows.Add(new object[] { "Jane", "Rulers", 75, 150.00 }); 
        dt.Rows.Add(new object[] { "Jane", "Calculators", 80, 800.00 }); 
        dt.Rows.Add(new object[] { "Jane", "Back Packs", 97, 1940.00 }); 
        dt.Rows.Add(new object[] { "Sally", "Pens", 202, 353.50 }); 
        dt.Rows.Add(new object[] { "Sally", "Pencils", 303, 378.75 }); 
        dt.Rows.Add(new object[] { "Sally", "Notebooks", 198, 600.00 }); 
        dt.Rows.Add(new object[] { "Sally", "Rulers", 98, 594.00 }); 
        dt.Rows.Add(new object[] { "Sally", "Calculators", 80, 800.00 }); 
        dt.Rows.Add(new object[] { "Sally", "Back Packs", 101, 2020.00 }); 
        dt.Rows.Add(new object[] { "Sarah", "Pens", 112, 196.00 }); 
        dt.Rows.Add(new object[] { "Sarah", "Pencils", 245, 306.25 }); 
        dt.Rows.Add(new object[] { "Sarah", "Notebooks", 198, 594.00 }); 
        dt.Rows.Add(new object[] { "Sarah", "Rulers", 50, 100.00 }); 
        dt.Rows.Add(new object[] { "Sarah", "Calculators", 66, 660.00 }); 
        dt.Rows.Add(new object[] { "Sarah", "Back Packs", 50, 2020.00 }); 
        return dt; 
    } 

     我已创建数据表的属性,它建立在上面的例子中的数据表。这只是用于演示目的。

代码

protected void Page_Load(object sender, EventArgs e) 

    //Advanced Pivot 
    Pivot advPivot = new Pivot(DataTableForTesting); 
    HtmlTable advancedPivot = advPivot.PivotTable("Sales Person", "Product", new string[] { "Sale Amount", "Quantity" }); 
    div1.Controls.Add(advancedPivot); 
    //Simple Pivot 
    Pivot pivot = new Pivot(DataTableForTesting); 
    //override default style with css 
    pivot.CssTopHeading = "Heading"; 
    pivot.CssLeftColumn = "LeftColumn"; 
    pivot.CssItems = "Items"; 
    pivot.CssTotals = "Totals"; 
    pivot.CssTable = "Table"; 
    HtmlTable simplePivot = pivot.PivotTable("Product", "Sales Person", "Sale Amount"); 
    div2.Controls.Add(simplePivot); 

    上述代码包括两个实例化的pivot对象。第一个高级的pivot和第二是一个简单的pivot。你可以看到我已经为div添加了HtmlTable控件。我创建具有runat="server"属性的div,这样我可以在后台代码里面访问它。div只是帮助HtmlTable的定位。

使用默认样式的高级的数据透视表:

  John Jane Sally Sarah Grand Totals
Product Sale Amount Quantity Sale Amount Quantity Sale Amount Quantity Sale Amount Quantity Sale Amount Quantity
Pens 350 200 393.75 225 353.5 202 196 112 1293.25 739
Pencils 500 400 418.75 335 378.75 303 306.25 245 1603.75 1283
Notebooks 300 100 600 200 600 198 594 198 2094 696
Rulers 100 50 150 75 594 98 100 50 944 273
Calculators 1200 120 800 80 800 80 660 66 3460 346
Back Packs 1500 75 1940 97 2020 101 2020 50 7480 323
Totals 3950 945 4302.50 1012 4746.25 982 3876.25 721 16875.00 3660

使用自定义的CSS样式简单的数据透视表:


Sales Person


Pens


Pencils


Notebooks


Rulers


Calculators


Back Packs


Grand Totals


John


350


500


300


100


1200


1500


3950


Jane


393.75


418.75


600


150


800


1940


4302.50


Sally


353.5


378.75


600


594


800


2020


4746.25


Sarah


196


306.25


594


100


660


2020


3876.25


Totals


1293.25


1603.75


2094


944


3460


7480


16875.00

 参考原文:http://www.codeproject.com/KB/aspnet/Pivot.aspx

时间: 2024-09-02 20:52:00

艾伟_转载:ASP.NET实现类似Excel的数据透视表的相关文章

ASP.NET实现类似Excel的数据透视表

数据透视表提供的数据三维视图效果,在Microsoft Excel能创建数据透视表,但是,它并不会总是很 方便使用Excel.您可能希望在Web应用程序中创建一个数据透视报表.创建一个简单的数据透视表可能是 一件非常复杂的任务.所以,我打算不但为你提供一个非常有用的工具创建简单和高级的数据透视表,而 且为你移除一些笼罩他们的神秘面纱. 目标是:我们想要有能力将datatable中的二维的数据转换成三维视图. 在大多数情况下,你会从数据库的查询数据填充数据表,例如 SELECt SalesPeop

移动Excel 2007数据透视表

      您可能想要移动Excel 2007数据透视表,以便可以在Excel 2007数据透视表的当前位置插入工作表单元格.行或列.         单击Excel 2007数据透视表.       在"选项"选项卡的"操作"组中,单击"移动数据透视表".       将显示"移动数据透视表"对话框.         在"选择放置数据透视表的位置"下,执行以下操作之一:       要将Excel 200

用excel中数据透视表分类求数据平均值方法

考试结束,教育部门要求全市学生的成绩都汇总在如图1的同一个Excel工作表中,并要求求出各学校.各专业.各学科的平均分. 全市三个学校.每个学校都有六个专业.每个专业都有五门课.各专业人数不等,总计有1000余人,工作量巨大.但如果采用Excel数据透视表来完成的话,呵呵,就简单多了. 一.创建数据透视表 点击菜单命令"数据→数据透视表和数据透视图",打开"数据透视表和数据透视图向导"对话框. 第一步,如图2所示,选择"Microsoft Excel数据列

艾伟_转载:透视Datatable

源代码:/Files/zhuqil/PivotDataTable.zip  现在,以表格的形式显示的数据是任何应用程序的重要组成部分.但有时你需要以数据行格式显示大量的数据.如果行数巨大,它变得非常难以分析.在这种情况下,您可能希望使用其他格式统计你的数据,如: charts, graphs, groups, pivots等 .本文将介绍一种使用适当的聚合函数的方式来透视你的数据,它可以很容易提高您的报表功能. 下面的截图是在GridView中显示的数据透视功能.(关于数据透视还可以参考:ASP

VSTO学习笔记(十四)Excel数据透视表与PowerPivot

原文:VSTO学习笔记(十四)Excel数据透视表与PowerPivot 近期公司内部在做一种通用查询报表,方便人力资源分析.统计数据.由于之前公司系统中有一个类似的查询使用Excel数据透视表完成的,故我也打算借鉴一下. 测试代码下载    原有系统是使用VBA编写的,难以维护,且对新的操作系统如Windows 7.64位架构不支持,我准备用VSTO进行重写. 数据透视表是一种交互式的表,可以进行某些计算,如求和与计数等.所进行的计算与数据跟数据透视表中的排列有关. 数据透视表是一种完全自助式

IIS日志分析工具之EXCEL数据透视表

互联网上分析IIS的工具倒是不少,不过我没有遇见能够符合我要求的,一般的都是只能查询IIS日志内的蜘蛛爬行的次数而已.下面说个比较简单且非常实用的方法,通过EXCEL的一些简单的公式做出想得到的一系列数据,例如时间间隔,爬行页面,返回状态码,网址参数,蜘蛛类型,蜘蛛IP等,通过以上数据可以进行对网站的问题的排查,更正. 首先必须有自己的服务器或者能够查看IIS日志的权限,通过FTP将iis日志文件从空间中下载到本地 服务器获取IIS日志的方式:打开IIS,点击要查询网站>右键>属性>网站

Excel中如何用数据透视表进行分类打印

  入数据透视表 选择数据源中的某个单元格,单击"插入"选项卡,在"表格"组中单击"数据透视表",弹出对话框后直接点确定,在新工作表中插入数据透视表. 在"数据透视表字段列表"中依次勾选各个字段名称,将各个字段添加到数据透视表中,需要注意的是,本例要按"班级"分类打印,因而需要将"班级"字段放置到数据透视表的第一列,即在"数据透视表字段列表"中将"班级&qu

ASP.NET实例教程:创建数据透视表

代码:Pivot.zip 数据透视表提供的数据三维视图效果,在Microsoft Excel能创建数据透视表,但是,它并不会总是很方便使用Excel.您可能希望在Web应用程序中创建一个数据透视报表.创建一个简单的数据透视表可能是一件非常复杂的任务.所以,我打算不但为你提供一个非常有用的工具创建简单和高级的数据透视表,而且为你移除一些笼罩他们的神秘面纱. 目标是:我们想要有能力将datatable中的二维的数据转换成三维视图. 在大多数情况下,你会从数据库的查询数据填充数据表,例如 SELECT

Excel应用教程:Excel数据透视表分类求学生成绩平均值

期末统考结束后,教育局要求全市学生的成绩都汇总在如图1的同一个Excel工作表中,并要求求出各学校.各专业.各学科的平均分. 全市三个学校.每个学校都有六个专业.每个专业都有五门课.各专业人数不等,总计有1000余人,工作量巨大.但如果采用Excel数据透视表来完成的话,呵呵,就简单多了. 一.创建数据透视表 点击菜单命令"数据→数据透视表和数据透视图",打开"数据透视表和数据透视图向导"对话框. 第一步,如图2所示,选择"Microsoft Excel数