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 列来定义多表头,如下所示:
这是一个树状的结构,通过 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();
}
|
最终导出的文件结构如下所示:
转载自