FineUI小技巧(7)多表头表格导出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

在 ASPX 中,我们通过 GroupField 列来定义多表头,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
< f:Grid  ID="Grid1" Title="表格" EnableCollapse="true" ShowBorder="true" ShowHeader="true" Width="800px"
     runat="server" DataKeyNames="Id,Name">
     < Columns >
         < f:TemplateField  ColumnID="tfNumber" Width="60px">
             < ItemTemplate >
                 < span  id="spanNumber" runat="server"><%# Container.DataItemIndex + 1 %></ span >
             </ ItemTemplate >
         </ f:TemplateField >
         < f:GroupField  EnableLock="true" HeaderText="分组一" TextAlign="Center">
             < Columns >
                 < f:BoundField  Width="100px" DataField="Name" DataFormatString="{0}" HeaderText="姓名" />
                 < f:TemplateField  ColumnID="tfGender" Width="80px" HeaderText="性别" TextAlign="Center">
                     < ItemTemplate >
                         < asp:Label  ID="labGender" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></ asp:Label >
                     </ ItemTemplate >
                 </ f:TemplateField >
                 < f:GroupField  EnableLock="true" HeaderText="考试成绩" TextAlign="Center">
                     < Columns >
                         < f:BoundField  EnableLock="true" Width="80px" DataField="ChineseScore" SortField="ChineseScore" HeaderText="语文成绩"
                             TextAlign="Center" />
                         < f:BoundField  EnableLock="true" Width="80px" DataField="MathScore" SortField="MathScore" HeaderText="数学成绩"
                             TextAlign="Center" />
                         < f:BoundField  EnableLock="true" Width="80px" DataField="TotalScore" SortField="TotalScore" HeaderText="总成绩"
                             TextAlign="Center" />
                     </ Columns >
                 </ f:GroupField >
             </ Columns >
         </ f:GroupField >
         < f:BoundField  ExpandUnusedSpace="True" DataField="Major" HeaderText="所学专业" />
         < f:BoundField  Width="100px" DataField="LogTime" DataFormatString="{0:yy-MM-dd}" HeaderText="注册日期" />
     </ Columns >
</ f:Grid >

这是一个树状的结构,通过 GroupField 的 Columns 集合来定义子列,从而实现多表头的效果:


/// <summary>
/// 处理多表头的类
/// </summary>
public  class  MultiHeaderTable
{
     // 包含 rowspan,colspan 的多表头,方便生成 HTML 的 table 标签
     public  List<List< object []>> MultiTable =  new  List<List< object []>>();
     // 最终渲染的列数组
     public  List<GridColumn> Columns =  new  List<GridColumn>();
 
 
     public  void  ResolveMultiHeaderTable(GridColumnCollection columns)
     {
         List< object []> row =  new  List< object []>();
         foreach  (GridColumn column  in  columns)
         {
             object [] cell =  new  object [4];
             cell[0] = 1;     // rowspan
             cell[1] = 1;     // colspan
             cell[2] = column;
             cell[3] =  null ;
 
             row.Add(cell);
         }
 
         ResolveMultiTable(row, 0);
 
         ResolveColumns(row);
     }
 
     private  void  ResolveColumns(List< object []> row)
     {
         foreach  ( object [] cell  in  row)
         {
             GroupField groupField = cell[2]  as  GroupField;
             if  (groupField !=  null  && groupField.Columns.Count > 0)
             {
                 List< object []> subrow =  new  List< object []>();
                 foreach  (GridColumn column  in  groupField.Columns)
                 {
                     subrow.Add( new  object []
                     {
                         1,
                         1,
                         column,
                         groupField
                     });
                 }
 
                 ResolveColumns(subrow);
             }
             else
             {
                 Columns.Add(cell[2]  as  GridColumn);
             }
         }
 
     }
 
     private  void  ResolveMultiTable(List< object []> row,  int  level)
     {
         List< object []> nextrow =  new  List< object []>();
 
         foreach  ( object [] cell  in  row)
         {
             GroupField groupField = cell[2]  as  GroupField;
             if  (groupField !=  null  && groupField.Columns.Count > 0)
             {
                 // 如果当前列包含子列,则更改当前列的 colspan,以及增加父列(向上递归)的colspan
                 cell[1] = Convert.ToInt32(groupField.Columns.Count);
                 PlusColspan(level - 1, cell[3]  as  GridColumn,groupField.Columns.Count - 1);
 
                 foreach  (GridColumn column  in  groupField.Columns)
                 {
                     nextrow.Add( new  object []
                     {
                         1,
                         1,
                         column,
                         groupField
                     });
                 }
             }
         }
 
         MultiTable.Add(row);
 
         // 如果当前下一行,则增加上一行(向上递归)中没有子列的列的 rowspan
         if  (nextrow.Count > 0)
         {
             PlusRowspan(level);
 
             ResolveMultiTable(nextrow, level + 1);
         }
     }
 
     private  void  PlusRowspan( int  level)
     {
         if  (level < 0)
         {
             return ;
         }
 
         foreach  ( object [] cells  in  MultiTable[level])
         {
             GroupField groupField = cells[2]  as  GroupField;
             if  (groupField !=  null  && groupField.Columns.Count > 0)
             {
                 // ...
             }
             else
             {
                 cells[0] = Convert.ToInt32(cells[0]) + 1;
             }
         }
 
         PlusRowspan(level - 1);
     }
 
     private  void  PlusColspan( int  level, GridColumn parent,  int  plusCount)
     {
         if  (level < 0)
         {
             return ;
         }
 
         foreach  ( object [] cells  in  MultiTable[level])
         {
             GridColumn column = cells[2]  as  GridColumn;
             if  (column == parent)
             {
                 cells[1] = Convert.ToInt32(cells[1]) + plusCount;
 
                 PlusColspan(level - 1, cells[3]  as  GridColumn, plusCount);
             }
         }
     }
 
}

 

其实主要的逻辑就上面提到的两点,然后需要好几个递归函数来一块完成任务。

 

导出的代码调用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
protected  void  Button1_Click( object  sender, EventArgs e)
{
     Response.ClearContent();
     Response.AddHeader( "content-disposition" "attachment; filename=myexcel.xls" );
     Response.ContentType =  "application/excel" ;
     Response.ContentEncoding = System.Text.Encoding.UTF8;
     Response.Write(GetGridTableHtml(Grid1));
     Response.End();
}
 
private  string  GetGridTableHtml(Grid grid)
{
     StringBuilder sb =  new  StringBuilder();
 
     MultiHeaderTable mht =  new  MultiHeaderTable();
     mht.ResolveMultiHeaderTable(Grid1.Columns);
 
 
     sb.Append( "<meta http-equiv=\"content-type\" content=\"application/excel; charset=UTF-8\"/>" );
 
 
     sb.Append( "<table cellspacing=\"0\" rules=\"all\" border=\"1\" style=\"border-collapse:collapse;\">" );
 
     foreach  (List< object []> rows  in  mht.MultiTable)
     {
         sb.Append( "<tr>" );
         foreach  ( object [] cell  in  rows)
         {
             int  rowspan = Convert.ToInt32(cell[0]);
             int  colspan = Convert.ToInt32(cell[1]);
             GridColumn column = cell[2]  as  GridColumn;
 
             sb.AppendFormat( "<th{0}{1}{2}>{3}</th>" ,
                 rowspan != 1 ?  " rowspan=\""  + rowspan +  "\""  "" ,
                 colspan != 1 ?  " colspan=\""  + colspan +  "\""  "" ,
                 colspan != 1 ?  " style=\"text-align:center;\""  "" ,
                 column.HeaderText);
         }
         sb.Append( "</tr>" );
     }
 
 
     foreach  (GridRow row  in  grid.Rows)
     {
         sb.Append( "<tr>" );
 
         foreach  (GridColumn column  in  mht.Columns)
         {
             string  html = row.Values[column.ColumnIndex].ToString();
 
             if  (column.ColumnID ==  "tfNumber" )
             {
                 html = (row.FindControl( "spanNumber" as  System.Web.UI.HtmlControls.HtmlGenericControl).InnerText;
             }
             else  if  (column.ColumnID ==  "tfGender" )
             {
                 html = (row.FindControl( "labGender" as  AspNet.Label).Text;
             }
 
 
             sb.AppendFormat( "<td>{0}</td>" , html);
         }
 
         sb.Append( "</tr>" );
     }
 
     sb.Append( "</table>" );
 
     return  sb.ToString();
}

最终导出的文件结构如下所示:

转载自

Sanshi(Asp.Net控件)

转载地址:http://www.cnblogs.com/sanshi/p/4104411.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值