.Net GridView应用:多表头固定+分组+总计

一直在网上找资料来弄个固定表头的东西 有时也想根据有字段来对数据进行分组。

完成了一个项目也把一些经常见到的需求提炼出了一个还比较可以的解决方案。

常见需求:

   1、列表显示数据

   2、滚动滚动条时表头固定

   3、按要求将数据分组并计算求和

这些问题在财务系统中经常遇到相比在其他行业也有类似情况,今天下午整理了下资料,来出来和大家分享。

  效果图1:

效果图2 :含总计行

 

代码:

  页面类:

代码
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>GridView固定表头+分组+固定</title>
<style type="text/css">
.staicTitlteDiv{
WIDTH: 1000px;
height:500px ;
OVERFLOW: scroll;
SCROLLBAR
-FACE-COLOR: EAECEC;
SCROLLBAR
-HIGHLIGHT-COLOR: EAECEC;
SCROLLBAR
-SHADOW-COLOR: BLACK;
SCROLLBAR
-3DLIGHT-COLOR: EAECEC;
SCROLLBAR
-ARROW-COLOR: EAECEC;
SCROLLBAR
-TRACK-COLOR: FFFFFF;
SCROLLBAR
-DARKSHADOW-COLOR: EAECEC;

}
.fixedHeaderTr
{
position:relative;
border:
0;
top:expression(
this.offsetParent.scrollTop);

}
th{
position:relative;
background
-color: Beige;
top:expression(
this.offsetParent.scrollTop);
}
</style>

</head>
<body style="text-align:center">
<form id="form1" runat="server">
<div class="staicTitlteDiv">
<asp:GridView ID="GridView1" runat="server">
<HeaderStyle CssClass="fixedHeaderTr" BorderColor="Beige"/>
</asp:GridView>
</div>
</form>
</body>
</html>

后置代码:

using System;
2 using System.Collections;
3 using System.Configuration;
4 using System.Data;
5 using System.Linq;
6 using System.Web;
7 using System.Web.Security;
8 using System.Web.UI;
9 using System.Web.UI.HtmlControls;
10 using System.Web.UI.WebControls;
11 using System.Web.UI.WebControls.WebParts;
12 using System.Xml.Linq;
13 using System.Collections.Generic;
14 using System.Linq;
15 publicpartialclass Default2 : System.Web.UI.Page
16 {
17
18 protectedvoid Page_Load(object sender, EventArgs e)
19 {
20 if (!IsPostBack)
21 {
22 GridView1.RowDataBound+=new GridViewRowEventHandler(GridView1_RowDataBound);
23 GridView1.DataBound+=new EventHandler(GridView_DataBound);
24 GridView1DataBind();
25
26
27 }
28 }
29 void GridView1DataBind()
30 {
31 DataTable table=new DataTable();
32 table.Columns.Add("class",typeof(string)).SetOrdinal(0);
33 table.Columns.Add("student",typeof(string)).SetOrdinal(1);
34 table.Columns.Add("Languages",typeof(Double)).SetOrdinal(2);
35 table.Columns.Add("Rate1",typeof(Double)).SetOrdinal(3);
36 table.Columns.Add("Mathematics",typeof(Double)).SetOrdinal(4);
37 table.Columns.Add("Rate2",typeof(Double)).SetOrdinal(5);
38 table.Columns.Add("English",typeof(Double)).SetOrdinal(6);
39 table.Columns.Add("Rate3",typeof(Double)).SetOrdinal(7);
40 table.Columns.Add("Other",typeof(Double)).SetOrdinal(8);
41 table.Columns.Add("TotalScore",typeof(Double),"ISNULL(Languages,0)+ISNULL(Mathematics,0)+ISNULL(English,0)+ISNULL(Other,0)").SetOrdinal(9);
42
43 table.Columns[3].Expression="Languages/TotalScore";
44 table.Columns[5].Expression="Mathematics/TotalScore";
45 table.Columns[7].Expression="English/TotalScore";
46 Random random=new Random();
47 for (int i=0; i < 100; i++)
48 {
49 DataRow row= table.NewRow();
50 row["student"]="学生"+ i;
51 row["class"]="班级"+ random.Next(0,10);
52 row["Languages"]= random.Next(0,151);
53 row["Mathematics"]= random.Next(0,151);
54 row["English"]= random.Next(0,151);
55 row["Other"]= random.Next(0,150*3+1);
56 table.Rows.Add(row);
57 }
58
59 //GridView1.DataSource =GridViewGroup.AddGurop(table, "class");
60 GridView1.DataSource= GridViewGroup.AddGurop(table,"class","Languages#Mathematics#English#Other");
61 GridView1.DataBind();
62
63 }
64 void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
65 {
66 if (e.Row.RowType== DataControlRowType.Header)
67 {
68 string header="班级#学生#其中 语文 成绩,比例#其中 数学 成绩,比例#其中 英语 成绩,比例#其中 &nbsp; 其他3科#总成绩";
69 AndyGridViewTHeaderHepler help=new AndyGridViewTHeaderHepler();
70 e.Row.CssClass="fixedHeaderTr";
71
72 e.Row.BackColor= System.Drawing.Color.Beige;
73 help.SplitTableHeader(e.Row, header);
74 }
75 else
76 {
77 e.Row.Attributes.Add("onmouseout","this.style.backgroundColor='White'");
78 e.Row.Attributes.Add("onmouseover","this.style.backgroundColor=/"" +"#E7E7FF" +"/"");
79
80 }
81 }
82
83 protectedvoid GridView_DataBound(object sender, EventArgs e)
84 {
85 int index=-1;
86 int startGroupIndex=0;
87 foreach (GridViewRow rowin GridView1.Rows)
88 {
89 index++;
90
91 if (index>0&& (row.Cells[0].Text.ToString().Trim()==""|| row.Cells[0].Text.ToString().Trim()=="&nbsp;"))
92 {
93 row.Cells[0].Text="小计";// GridView1.Rows[startGroupIndex].Cells[0].Text;
94 row.Attributes.Add("style","background-color: #F2F2F2; font-weight: bold;font-variant: normal; color: #000000;text-align:center;");
95 row.Attributes.Remove("onmouseout");
96 row.Attributes.Remove("onmouseover");
97 GridViewGroup.GroupRow(GridView1, index,0,2);
98 GridViewGroup.GropCell(GridView1,0, startGroupIndex, index-1);
99 startGroupIndex= index+1;
100 }
101 }
102 GridViewRow sumRow= GridView1.Rows[index];
103 sumRow.Attributes.Add("style","background-color: #EAEAEA;font-weight: bold;font-variant: normal;color: #000000;text-align: center;");
104 sumRow.Attributes.Remove("onmouseout");
105 sumRow.Attributes.Remove("onmouseover");
106 GridViewGroup.GroupRow(GridView1, index,0,2);
107 }
108 }
109

多表头帮助类(来自网络)

AndyGridViewTHeaderHepler.cs
    
    
1 2 using System; 3 using System.Data; 4 using System.Configuration; 5 using System.Web; 6 using System.Web.Security; 7 using System.Web.UI; 8 using System.Web.UI.WebControls; 9 using System.Web.UI.WebControls.WebParts; 10 using System.Web.UI.HtmlControls; 11 using System.Collections.Generic; 12 using System.Collections; 13 14 15 // ----------------------------------------------------------------------------------- 16 // 17 // Created: 23:07 2008/9/28 Author: Andy Lu 18 // File: AndyGridViewTHeaderHepler.cs 19 // Description: 动态生成复合表头帮助类 20 // 相邻父列头之间用'#'分隔,父列头与子列头用空格(' ')分隔,相邻子列头用逗号分隔(','). 21 // 两行:序号#分公司#组别#本日成功签约单数 预警,续约,流失,合计#累计成功签约单数 预警,续约,流失,合计#任务数#完成比例#排名 22 // 三行:等级#级别#上期结存 件数, 重量,比例#本期调入 收购调入 件数,重量,比例#本期发出 车间投料 件数,重量,比例#本期发出 产品外销百分比 件数,重量,比例#平均值 23 // 三行时请注意:列头要重复 24 // 25 // ----------------------------------------------------------------------------------- 26 public class AndyGridViewTHeaderHepler 27 { 28 public AndyGridViewTHeaderHepler() 29 { 30 // 31 // TODO: Add constructor logic here 32 // 33 } 34 /**/ 35 /// <summary> 36 /// 重写表头 37 /// </summary> 38 /// <param name="targetHeader"> 目标表头 </param> 39 /// <param name="newHeaderNames"> 新表头 </param> 40 /// <remarks> 41 /// </remarks> 42 public void SplitTableHeader(GridViewRow targetHeader, string newHeaderNames) 43 { 44 TableCellCollection tcl = targetHeader.Cells; // 获得表头元素的实例 45 tcl.Clear(); // 清除元素 46 int row = GetRowCount(newHeaderNames); 47 int col = GetColCount(newHeaderNames); 48 string [,] nameList = ConvertList(newHeaderNames, row, col); 49 int RowSpan = 0 ; 50 int ColSpan = 0 ; 51 for ( int k = 0 ; k < row; k ++ ) 52 { 53 string LastFName = "" ; 54 for ( int i = 0 ; i < col; i ++ ) 55 { 56 if (LastFName == nameList[i, k] && k != row - 1 ) 57 { 58 LastFName = nameList[i, k]; 59 continue ; 60 } 61 else 62 { 63 LastFName = nameList[i, k]; 64 } 65 int bFlag = IsVisible(nameList, k, i, LastFName); 66 switch (bFlag) 67 { 68 case 0 : 69 break ; 70 case 1 : 71 RowSpan = GetSpanRowCount(nameList, row, k, i); 72 ColSpan = GetSpanColCount(nameList, row, col, k, i); 73 tcl.Add( new TableHeaderCell()); // 添加表头控件 74 tcl[tcl.Count - 1 ].RowSpan = RowSpan; 75 tcl[tcl.Count - 1 ].ColumnSpan = ColSpan; 76 tcl[tcl.Count - 1 ].HorizontalAlign = HorizontalAlign.Center; 77 tcl[tcl.Count - 1 ].Text = LastFName; 78 break ; 79 case - 1 : 80 string [] EndColName = LastFName.Split( new char [] { ' , ' }); 81 foreach ( string eName in EndColName) 82 { 83 tcl.Add( new TableHeaderCell()); // 添加表头控件 84 tcl[tcl.Count - 1 ].HorizontalAlign = HorizontalAlign.Center; 85 tcl[tcl.Count - 1 ].Text = eName; 86 } 87 break ; 88 } 89 } 90 if (k != row - 1 ) 91 { // 不是起始行,加入新行标签 92 tcl[tcl.Count - 1 ].Text = tcl[tcl.Count - 1 ].Text + " </th></tr><tr class=/ "" + targetHeader.CssClass + " / " > " ; 93 } 94 } 95 } 96 /**/ 97 /// <summary> 98 /// 重写表头 99 /// </summary> 100 /// <param name="targetHeader"> 目标表头 </param> 101 /// <param name="newHeaderNames"> 新表头 </param> 102 /// <remarks> 103 /// </remarks> 104 public void SplitTableHeader(DataGridItem targetHeader, string newHeaderNames) 105 { 106 TableCellCollection tcl = targetHeader.Cells; // 获得表头元素的实例 107 tcl.Clear(); // 清除元素 108 int row = GetRowCount(newHeaderNames); 109 int col = GetColCount(newHeaderNames); 110 string [,] nameList = ConvertList(newHeaderNames, row, col); 111 int RowSpan = 0 ; 112 int ColSpan = 0 ; 113 for ( int k = 0 ; k < row; k ++ ) 114 { 115 string LastFName = "" ; 116 for ( int i = 0 ; i < col; i ++ ) 117 { 118 if (LastFName == nameList[i, k] && k != row - 1 ) 119 { 120 LastFName = nameList[i, k]; 121 continue ; 122 } 123 else 124 { 125 LastFName = nameList[i, k]; 126 } 127 int bFlag = IsVisible(nameList, k, i, LastFName); 128 switch (bFlag) 129 { 130 case 0 : 131 break ; 132 case 1 : 133 RowSpan = GetSpanRowCount(nameList, row, k, i); 134 ColSpan = GetSpanColCount(nameList, row, col, k, i); 135 tcl.Add( new TableHeaderCell()); // 添加表头控件 136 tcl[tcl.Count - 1 ].RowSpan = RowSpan; 137 tcl[tcl.Count - 1 ].ColumnSpan = ColSpan; 138 tcl[tcl.Count - 1 ].HorizontalAlign = HorizontalAlign.Center; 139 tcl[tcl.Count - 1 ].Text = LastFName; 140 break ; 141 case - 1 : 142 string [] EndColName = LastFName.Split( new char [] { ' , ' }); 143 foreach ( string eName in EndColName) 144 { 145 tcl.Add( new TableHeaderCell()); // 添加表头控件 146 tcl[tcl.Count - 1 ].HorizontalAlign = HorizontalAlign.Center; 147 tcl[tcl.Count - 1 ].Text = eName; 148 } 149 break ; 150 } 151 } 152 if (k != row - 1 ) 153 { // 不是起始行,加入新行标签 154 tcl[tcl.Count - 1 ].Text = tcl[tcl.Count - 1 ].Text + " </th></tr><tr class=/ "" + targetHeader.CssClass + " / " > " ; 155 } 156 } 157 } 158 /**/ 159 /// <summary> 160 /// 如果上一行已经输出和当前内容相同的列头,则不显示 161 /// </summary> 162 /// <param name="ColumnList"> 表头集合 </param> 163 /// <param name="rowIndex"> 行索引 </param> 164 /// <param name="colIndex"> 列索引 </param> 165 /// <returns> 1: 显示,-1:含','分隔符,0:不显示 </returns> 166 private int IsVisible( string [,] ColumnList, int rowIndex, int colIndex, string CurrName) 167 { 168 if (rowIndex != 0 ) 169 { 170 if (ColumnList[colIndex, rowIndex - 1 ] == CurrName) 171 { 172 return 0 ; 173 } 174 else 175 { 176 if (ColumnList[colIndex, rowIndex].Contains( " , " )) 177 { 178 return - 1 ; 179 } 180 else 181 { 182 return 1 ; 183 } 184 } 185 } 186 return 1 ; 187 } 188 /**/ 189 /// <summary> 190 /// 取得和当前索引行及列对应的下级的内容所跨的行数 191 /// </summary> 192 /// <param name="ColumnList"& gt;表头集合</param> 193 /// <param name="row"& gt;行数</param> 194 /// <param name="rowIndex"& gt;行索引</param> 195 /// <param name="colIndex"& gt;列索引</param> 196 /// <returns> 行数 </returns> 197 private int GetSpanRowCount( string [,] ColumnList, int row, int rowIndex, int colIndex) 198 { 199 string LastName = "" ; 200 int RowSpan = 1 ; 201 for ( int k = rowIndex; k < row; k ++ ) 202 { 203 if (ColumnList[colIndex, k] == LastName) 204 { 205 RowSpan ++ ; 206 } 207 else 208 { 209 LastName = ColumnList[colIndex, k]; 210 } 211 } 212 return RowSpan; 213 } 214 /**/ 215 /// <summary> 216 /// 取得和当前索引行及列对应的下级的内容所跨的列数 217 /// </summary> 218 /// <param name="ColumnList"& gt;表头集合</param> 219 /// <param name="row"& gt;行数</param> 220 /// <param name="col"& gt;列数</param> 221 /// <param name="rowIndex"& gt;行索引</param> 222 /// <param name="colIndex"& gt;列索引</param> 223 /// <returns> 列数 < /returns> 224 private int GetSpanColCount( string [,] ColumnList, int row, int col, int rowIndex, int colIndex) 225 { 226 string LastName = ColumnList[colIndex, rowIndex]; 227 int ColSpan = ColumnList[colIndex, row - 1 ].Split( new char [] { ' , ' }).Length; 228 ColSpan = ColSpan == 1 ? 0 : ColSpan; 229 for ( int i = colIndex + 1 ; i < col; i ++ ) 230 { 231 if (ColumnList[i, rowIndex] == LastName) 232 { 233 ColSpan += ColumnList[i, row - 1 ].Split( new char [] { ' , ' }).Length; 234 } 235 else 236 { 237 LastName = ColumnList[i, rowIndex]; 238 break ; 239 } 240 } 241 return ColSpan; 242 } 243 /**/ 244 /// <summary> 245 /// 将已定义的表头保存到数组 246 /// </summary> 247 /// <param name="newHeaders"& gt;新表头</param> 248 /// <param name="row"& gt;行数</param> 249 /// <param name="col"& gt;列数</param> 250 /// <returns> 表头数组 </returns> 251 private string [,] ConvertList( string newHeaders, int row, int col) 252 { 253 string [] ColumnNames = newHeaders.Split( new char [] { ' # ' }); 254 string [,] news = new string [col, row]; 255 string Name = "" ; 256 for ( int i = 0 ; i < col; i ++ ) 257 { 258 string [] CurrColNames = ColumnNames[i].ToString().Split( new char [] { ' ' }); 259 for ( int k = 0 ; k < row; k ++ ) 260 { 261 if (CurrColNames.Length - 1 >= k) 262 { 263 if (CurrColNames[k].Contains( " , " )) 264 { 265 if (CurrColNames.Length != row) 266 { 267 if (Name == "" ) 268 { 269 news[i, k] = news[i, k - 1 ]; 270 Name = CurrColNames[k].ToString(); 271 } 272 else 273 { 274 news[i, k + 1 ] = Name; 275 Name = "" ; 276 } 277 } 278 else 279 { 280 news[i, k] = CurrColNames[k].ToString(); 281 } 282 } 283 else 284 { 285 news[i, k] = CurrColNames[k].ToString(); 286 } 287 } 288 else 289 { 290 if (Name == "" ) 291 { 292 news[i, k] = news[i, k - 1 ]; 293 } 294 else 295 { 296 news[i, k] = Name; 297 Name = "" ; 298 } 299 } 300 } 301 } 302 return news; 303 } 304 /**/ 305 /// <summary> 306 /// 取得复合表头的行数 307 /// </summary> 308 /// <param name="newHeaders"& gt;新表头</param> 309 /// <returns> 行数 < /returns> 310 private int GetRowCount( string newHeaders) 311 { 312 string [] ColumnNames = newHeaders.Split( new char [] { ' # ' }); 313 int Count = 0 ; 314 foreach ( string name in ColumnNames) 315 { 316 int TempCount = name.Split( new char [] { ' ' }).Length; 317 if (TempCount > Count) 318 Count = TempCount; 319 } 320 return Count; 321 } 322 /**/ 323 /// <summary> 324 /// 取得复合表头的列数 325 /// </summary> 326 /// <param name="newHeaders"& gt;新表头</param> 327 /// <returns> 列数 < /returns> 328 private int GetColCount( string newHeaders) 329 { 330 return newHeaders.Split( new char [] { ' # ' }).Length; 331 } 332 333 } 334 335 336 分组 汇总 总计帮助类
GridViewGroup.cs
        
        
1 using System; 2 using System.Data; 3 using System.Configuration; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Security; 7 using System.Web.UI; 8 using System.Web.UI.HtmlControls; 9 using System.Web.UI.WebControls; 10 using System.Web.UI.WebControls.WebParts; 11 using System.Xml.Linq; 12 using System.Collections.Generic; 13 14 /// <summary> 15 /// GridViewGroup 的摘要说明 16 /// </summary> 17 public class GridViewGroup 18 { 19 public GridViewGroup() 20 { 21 // 22 // TODO: 在此处添加构造函数逻辑 23 // 24 } 25 /// <summary> 26 /// 向DataTable中添加 行分组汇总列 27 /// </summary> 28 /// <param name="olDtable"> DataTable </param> 29 /// <param name="bjName"> 分组列 </param> 30 /// <param name="numColumsStr"> 需要计算求和的列,用#分割 </param> 31 /// <returns></returns> 32 public static DataTable AddGurop(DataTable olDtable, string bjName, string numColumsStr) 33 { 34 35 // 为null 或 只有一条记录对于分组来说无意义 36 if (olDtable == null ) 37 { 38 return olDtable; 39 } 40 DataTable table = TableSort(olDtable, bjName); 41 Dictionary < int , DataRow > rows = new Dictionary < int , DataRow > (); // 存放汇总行 42 43 IList < string > numColumns = new List < string > (); 44 if (numColumsStr == null ) 45 { 46 numColumns = GetNumColumns(table); 47 } 48 else 49 { 50 string [] columns = numColumsStr.Split( ' # ' ); 51 foreach ( string str in columns) 52 { 53 numColumns.Add(str); 54 } 55 } 56 57 string prevDept = table.Rows[ 0 ][bjName].ToString(); // 58 int NoOwn = 0 ; // 同组项的第一行记录的位置 59 int index = - 1 ; // 索引 60 foreach (DataRow item in table.Rows) 61 { 62 index ++ ; // 当前行索引 63 // 如果相邻两行 分组标记相同 则继续寻找下行,否则该行为同组的最后一行。进行数据处理 64 // item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行 65 if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1 ) 66 { 67 continue ; 68 } 69 else if (index == table.Rows.Count - 1 ) 70 { 71 if (item[bjName].ToString() != prevDept) 72 { 73 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 74 rows.Add(index + rows.Count, row); 75 76 DataRow row2 = table.NewRow(); 77 foreach ( string columnName in numColumns) 78 { 79 row2[columnName] = item[columnName]; 80 } 81 rows.Add(index + rows.Count + 1 , row2); 82 } 83 else 84 { 85 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 86 rows.Add(index + rows.Count + 1 , row); 87 } 88 89 } 90 else 91 { 92 prevDept = item[bjName].ToString(); // 当前分组标记 93 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 94 NoOwn = index; 95 rows.Add(index + rows.Count, row); 96 } 97 } 98 99 DataRow sumRow = CreateSumRow(table, rows, numColumns); 100 101 foreach ( int key in rows.Keys) 102 { 103 table.Rows.InsertAt(rows[key], key); 104 } 105 106 table.Rows.Add(sumRow); 107 return table; 108 } 109 /// <summary> 110 /// 向DataTable中添加 行分组汇总列 111 /// </summary> 112 /// <param name="olDtable"> DataTable </param> 113 /// <param name="bjName"> 分组列 </param> 114 /// <returns></returns> 115 public static DataTable AddGurop(DataTable olDtable, string bjName) 116 { 117 118 // 为null 或 只有一条记录对于分组来说无意义 119 if (olDtable == null ) 120 { 121 return olDtable; 122 } 123 DataTable table = TableSort(olDtable, bjName); 124 Dictionary < int , DataRow > rows = new Dictionary < int , DataRow > (); // 存放汇总行 125 IList < string > numColumns = GetNumColumns(table); 126 string prevDept = table.Rows[ 0 ][bjName].ToString(); // 127 int NoOwn = 0 ; // 同组项的第一行记录的位置 128 int index = - 1 ; // 索引 129 foreach (DataRow item in table.Rows) 130 { 131 index ++ ; // 当前行索引 132 // 如果相邻两行 分组标记相同 则继续寻找下行,否则该行为同组的最后一行。进行数据处理 133 // item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行 134 if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1 ) 135 { 136 continue ; 137 } 138 else if (index == table.Rows.Count - 1 ) 139 { 140 if (item[bjName].ToString() != prevDept) 141 { 142 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 143 rows.Add(index + rows.Count, row); 144 145 DataRow row2 = table.NewRow(); 146 foreach ( string columnName in numColumns) 147 { 148 row2[columnName] = item[columnName]; 149 } 150 rows.Add(index + rows.Count + 1 , row2); 151 } 152 else 153 { 154 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 155 rows.Add(index + rows.Count + 1 , row); 156 } 157 158 } 159 else 160 { 161 prevDept = item[bjName].ToString(); // 当前分组标记 162 DataRow row = CreateGroupRow(table, numColumns, NoOwn, index); 163 NoOwn = index; 164 rows.Add(index + rows.Count, row); 165 } 166 } 167 168 DataRow sumRow = CreateSumRow(table, rows, numColumns); 169 170 foreach ( int key in rows.Keys) 171 { 172 table.Rows.InsertAt(rows[key], key); 173 } 174 175 table.Rows.Add(sumRow); 176 return table; 177 } 178 179 /// <summary> 180 /// 生成总计行 181 /// </summary> 182 /// <param name="table"> DataTalbe </param> 183 /// <param name="rows"> 汇总行集合 </param> 184 /// <param name="numColumns"> 累计列 </param> 185 /// <returns> 总计行 </returns> 186 private static DataRow CreateSumRow(DataTable table, Dictionary < int , DataRow > rows, IList < string > numColumns) 187 { 188 DataRow sumRow = table.NewRow(); 189 sumRow[ 0 ] = " 合计 " ; 190 foreach ( string columnName in numColumns) 191 { 192 foreach ( int key in rows.Keys) 193 { 194 object count = sumRow[columnName]; // 汇总行 列值 195 // 如果值为null 或 "" 则默认为 0 196 if (count == null || count.ToString().Trim() == "" ) 197 { 198 count = 0 ; 199 } 200 sumRow[columnName] = decimal .Parse(count.ToString()) + decimal .Parse(rows[key][columnName].ToString()); // 累加 201 } 202 203 } 204 return sumRow; 205 } 206 207 private static IList < string > GetNumColumns(DataTable table) 208 { 209 IList < string > numColumns = new List < string > (); // 存放数字行 210 foreach (DataColumn column in table.Columns) 211 { 212 if (column.DataType == typeof (Decimal) || column.DataType == typeof (Int32) 213 || column.DataType == typeof (Int64) | column.DataType == typeof ( float ) 214 || column.DataType == typeof (Int64) | column.DataType == typeof (Double) 215 ) 216 { 217 numColumns.Add(column.ColumnName); 218 } 219 } 220 return numColumns; 221 } 222 /// <summary> 223 /// 将dataTable排序 224 /// </summary> 225 /// <param name="olDtable"> DataTable </param> 226 /// <param name="bjName"> 排序字段 </param> 227 /// <returns></returns> 228 public static DataTable TableSort(DataTable olDtable, string bjName) 229 { 230 DataTable table = olDtable.Clone(); 231 DataRow[] sortRows = olDtable.Select( null , bjName); 232 foreach (DataRow item in sortRows) 233 { 234 table.ImportRow(item); 235 } 236 return table; 237 } 238 /// <summary> 239 /// 生成汇总行 240 /// </summary> 241 /// <param name="table"> 分组表 </param> 242 /// <param name="numColumns"> 需要汇总的列 </param> 243 /// <param name="NoOwn"> 开始行 </param> 244 /// <param name="index"> 结束行 </param> 245 /// <returns> 汇总行 </returns> 246 private static DataRow CreateGroupRow(DataTable table, IList < string > numColumns, int startRowIndex, int endRowIndex) 247 { 248 DataRow row = table.NewRow(); // 汇总行 249 // 从同组项的第一行记录的位置 到 同组的最后一行 250 for ( int i = startRowIndex; i < endRowIndex + 1 ; i ++ ) 251 { 252 253 foreach ( string columnName in numColumns) 254 { 255 256 object count = row[columnName]; // 汇总行 列值 257 object tempt = table.Rows[i][columnName]; // 当前行 列值 258 // 如果值为null 或 "" 则默认为 0 259 if (count == null || count.ToString().Trim() == "" ) 260 { 261 count = 0 ; 262 } 263 if (tempt == null || tempt.ToString().Trim() == "" ) 264 { 265 tempt = 0 ; 266 } 267 row[columnName] = decimal .Parse(count.ToString()) + decimal .Parse(tempt.ToString()); // 累加 268 } 269 } 270 return row; 271 } 272 273 /// <summary> 274 /// 合并单元格 合并一行中的几列 275 /// </summary> 276 /// <param name="GridView1"> GridView对象 </param> 277 /// <param name="rows"> 行索引 </param> 278 /// <param name="sCol"> 开始列 </param> 279 /// <param name="eCol"> 结束列 </param> 280 public static void GroupRow(GridView gridView, int rows, int sCol, int eCol) 281 { 282 TableCell oldTc = gridView.Rows[rows].Cells[sCol]; 283 for ( int i = 1 ; i < eCol - sCol; i ++ ) 284 { 285 TableCell tc = gridView.Rows[rows].Cells[i + sCol];   // Cells[0]就是你要合并的列 286 tc.Visible = false ; 287 if (oldTc.ColumnSpan == 0 ) 288 { 289 oldTc.ColumnSpan = 1 ; 290 } 291 oldTc.ColumnSpan ++ ; 292 oldTc.VerticalAlign = VerticalAlign.Middle; 293 } 294 } 295 /// <summary> 296 /// 合并列 297 /// </summary> 298 /// <param name="gv"> gridview对象 </param> 299 /// <param name="cells"> 列索引 </param> 300 /// <param name="sRow"> 合并列开始位置 </param> 301 /// <param name="eRow"> 合并列结束位置 </param> 302 public static void GropCell(GridView gv, int cells, int sRow, int eRow) 303 { 304 TableCell tc = gv.Rows[sRow].Cells[cells]; 305 tc.RowSpan = eRow - sRow + 1 ; 306 for ( int i = sRow + 1 ; i <= eRow; i ++ ) 307 { 308 gv.Rows[i].Cells[cells].Visible = false ; 309 } 310 } 311 }
 

GridView中实现同行小计末行总计的报表

妙用GridView的RowCreated事件,可以实现报表中的小计和总计,减少对使用构造数据集合的依赖。现举一简单例子以便大家来探讨完善。

实现思路:1、整个报表的总计项,即第一行和最后一列的总计数量在SQL总计算;

2、每一型号则在创建Gridview时(RowCreated事件)实现;

protected void gvstatistics_RowCreated(object sender, GridViewRowEventArgs e) { string strrow = ""; string tempname = ""; if (e.Row.RowIndex >1 && this.gvstatistics.Rows.Count > 0) { tempname = gvstatistics.Rows[e.Row.RowIndex - 1].Cells[0].Text.Trim(); if (tempname != gvstatistics.Rows[e.Row.RowIndex -2].Cells[0].Text.Trim()) {//插入小结数据 DataTable dtdetail = getDetailStatistics(gvstatistics.Rows[e.Row.RowIndex - 2].Cells[0].Text.Trim());//获取数据函数 if (dtdetail.Rows.Count>0) { strrow = "</td></tr><tr><td>" + dtdetail.Rows[0][0].ToString() + "</td><td>" + dtdetail.Rows[0][1].ToString() + "</td>" + " <td>" + dtdetail.Rows[0][2].ToString() + "</td><td>" + dtdetail.Rows[0][3].ToString() + "</td>" + " <td>" + dtdetail.Rows[0][4].ToString() + "</td><td>" + dtdetail.Rows[0][5].ToString() + "</td>" + " <td>" + dtdetail.Rows[0][6].ToString() + "</td><td>" + dtdetail.Rows[0][7].ToString() + "</td>" + " <td>" + dtdetail.Rows[0][8].ToString() + "</td><td>" + dtdetail.Rows[0][9].ToString() + "</td>" + " <td>" + dtdetail.Rows[0][10].ToString() + "</td><td>" + dtdetail.Rows[0][11].ToString() + ""; gvstatistics.Rows[e.Row.RowIndex - 2].Cells[e.Row.Cells.Count - 1].Text += strrow; } } } }

这样就可以达到报表既有小计又有总计的效果,并且可以导出到Excel文件。

实现效果如下:

GridView1.ShowFooter 屬性是控制footer是否顯示的.默認值是false

如何在GridView的Footer内显示总计?

前台:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< asp:GridView ID = "GridView2" runat = "server" AutoGenerateColumns = "False"
OnRowDataBound = "GridView1_RowDataBound"
ShowFooter = "true" >
< Columns >
< asp:TemplateField >
< ItemTemplate >
< asp:Label ID = "labelfirst" runat = "server" Text='<%# Eval("first") %>'></ asp:Label >
</ ItemTemplate >
< FooterTemplate >
< asp:Label id = "labelAll" runat = "server" Text = "总计:" ></ asp:Label >
</ FooterTemplate >
</ asp:TemplateField >
</ Columns >
</ asp:GridView >

后台:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private int num = 0;
protected void GridView1_RowDataBound( object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView dr = e.Row.DataItem as DataRowView;
num += Convert.ToInt32(dr.Row[ "first" ]);
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
Label LabelAll = e.Row.FindControl( "labelAll" ) as Label;
if (LabelAll != null )
{
LabelAll.Text += num.ToString(); //"计算的总数,或者也可以单独计算";//
}
}
}

"first"是数据源的一个字段

 

  
  
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值