asp.net 利用NPOI导出Excel通用类

本文介绍了解决中文文件名保存Excel时出现乱码的问题,通过判断浏览器类型(火狐或IE)来采取不同的处理策略。同时提供了一个类库ATNPOIHelper.cs,用于利用NPOI实现导出Excel,并支持多表头、表头标题等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解决中文文件名保存Excel乱码问题,主要是判断火狐或者IE浏览器,然后做对应的判断处理,核心代码如下:

 


 
  1. System.Web.HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";

  2. //设置下载的Excel文件名\

  3. if (System.Web.HttpContext.Current.Request.ServerVariables["http_user_agent"].ToString().IndexOf("Firefox") != -1)

  4. {

  5. //火狐浏览器

  6. System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "=?UTF-8?B?" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fileName)) + "?="));

  7. }

  8. else

  9. {

  10. //IE等浏览器

  11. System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8)));

  12. }


 

废话不多说,直接上类库代码,ATNPOIHelper.cs:

 


 
  1. using System;

  2. using System.Linq;

  3. using System.Web;

  4. using System.IO;

  5. using NPOI;

  6. using NPOI.SS.Util;

  7. using NPOI.HSSF.Util;

  8. using NPOI.SS.UserModel;

  9. using NPOI.HSSF.UserModel;

  10. using System.Data;

  11. using System.Collections.Generic;

  12. using System.Text;

  13.  
  14. namespace AT.Utility.DotNetFile

  15. {

  16. /*

  17. 导出Excel包含的功能:

  18. 1.多表头导出最多支持到三行,表头格式说明

  19. 相邻父列头之间用’#’分隔,父列头与子列头用空格(’ ‘)分隔,相邻子列头用逗号分隔(‘,’)

  20. 两行:序号#分公司#组别#本日成功签约单数 预警,续约,流失,合计#累计成功签约单数 预警,续约,流失,合计#任务数#完成比例#排名

  21. 三行:等级#级别#上期结存 件数,重量,比例#本期调入 收购调入 件数,重量,比例#本期发出 车间投料 件数,重量,比例#本期发出 产品外销百分比 件数,重量,比例#平均值

  22. 三行时请注意:列头要重复

  23. 2.添加表头标题功能

  24. 3.添加序号功能

  25. 4.根据数据设置列宽

  26.  
  27. 缺陷:

  28. 数据内容不能合并列合并行

  29.  
  30. 改进思路:

  31. 添加一属性:设置要合并的列,为了实现多列合并可以这样设置{“列1,列2”,”列4”}

  32. */

  33. /// <summary>

  34. /// 利用NPOI实现导出Excel

  35. /// </summary>

  36. public class ATNPOIHelper

  37. {

  38.  
  39. #region 初始化

  40.  
  41. /// <summary>

  42. /// 声明 HSSFWorkbook 对象

  43. /// </summary>

  44. private static HSSFWorkbook _workbook;

  45.  
  46. /// <summary>

  47. /// 声明 HSSFSheet 对象

  48. /// </summary>

  49. private static HSSFSheet _sheet;

  50.  
  51. #endregion

  52.  
  53. #region Excel导出

  54.  
  55. /// <summary>

  56. /// Excel导出

  57. /// </summary>

  58. /// <param name="fileName">文件名称 如果为空或NULL,则默认“新建Excel.xls”</param>

  59. /// <param name="list"></param>

  60. /// <param name="ColMergeNum">合计:末行合计时,合并的列数</param>

  61. /// <param name="method">导出方式 1:WEB导出(默认)2:按文件路径导出</param>

  62. /// <param name="filePath">文件路径 如果WEB导出,则可以为空;如果按文件路径导出,则默认桌面路径</param>

  63. public static void Export(string fileName, IList<NPOIModel> list, int ColMergeNum, int method = 1, string filePath = null)

  64. {

  65. // 文件名称

  66. if (!string.IsNullOrEmpty(fileName))

  67. {

  68. if (fileName.IndexOf('.') == -1)

  69. {

  70. fileName += ".xls";

  71. }

  72. else

  73. {

  74. fileName = fileName.Substring(1, fileName.IndexOf('.')) + ".xls";

  75. }

  76. }

  77. else

  78. {

  79. fileName = "新建Excel.xls";

  80. }

  81. // 文件路径

  82. if (2 == method && string.IsNullOrEmpty(filePath))

  83. {

  84. filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

  85. }

  86. // 调用导出处理程序

  87. Export(list, ColMergeNum);

  88. // WEB导出

  89. if (1 == method)

  90. {

  91. System.Web.HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";

  92. //设置下载的Excel文件名\

  93. if (System.Web.HttpContext.Current.Request.ServerVariables["http_user_agent"].ToString().IndexOf("Firefox") != -1)

  94. {

  95. //火狐浏览器

  96. System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "=?UTF-8?B?" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fileName)) + "?="));

  97. }

  98. else

  99. {

  100. //IE等浏览器

  101. System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8)));

  102. }

  103. using (MemoryStream ms = new MemoryStream())

  104. {

  105. //将工作簿的内容放到内存流中

  106. _workbook.Write(ms);

  107. //将内存流转换成字节数组发送到客户端

  108. System.Web.HttpContext.Current.Response.BinaryWrite(ms.GetBuffer());

  109. System.Web.HttpContext.Current.Response.End();

  110. _sheet = null;

  111. _workbook = null;

  112. }

  113. }

  114. else if (2 == method)

  115. {

  116. using (FileStream fs = File.Open(filePath, FileMode.Append))

  117. {

  118. _workbook.Write(fs);

  119. _sheet = null;

  120. _workbook = null;

  121. }

  122. }

  123. }

  124.  
  125. /// <summary>

  126. /// 导出方法实现

  127. /// </summary>

  128. /// <param name="list"></param>

  129. private static void Export(IList<NPOIModel> list, int ColMergeNum)

  130. {

  131.  
  132. #region 变量声明

  133.  
  134. // 初始化

  135. _workbook = new HSSFWorkbook();

  136. // 声明 Row 对象

  137. IRow _row;

  138. // 声明 Cell 对象

  139. ICell _cell;

  140. // 总列数

  141. int cols = 0;

  142. // 总行数

  143. int rows = 0;

  144. // 行数计数器

  145. int rowIndex = 0;

  146. // 单元格值

  147. string drValue = null;

  148.  
  149. #endregion

  150.  
  151. foreach (NPOIModel model in list)

  152. {

  153. // 工作薄命名

  154. if (model.sheetName != null)

  155. _sheet = (HSSFSheet)_workbook.CreateSheet(model.sheetName);

  156. else

  157. _sheet = (HSSFSheet)_workbook.CreateSheet();

  158.  
  159. // 获取数据源

  160. DataTable dt = model.dataSource;

  161. // 初始化

  162. rowIndex = 0;

  163. // 获取总行数

  164. rows = GetRowCount(model.headerName);

  165. // 获取总列数

  166. cols = GetColCount(model.headerName);

  167.  
  168. //合计:合并表格末行N列,rows为表头行数,dt.Rows.Count为数据行数

  169. if (ColMergeNum > 1)

  170. {

  171. CellRangeAddress region_Merge = new CellRangeAddress(rows + dt.Rows.Count, rows + dt.Rows.Count, 0, ColMergeNum - 1);

  172. _sheet.AddMergedRegion(region_Merge);

  173. }

  174.  
  175. ICellStyle myBodyStyle = bodyStyle;

  176. ICellStyle myTitleStyle = titleStyle;

  177. ICellStyle myDateStyle = dateStyle;

  178. ICellStyle myBodyRightStyle = bodyRightStyle;

  179. // 循环行数

  180. foreach (DataRow row in dt.Rows)

  181. {

  182.  
  183. #region 新建表,填充表头,填充列头,样式

  184.  
  185. if (rowIndex == 65535 || rowIndex == 0)

  186. {

  187. if (rowIndex != 0)

  188. _sheet = (HSSFSheet)_workbook.CreateSheet();

  189.  
  190. // 构建行

  191. for (int i = 0; i < rows + model.isTitle; i++)

  192. {

  193. _row = _sheet.GetRow(i);

  194. // 创建行

  195. if (_row == null)

  196. _row = _sheet.CreateRow(i);

  197.  
  198. for (int j = 0; j < cols; j++)

  199. _row.CreateCell(j).CellStyle = myBodyStyle;

  200. }

  201.  
  202. // 如果存在表标题

  203. if (model.isTitle > 0)

  204. {

  205. // 获取行

  206. _row = _sheet.GetRow(0);

  207. // 合并单元格

  208. CellRangeAddress region = new CellRangeAddress(0, 0, 0, (cols - 1));

  209. _sheet.AddMergedRegion(region);

  210. // 填充值

  211. _row.CreateCell(0).SetCellValue(model.tableTitle);

  212. // 设置样式

  213. _row.GetCell(0).CellStyle = myTitleStyle;

  214. // 设置行高

  215. _row.HeightInPoints = 20;

  216. }

  217.  
  218. // 取得上一个实体

  219. NPOIHeader lastRow = null;

  220. IList<NPOIHeader> hList = GetHeaders(model.headerName, rows, model.isTitle);

  221. // 创建表头

  222. foreach (NPOIHeader m in hList)

  223. {

  224. var data = hList.Where(c => c.firstRow == m.firstRow && c.lastCol == m.firstCol - 1);

  225. if (data.Count() > 0)

  226. {

  227. lastRow = data.First();

  228. if (m.headerName == lastRow.headerName)

  229. m.firstCol = lastRow.firstCol;

  230. }

  231.  
  232. // 获取行

  233. _row = _sheet.GetRow(m.firstRow);

  234. // 合并单元格

  235. CellRangeAddress region = new CellRangeAddress(m.firstRow, m.lastRow, m.firstCol, m.lastCol);

  236.  
  237. _sheet.AddMergedRegion(region);

  238. // 填充值

  239. _row.CreateCell(m.firstCol).SetCellValue(m.headerName);

  240. }

  241. // 填充表头样式

  242. for (int i = 0; i < rows + model.isTitle; i++)

  243. {

  244. _row = _sheet.GetRow(i);

  245. for (int j = 0; j < cols; j++)

  246. {

  247. _row.GetCell(j).CellStyle = myBodyStyle;

  248. //设置列宽

  249. _sheet.SetColumnWidth(j, (model.colWidths[j] + 1) * 450);

  250. }

  251. }

  252.  
  253. rowIndex = (rows + model.isTitle);

  254. }

  255.  
  256. #endregion

  257.  
  258. #region 填充内容

  259.  
  260. // 构建列

  261. _row = _sheet.CreateRow(rowIndex);

  262. foreach (DataColumn column in dt.Columns)

  263. {

  264. // 添加序号列

  265. if (1 == model.isOrderby && column.Ordinal == 0)

  266. {

  267. _cell = _row.CreateCell(0);

  268. _cell.SetCellValue(rowIndex - rows);

  269. _cell.CellStyle = myBodyStyle;

  270. }

  271.  
  272. // 创建列

  273. _cell = _row.CreateCell(column.Ordinal + model.isOrderby);

  274.  
  275. // 获取值

  276. drValue = row[column].ToString();

  277.  
  278. switch (column.DataType.ToString())

  279. {

  280. case "System.String"://字符串类型

  281. _cell.SetCellValue(drValue);

  282. _cell.CellStyle = myBodyStyle;

  283. break;

  284. case "System.DateTime"://日期类型

  285. DateTime dateV;

  286. DateTime.TryParse(drValue, out dateV);

  287. _cell.SetCellValue(dateV);

  288.  
  289. _cell.CellStyle = myDateStyle;//格式化显示

  290. break;

  291. case "System.Boolean"://布尔型

  292. bool boolV = false;

  293. bool.TryParse(drValue, out boolV);

  294. _cell.SetCellValue(boolV);

  295. _cell.CellStyle = myBodyStyle;

  296. break;

  297. case "System.Int16"://整型

  298. case "System.Int32":

  299. case "System.Int64":

  300. case "System.Byte":

  301. int intV = 0;

  302. int.TryParse(drValue, out intV);

  303. _cell.SetCellValue(intV);

  304. _cell.CellStyle = myBodyRightStyle;

  305. break;

  306. case "System.Decimal"://浮点型

  307. case "System.Double":

  308. double doubV = 0;

  309. double.TryParse(drValue, out doubV);

  310. _cell.SetCellValue(doubV.ToString("f2"));

  311. _cell.CellStyle = myBodyRightStyle;

  312. break;

  313. case "System.DBNull"://空值处理

  314. _cell.SetCellValue("");

  315. break;

  316. default:

  317. _cell.SetCellValue("");

  318. break;

  319. }

  320.  
  321. }

  322.  
  323. #endregion

  324.  
  325. rowIndex++;

  326. }

  327. }

  328. }

  329.  
  330. #region 辅助方法

  331.  
  332. /// <summary>

  333. /// 表头解析

  334. /// </summary>

  335. /// <remarks>

  336. /// </remarks>

  337. /// <param name="header">表头</param>

  338. /// <param name="rows">总行数</param>

  339. /// <param name="addRows">外加行</param>

  340. /// <param name="addCols">外加列</param>

  341. /// <returns></returns>

  342. private static IList<NPOIHeader> GetHeaders(string header, int rows, int addRows)

  343. {

  344. // 临时表头数组

  345. string[] tempHeader;

  346. string[] tempHeader2;

  347. // 所跨列数

  348. int colSpan = 0;

  349. // 所跨行数

  350. int rowSpan = 0;

  351. // 单元格对象

  352. NPOIHeader model = null;

  353. // 行数计数器

  354. int rowIndex = 0;

  355. // 列数计数器

  356. int colIndex = 0;

  357. //

  358. IList<NPOIHeader> list = new List<NPOIHeader>();

  359. // 初步解析

  360. string[] headers = header.Split(new string[] { "#" }, StringSplitOptions.RemoveEmptyEntries);

  361. // 表头遍历

  362. for (int i = 0; i < headers.Length; i++)

  363. {

  364. // 行数计数器清零

  365. rowIndex = 0;

  366. // 列数计数器清零

  367. colIndex = 0;

  368. // 获取所跨行数

  369. rowSpan = GetRowSpan(headers[i], rows);

  370. // 获取所跨列数

  371. colSpan = GetColSpan(headers[i]);

  372.  
  373. // 如果所跨行数与总行数相等,则不考虑是否合并单元格问题

  374. if (rows == rowSpan)

  375. {

  376. colIndex = GetMaxCol(list);

  377. model = new NPOIHeader(headers[i],

  378. addRows,

  379. (rowSpan - 1 + addRows),

  380. colIndex,

  381. (colSpan - 1 + colIndex),

  382. addRows);

  383. list.Add(model);

  384. rowIndex += (rowSpan - 1) + addRows;

  385. }

  386. else

  387. {

  388. // 列索引

  389. colIndex = GetMaxCol(list);

  390. // 如果所跨行数不相等,则考虑是否包含多行

  391. tempHeader = headers[i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

  392. for (int j = 0; j < tempHeader.Length; j++)

  393. {

  394.  
  395. // 如果总行数=数组长度

  396. if (1 == GetColSpan(tempHeader[j]))

  397. {

  398. if (j == tempHeader.Length - 1 && tempHeader.Length < rows)

  399. {

  400. model = new NPOIHeader(tempHeader[j],

  401. (j + addRows),

  402. (j + addRows) + (rows - tempHeader.Length),

  403. colIndex,

  404. (colIndex + colSpan - 1),

  405. addRows);

  406. list.Add(model);

  407. }

  408. else

  409. {

  410. model = new NPOIHeader(tempHeader[j],

  411. (j + addRows),

  412. (j + addRows),

  413. colIndex,

  414. (colIndex + colSpan - 1),

  415. addRows);

  416. list.Add(model);

  417. }

  418. }

  419. else

  420. {

  421. // 如果所跨列数不相等,则考虑是否包含多列

  422. tempHeader2 = tempHeader[j].Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);

  423. for (int m = 0; m < tempHeader2.Length; m++)

  424. {

  425. // 列索引

  426. colIndex = GetMaxCol(list) - colSpan + m;

  427. if (j == tempHeader.Length - 1 && tempHeader.Length < rows)

  428. {

  429. model = new NPOIHeader(tempHeader2[m],

  430. (j + addRows),

  431. (j + addRows) + (rows - tempHeader.Length),

  432. colIndex,

  433. colIndex,

  434. addRows);

  435. list.Add(model);

  436. }

  437. else

  438. {

  439. model = new NPOIHeader(tempHeader2[m],

  440. (j + addRows),

  441. (j + addRows),

  442. colIndex,

  443. colIndex,

  444. addRows);

  445. list.Add(model);

  446. }

  447. }

  448. }

  449. rowIndex += j + addRows;

  450. }

  451. }

  452. }

  453. return list;

  454. }

  455.  
  456. /// <summary>

  457. /// 获取最大列

  458. /// </summary>

  459. /// <param name="list"></param>

  460. /// <returns></returns>

  461. private static int GetMaxCol(IList<NPOIHeader> list)

  462. {

  463. int maxCol = 0;

  464. if (list.Count > 0)

  465. {

  466. foreach (NPOIHeader model in list)

  467. {

  468. if (maxCol < model.lastCol)

  469. maxCol = model.lastCol;

  470. }

  471. maxCol += 1;

  472. }

  473.  
  474. return maxCol;

  475. }

  476.  
  477. /// <summary>

  478. /// 获取表头行数

  479. /// </summary>

  480. /// <param name="newHeaders">表头文字</param>

  481. /// <returns></returns>

  482. private static int GetRowCount(string newHeaders)

  483. {

  484. string[] ColumnNames = newHeaders.Split(new char[] { '@' });

  485. int Count = 0;

  486. if (ColumnNames.Length <= 1)

  487. ColumnNames = newHeaders.Split(new char[] { '#' });

  488. foreach (string name in ColumnNames)

  489. {

  490. int TempCount = name.Split(new char[] { ' ' }).Length;

  491. if (TempCount > Count)

  492. Count = TempCount;

  493. }

  494. return Count;

  495. }

  496.  
  497. /// <summary>

  498. /// 获取表头列数

  499. /// </summary>

  500. /// <param name="newHeaders">表头文字</param>

  501. /// <returns></returns>

  502. private static int GetColCount(string newHeaders)

  503. {

  504. string[] ColumnNames = newHeaders.Split(new char[] { '@' });

  505. int Count = 0;

  506. if (ColumnNames.Length <= 1)

  507. ColumnNames = newHeaders.Split(new char[] { '#' });

  508. Count = ColumnNames.Length;

  509. foreach (string name in ColumnNames)

  510. {

  511. int TempCount = name.Split(new char[] { ',' }).Length;

  512. if (TempCount > 1)

  513. Count += TempCount - 1;

  514. }

  515. return Count;

  516. }

  517.  
  518. /// <summary>

  519. /// 列头跨列数

  520. /// </summary>

  521. /// <remarks>

  522. /// </remarks>

  523. /// <param name="newHeaders">表头文字</param>

  524. /// <returns></returns>

  525. private static int GetColSpan(string newHeaders)

  526. {

  527. return newHeaders.Split(',').Count();

  528. }

  529.  
  530. /// <summary>

  531. /// 列头跨行数

  532. /// </summary>

  533. /// <remarks>

  534. /// </remarks>

  535. /// <param name="newHeaders">列头文本</param>

  536. /// <param name="rows">表头总行数</param>

  537. /// <returns></returns>

  538. private static int GetRowSpan(string newHeaders, int rows)

  539. {

  540. int Count = newHeaders.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Length;

  541. // 如果总行数与当前表头所拥有行数相等

  542. if (rows == Count)

  543. Count = 1;

  544. else if (Count < rows)

  545. Count = 1 + (rows - Count);

  546. else

  547. throw new Exception("表头格式不正确!");

  548. return Count;

  549. }

  550.  
  551. #endregion

  552.  
  553. #region 单元格样式

  554.  
  555. /// <summary>

  556. /// 数据单元格样式

  557. /// </summary>

  558. private static ICellStyle bodyStyle

  559. {

  560. get

  561. {

  562. ICellStyle style = _workbook.CreateCellStyle();

  563. style.Alignment = HorizontalAlignment.CENTER; //居中

  564. style.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中

  565. style.WrapText = true;//自动换行

  566. // 边框

  567. style.BorderBottom = BorderStyle.THIN;

  568. style.BorderLeft = BorderStyle.THIN;

  569. style.BorderRight = BorderStyle.THIN;

  570. style.BorderTop = BorderStyle.THIN;

  571. // 字体

  572. //IFont font = _workbook.CreateFont();

  573. //font.FontHeightInPoints = 10;

  574. //font.FontName = "宋体";

  575. //style.SetFont(font);

  576.  
  577. return style;

  578. }

  579. }

  580.  
  581. /// <summary>

  582. /// 数据单元格样式

  583. /// </summary>

  584. private static ICellStyle bodyRightStyle

  585. {

  586. get

  587. {

  588. ICellStyle style = _workbook.CreateCellStyle();

  589. style.Alignment = HorizontalAlignment.RIGHT; //居中

  590. style.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中

  591. style.WrapText = true;//自动换行

  592. // 边框

  593. style.BorderBottom = BorderStyle.THIN;

  594. style.BorderLeft = BorderStyle.THIN;

  595. style.BorderRight = BorderStyle.THIN;

  596. style.BorderTop = BorderStyle.THIN;

  597. // 字体

  598. //IFont font = _workbook.CreateFont();

  599. //font.FontHeightInPoints = 10;

  600. //font.FontName = "宋体";

  601. //style.SetFont(font);

  602.  
  603. return style;

  604. }

  605. }

  606.  
  607. /// <summary>

  608. /// 标题单元格样式

  609. /// </summary>

  610. private static ICellStyle titleStyle

  611. {

  612. get

  613. {

  614. ICellStyle style = _workbook.CreateCellStyle();

  615. style.Alignment = HorizontalAlignment.CENTER; //居中

  616. style.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中

  617. style.WrapText = true;//自动换行

  618.  
  619. //IFont font = _workbook.CreateFont();

  620. //font.FontHeightInPoints = 14;

  621. //font.FontName = "宋体";

  622. //font.Boldweight = (short)FontBoldWeight.BOLD;

  623. //style.SetFont(font);

  624.  
  625. return style;

  626. }

  627. }

  628.  
  629. /// <summary>

  630. /// 日期单元格样式

  631. /// </summary>

  632. private static ICellStyle dateStyle

  633. {

  634. get

  635. {

  636. ICellStyle style = _workbook.CreateCellStyle();

  637. style.Alignment = HorizontalAlignment.CENTER; //居中

  638. style.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中

  639. style.WrapText = true;//自动换行

  640. // 边框

  641. style.BorderBottom = BorderStyle.THIN;

  642. style.BorderLeft = BorderStyle.THIN;

  643. style.BorderRight = BorderStyle.THIN;

  644. style.BorderTop = BorderStyle.THIN;

  645. // 字体

  646. //IFont font = _workbook.CreateFont();

  647. //font.FontHeightInPoints = 10;

  648. //font.FontName = "宋体";

  649. //style.SetFont(font);

  650.  
  651. IDataFormat format = _workbook.CreateDataFormat();

  652. style.DataFormat = format.GetFormat("yyyy-MM-dd");

  653. return style;

  654. }

  655. }

  656.  
  657. #endregion

  658.  
  659. #endregion

  660. }

  661.  
  662. /// <summary>

  663. /// 实体类

  664. /// </summary>

  665. public class NPOIModel

  666. {

  667. /// <summary>

  668. /// 数据源

  669. /// </summary>

  670. public DataTable dataSource { get; private set; }

  671. /// <summary>

  672. /// 要导出的数据列数组

  673. /// </summary>

  674. public string[] fileds { get; private set; }

  675. /// <summary>

  676. /// 工作薄名称数组

  677. /// </summary>

  678. public string sheetName { get; private set; }

  679. /// <summary>

  680. /// 表标题

  681. /// </summary>

  682. public string tableTitle { get; private set; }

  683. /// <summary>

  684. /// 表标题是否存在 1:存在 0:不存在

  685. /// </summary>

  686. public int isTitle { get; private set; }

  687. /// <summary>

  688. /// 是否添加序号

  689. /// </summary>

  690. public int isOrderby { get; private set; }

  691. /// <summary>

  692. /// 表头

  693. /// </summary>

  694. public string headerName { get; private set; }

  695. /// <summary>

  696. /// 取得列宽

  697. /// </summary>

  698. public int[] colWidths { get; private set; }

  699. /// <summary>

  700. /// 构造函数

  701. /// </summary>

  702. /// <remarks>

  703. /// </remarks>

  704. /// <param name="dataSource">数据来源 DataTable</param>

  705. /// <param name="filed">要导出的字段,如果为空或NULL,则默认全部</param>

  706. /// <param name="sheetName">工作薄名称</param>

  707. /// <param name="headerName">表头名称 如果为空或NULL,则默认数据列字段

  708. /// 相邻父列头之间用'#'分隔,父列头与子列头用空格(' ')分隔,相邻子列头用逗号分隔(',')

  709. /// 两行:序号#分公司#组别#本日成功签约单数 预警,续约,流失,合计#累计成功签约单数 预警,续约,流失,合计#任务数#完成比例#排名

  710. /// 三行:等级#级别#上期结存 件数,重量,比例#本期调入 收购调入 件数,重量,比例#本期发出 车间投料 件数,重量,比例#本期发出 产品外销百分比 件数,重量,比例#平均值

  711. /// 三行时请注意:列头要重复

  712. /// </param>

  713. /// <param name="tableTitle">表标题</param>

  714. /// <param name="isOrderby">是否添加序号 0:不添加 1:添加</param>

  715. public NPOIModel(DataTable dataSource, string filed, string sheetName, string headerName, string tableTitle = null, int isOrderby = 0)

  716. {

  717. if (!string.IsNullOrEmpty(filed))

  718. {

  719. this.fileds = filed.ToUpper().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

  720.  
  721. // 移除多余数据列

  722. for (int i = dataSource.Columns.Count - 1; i >= 0; i--)

  723. {

  724. DataColumn dc = dataSource.Columns[i];

  725. if (!this.fileds.Contains(dataSource.Columns[i].Caption.ToUpper()))

  726. {

  727. dataSource.Columns.Remove(dataSource.Columns[i]);

  728. }

  729. }

  730.  
  731. // 列索引

  732. int colIndex = 0;

  733. // 循环排序

  734. for (int i = 0; i < dataSource.Columns.Count; i++)

  735. {

  736. // 获取索引

  737. colIndex = GetColIndex(dataSource.Columns[i].Caption.ToUpper());

  738. // 设置下标

  739. dataSource.Columns[i].SetOrdinal(colIndex);

  740. }

  741. }

  742. else

  743. {

  744. this.fileds = new string[dataSource.Columns.Count];

  745. for (int i = 0; i < dataSource.Columns.Count; i++)

  746. {

  747. this.fileds[i] = dataSource.Columns[i].ColumnName;

  748. }

  749. }

  750. this.dataSource = dataSource;

  751.  
  752. if (!string.IsNullOrEmpty(sheetName))

  753. {

  754. this.sheetName = sheetName;

  755. }

  756. if (!string.IsNullOrEmpty(headerName))

  757. {

  758. this.headerName = headerName;

  759. }

  760. else

  761. {

  762. this.headerName = string.Join("#", this.fileds);

  763. }

  764. if (!string.IsNullOrEmpty(tableTitle))

  765. {

  766. this.tableTitle = tableTitle;

  767. this.isTitle = 1;

  768. }

  769. // 取得数据列宽 数据列宽可以和表头列宽比较,采取最长宽度

  770. colWidths = new int[this.dataSource.Columns.Count];

  771. foreach (DataColumn item in this.dataSource.Columns)

  772. {

  773. colWidths[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;

  774. }

  775. // 循环比较最大宽度

  776. for (int i = 0; i < this.dataSource.Rows.Count; i++)

  777. {

  778. for (int j = 0; j < this.dataSource.Columns.Count; j++)

  779. {

  780. int intTemp = Encoding.GetEncoding(936).GetBytes(this.dataSource.Rows[i][j].ToString()).Length;

  781. if (intTemp > colWidths[j])

  782. {

  783. colWidths[j] = intTemp;

  784. }

  785. }

  786. }

  787. if (isOrderby > 0)

  788. {

  789. this.isOrderby = isOrderby;

  790. this.headerName = "序号#" + this.headerName;

  791. }

  792. }

  793.  
  794. /// <summary>

  795. /// 获取列名下标

  796. /// </summary>

  797. /// <param name="colName">列名称</param>

  798. /// <returns></returns>

  799. private int GetColIndex(string colName)

  800. {

  801. for (int i = 0; i < this.fileds.Length; i++)

  802. {

  803. if (colName == this.fileds[i])

  804. return i;

  805. }

  806. return 0;

  807. }

  808. }

  809.  
  810. /// <summary>

  811. /// 表头构建类

  812. /// </summary>

  813. public class NPOIHeader

  814. {

  815. /// <summary>

  816. /// 表头

  817. /// </summary>

  818. public string headerName { get; set; }

  819. /// <summary>

  820. /// 起始行

  821. /// </summary>

  822. public int firstRow { get; set; }

  823. /// <summary>

  824. /// 结束行

  825. /// </summary>

  826. public int lastRow { get; set; }

  827. /// <summary>

  828. /// 起始列

  829. /// </summary>

  830. public int firstCol { get; set; }

  831. /// <summary>

  832. /// 结束列

  833. /// </summary>

  834. public int lastCol { get; set; }

  835. /// <summary>

  836. /// 是否跨行

  837. /// </summary>

  838. public int isRowSpan { get; private set; }

  839. /// <summary>

  840. /// 是否跨列

  841. /// </summary>

  842. public int isColSpan { get; private set; }

  843. /// <summary>

  844. /// 外加行

  845. /// </summary>

  846. public int rows { get; set; }

  847.  
  848. public NPOIHeader() { }

  849. /// <summary>

  850. /// 构造函数

  851. /// </summary>

  852. /// <param name="headerName">表头</param>

  853. /// <param name="firstRow">起始行</param>

  854. /// <param name="lastRow">结束行</param>

  855. /// <param name="firstCol">起始列</param>

  856. /// <param name="lastCol">结束列</param>

  857. /// <param name="rows">外加行</param>

  858. /// <param name="cols">外加列</param>

  859. public NPOIHeader(string headerName, int firstRow, int lastRow, int firstCol, int lastCol, int rows = 0)

  860. {

  861. this.headerName = headerName;

  862. this.firstRow = firstRow;

  863. this.lastRow = lastRow;

  864. this.firstCol = firstCol;

  865. this.lastCol = lastCol;

  866. // 是否跨行判断

  867. if (firstRow != lastRow)

  868. isRowSpan = 1;

  869. if (firstCol != lastCol)

  870. isColSpan = 1;

  871.  
  872. this.rows = rows;

  873. }

  874. }

  875. }

 

3、导出代码示例如下:

 


 
  1. /// <summary>

  2. /// 导出测点列表表格

  3. /// </summary>

  4. [HttpGet]

  5. [AllowAnonymous]

  6. public void ExportMeasurePointData(string TreeID, string TreeType)

  7. {

  8. DataTable dtResult = new DataTable();

  9. DataTable dtExcel = new DataTable();

  10. try

  11. {

  12. string sql = string.Format("EXEC P_GET_ZXJG_TagList '{0}','{1}'", TreeID, TreeType);

  13. dtResult = QuerySQL.GetDataTable(sql);

  14. dtExcel = dtResult.Copy();

  15. dtExcel.Columns.Add("xuhao", typeof(string));

  16. dtExcel.Columns.Add("StrValueTime", typeof(string));

  17. dtExcel.Columns["xuhao"].SetOrdinal(0);

  18. dtExcel.Columns["StrValueTime"].SetOrdinal(2);

  19. for (int i = 0; i < dtResult.Rows.Count; i++)

  20. {

  21. dtExcel.Rows[i]["xuhao"] = (i + 1).ToString();

  22. dtExcel.Rows[i]["StrValueTime"] = Convert.ToDateTime(dtResult.Rows[i]["F_ValueTime"]).ToString("yyyy-MM-dd HH:mm:ss");

  23. }

  24. List<NPOIModel> list = new List<NPOIModel>();

  25. list.Add(new NPOIModel(dtExcel, "xuhao;F_Description;StrValueTime;F_Value;F_Unit;F_AlmLow;F_AlmUp", "sheet", "序号#监测点#采集时间#当前数值#工程单位#报警下限#报警上限"));

  26. ATNPOIHelper.Export("测点列表", list, 0);

  27. }

  28. catch (Exception ex)

  29. {

  30.  
  31. }

  32. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值