Excel导出---NPOI和MS两种方式
Posted 好好学习V天天向上
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Excel导出---NPOI和MS两种方式相关的知识,希望对你有一定的参考价值。
NPOI方式(NPOI开源免费):
1 /// <summary> 2 /// 导出Excel文件 3 /// </summary> 4 /// <param name="sheetName"></param> 5 /// <param name="titles">EXCEL表格表头</param> 6 /// <param name="rowSpan">要合并的行数</param> 7 /// <param name="cols">需要合并的左侧列</param> 8 /// <param name="dt">数据表</param> 9 /// <param name="path">保存路径</param> 10 /// <param name="IsSpan">是否需要合并</param> 11 /// <param name="IsFormula">是否需要导出公式</param> 12 public static bool ExportExcelNPOI(string sheetName, List<Tuple<string, int, Type>> titles, int rowSpan, int cols, System.Data.DataTable dt, string path, bool IsSpan = true,bool IsFormula=false) 13 { 14 try 15 { 16 IWorkbook wb = new XSSFWorkbook(); 17 ISheet sheet = wb.CreateSheet(sheetName); //创建工作表 18 IRow row_Title = sheet.CreateRow(0); //创建列头行 19 row_Title.HeightInPoints = 19.5F; //设置列头行高 20 21 IDataFormat dataformat = wb.CreateDataFormat();//用于格式化单元格内容 22 23 #region 设置列头单元格样式 24 ICellStyle cs_Title = wb.CreateCellStyle(); //创建字符串列头样式 25 cs_Title.Alignment = HorizontalAlignment.Center; //水平居中 26 cs_Title.VerticalAlignment = VerticalAlignment.Center; //垂直居中 27 IFont cs_Title_Font = wb.CreateFont(); //创建字体 28 cs_Title_Font.IsBold = true; //字体加粗 29 cs_Title_Font.FontHeightInPoints = 12; //字体大小 30 cs_Title.SetFont(cs_Title_Font); //将字体绑定到样式 31 32 ICellStyle cs_Date_Title = wb.CreateCellStyle(); 33 cs_Date_Title.CloneStyleFrom(cs_Title); 34 cs_Date_Title.DataFormat = dataformat.GetFormat("yyyy/M/d"); 35 #endregion 36 37 #region 填充列头 38 ICell cell_Title; 39 int cnt = 0; 40 foreach (var title in titles) 41 { 42 cell_Title = row_Title.CreateCell(cnt); //创建单元格 43 44 if (title.Item3 == typeof(DateTime)) 45 { 46 cell_Title.CellStyle = cs_Date_Title; //将样式绑定到单元格 47 cell_Title.SetCellValue(DateTime.Parse(title.Item1)); 48 } 49 else if (title.Item3 == typeof(int)) 50 { 51 cell_Title.CellStyle = cs_Title; //将样式绑定到单元格 52 cell_Title.SetCellValue(int.Parse(title.Item1)); 53 } 54 else 55 { 56 cell_Title.CellStyle = cs_Title; 57 cell_Title.SetCellValue(title.Item1); 58 } 59 60 sheet.SetColumnWidth(cnt, title.Item2);//设置列宽 61 62 cnt++; 63 } 64 #endregion 65 66 #region 填充数据 67 List<int> valueTypeColNo = new List<int>();//除日期列和总计列之外其它值类型列的列号 68 if (dt.Columns.Contains("Inventory")) 69 { 70 valueTypeColNo.Add(dt.Columns["Inventory"].Ordinal); 71 } 72 73 int indexNo = 1;//序号 74 int dataRowNum = 0;//DataTalbe数据行行号 75 int excelRowNum = 0;//Excel数据行行号 76 #region 计算公式列名 77 string startCol, endCol; 78 string inventoryCol, demandCol, commitCol; 79 #endregion 80 foreach (DataRow row in dt.Rows) 81 { 82 excelRowNum = dataRowNum + 1; 83 84 #region 设置内容单元格样式 85 ICellStyle cs_Content = wb.CreateCellStyle(); //创建单元格样式 86 cs_Content.Alignment = HorizontalAlignment.Center; //水平居中 87 cs_Content.VerticalAlignment = VerticalAlignment.Center; //垂直居中 88 89 90 ICellStyle cs_Content_Date = wb.CreateCellStyle(); 91 cs_Content_Date.CloneStyleFrom(cs_Content); 92 cs_Content_Date.DataFormat = dataformat.GetFormat("yyyy/M/d"); 93 #endregion 94 95 IRow row_Content = sheet.CreateRow(excelRowNum); //创建数据行 96 row_Content.HeightInPoints = 16; 97 98 #region 设置序号 99 ICell cell_IndexNo = row_Content.CreateCell(0); //序号列 100 cell_IndexNo.CellStyle = cs_Content; 101 102 if (dataRowNum % rowSpan == 0) 103 { 104 cell_IndexNo.SetCellValue(indexNo); 105 indexNo++; 106 } 107 if (IsSpan && excelRowNum % rowSpan == 0)//合并单元格 108 { 109 sheet.AddMergedRegion(new CellRangeAddress(excelRowNum - (rowSpan - 1), excelRowNum, 0, 0)); 110 } 111 #endregion 112 113 for (int j = 0; j < dt.Columns.Count; j++) 114 { 115 ICell cell_Conent = row_Content.CreateCell(j + 1); //创建单元格 116 cell_Conent.CellStyle = cs_Content; 117 118 if (row[j] == DBNull.Value) 119 { 120 cell_Conent.SetCellValue(string.Empty); 121 } 122 else 123 { 124 if (row[j].GetType() == typeof(int)) 125 { 126 cell_Conent.SetCellValue(int.Parse(row[j].ToString())); 127 } 128 else if (row[j].GetType() == typeof(DateTime)) 129 { 130 cell_Conent.CellStyle = cs_Content_Date; 131 cell_Conent.SetCellValue(DateTime.Parse(row[j].ToString())); 132 } 133 else 134 { 135 cell_Conent.SetCellValue(row[j].ToString()); 136 } 137 } 138 139 if (IsSpan && excelRowNum % rowSpan == 0 && j < cols - 1)//合并单元格 140 { 141 sheet.AddMergedRegion(new CellRangeAddress(excelRowNum - (rowSpan - 1), excelRowNum, j + 1, j + 1)); 142 } 143 144 #region 导出公式 145 if (IsFormula) 146 { 147 if (j == dt.Columns.Count - 1)//最后一列求和 148 { 149 startCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex - (dt.Columns.Count - cols - 1), excelRowNum + 1); 150 endCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex - 1, excelRowNum + 1); 151 cell_Conent.SetCellFormula(string.Format("sum({0}:{1})", startCol, endCol)); 152 } 153 154 if (excelRowNum % rowSpan == 0 && j != dt.Columns.Count - 1) 155 { 156 if (j == cols)//第一个日期列 157 { 158 inventoryCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex - 2, excelRowNum - rowSpan + 2); 159 demandCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex, excelRowNum - rowSpan + 2); 160 commitCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex, excelRowNum - rowSpan + 3); 161 cell_Conent.SetCellFormula(string.Format("{0}+{1}-{2}", inventoryCol, commitCol, demandCol)); 162 } 163 else if (j > cols) 164 { 165 inventoryCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex - 1, excelRowNum + 1); 166 demandCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex, excelRowNum - rowSpan + 2); 167 commitCol = EXCELUtilty.GetCellIdentity(cell_Conent.ColumnIndex, excelRowNum - rowSpan + 3); 168 cell_Conent.SetCellFormula(string.Format("{0}+{1}-{2}", inventoryCol, commitCol, demandCol)); 169 } 170 171 } 172 173 } 174 #endregion 175 } 176 177 dataRowNum++; 178 } 179 180 sheet.ForceFormulaRecalculation = true;//激活公式 181 #endregion 182 183 using (FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write)) 184 { 185 wb.Write(file); 186 } 187 188 return true; 189 } 190 catch 191 { 192 return false; 193 } 194 }
MS方式(有版权的,微软要收费):
1 /// <summary> 2 /// 导出Excel文件 3 /// </summary> 4 /// <param name="sheetName"></param> 5 /// <param name="titles">EXCEL表格表头</param> 6 /// <param name="rowSpan">要合并的行数</param> 7 /// <param name="cols">需要合并的左侧列</param> 8 /// <param name="dt"></param> 9 public static void ExportExcel(string sheetName, Dictionary<string, int> titles, int rowSpan, int cols, System.Data.DataTable dt, bool IsSpan = true) 10 { 11 //0.注意: 12 // * Excel中形如Cells[x][y]的写法,前面的数字是列,后面的数字是行! 13 // * Excel中的行、列都是从1开始的,而不是0 14 //制作一个新的Excel文档实例 15 EXCEL.Application xlsApp = new EXCEL.Application(); 16 xlsApp.DisplayAlerts = false; 17 xlsApp.Workbooks.Add(true); 18 //设置Excel分页卡标题 19 xlsApp.ActiveSheet.Name = sheetName; 20 21 EXCEL.Range range; 22 23 //填写各列的标题行 24 int colNum = 1;//列号 25 int rowNum = 1;//行号 26 27 int cnt = 0; 28 foreach (var title in titles) 29 { 30 xlsApp.Cells[colNum + cnt][rowNum] = title.Key; 31 xlsApp.Cells[colNum + cnt][rowNum].ColumnWidth = title.Value; 32 cnt++; 33 } 34 35 xlsApp.Rows[rowNum].Font.Name = "宋体"; 36 xlsApp.Rows[rowNum].Font.Size = 13;//设置字号 37 xlsApp.Rows[rowNum].Font.Bold = true;//粗体 38 xlsApp.Rows[rowNum].HorizontalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;//居中 39 40 //填充数据 41 int rcnt = 0; 42 int indexNo = 1;//序号列 43 int row;//EXCEL行号 44 int col;//EXCEL列号 45 46 for (int i = 0; i < dt.Rows.Count; i++) 47 { 48 row = i + 2; 49 50 #region 设置序号 51 if (rcnt % rowSpan == 0) 52 { 53 xlsApp.Cells[1][row] = indexNo; 54 indexNo++; 55 } 56 if (IsSpan && (row - 1) % rowSpan == 0) 57 { 58 range = xlsApp.ActiveSheet.Range[xlsApp.ActiveSheet.Cells[row - (rowSpan-1), 1], xlsApp.ActiveSheet.Cells[row, 1]]; 59 range.Merge(0); 60 xlsApp.ActiveSheet.Cells[row - (rowSpan - 1), 1] = indexNo - 1; 61 } 62 #endregion 63 64 for (int j = 0; j < dt.Columns.Count; j++) 65 { 66 col = j + 2; 67 xlsApp.Cells[col][row] = dt.Rows[i][j];//填充值 68 69 if (IsSpan && (row - 1) % rowSpan == 0 && col <= cols) 70 { 71 range = xlsApp.ActiveSheet.Range[xlsApp.ActiveSheet.Cells[row - (rowSpan - 1), col], xlsApp.ActiveSheet.Cells[row, col]]; 72 range.Merge(0); 73 xlsApp.ActiveSheet.Cells[row - (rowSpan - 1), col] = dt.Rows[i - (rowSpan - 1)][j]; 74 } 75 } 76 77 rcnt++; 78 } 79 80 //打开制作完毕的表格 81 xlsApp.Visible = true; 82 }
这里介绍一个坑,如果通过AJAX导出EXCEL,浏览器无法直接下载文件。我的做法是先把文件存到服务器上,向前端ajax方法返回服务器路径。
function openExport() { var Id = $("#Id").val(); $.ajax({ type: \'POST\', url: "/XXX/ExportExcel?Id=" + Id, success: function (res) { if (res.type === \'E\') { $.hqmsg.showMsg({ msgtype: \'E\', content: "导出失败" }); } else if (res.type === \'S\') { $.hqmsg.showMsg({ msgtype: \'S\', content: "导出成功" }); var link = $(\'<a href="\' + res.message + \'" target="_blank"></a>\'); link.get(0).click(); } } }); }
辅助类代码:
1 class EXCELUtilty 2 { 3 public static ISheet GetExcelSheet(string path,int sheetIndex) 4 { 5 IWorkbook book; 6 try 7 { 8 using (var file = new FileStream(path, FileMode.Open, FileAccess.Read)) 9 { 10 book = WorkbookFactory.Create(file); 11 return book.GetSheetAt(sheetIndex); 12 } 13 } 14 catch 15 { 16 return null; 17 } 18 } 19 20 /// <summary> 21 /// 读Excel单元格的数据 22 /// </summary> 23 /// <param name="cell">Excel单元格</param> 24 /// <param name="type">列数据类型</param> 25 /// <returns>object 单元格数据</returns> 26 public static dynamic GetCellData(ICell cell, Type type) 27 { 28 var cellValue = GetCellValue(cell); 29 if (cellValue == null) 30 { 31 return DBNull.Value; 32 } 33 34 if (type.Name == "Int32") 35 { 36 int intobj = 0; 37 if (int.TryParse(cellValue, out intobj)) 38 { 39 return intobj; 40 } 41 else 42 { 43 return DBNull.Value; 44 } 45 } 46 else if (type.Name == "Decimal") 47 { 48 decimal decobj = 0.0m; 49 if (decimal.TryParse(cellValue, out decobj)) 50 { 51 return decobj; 52以上是关于Excel导出---NPOI和MS两种方式的主要内容,如果未能解决你的问题,请参考以下文章
Winform中通过NPOI导出Excel的三种方式(HSSFWorkbook,XSSFWorkbook,SXSSFWorkbook)附代码下载