参考链接
https://www.cnblogs.com/tangpeng97/p/7839189.html
https://www.cnblogs.com/chenyanbin/archive/2019/05/10/10832614.html
准备工作
- 安装好插件后,需要重写方法 //年代有点久,忘记为什么要重写了
/// <summary> /// 重写Npoi方法 /// </summary> public class NpoiMemoryStream : MemoryStream { public NpoiMemoryStream() { AllowClose = true; } public bool AllowClose { get; set; } public override void Close() { if (AllowClose) base.Close(); } }
Excel文件转DataTable
注意点
- xlsx和xls 需要分别对应两个类型,xlsx对应XSSFWorkbook,xls对应HSSFWorkbook
根据文件路径得到Excel转Datatable
XSSFWorkbook workbook = new XSSFWorkbook("D:\\test.xlsx");//这段没测试,应该可以用 NPOI.SS.UserModel.ISheet sheet = workbook.GetSheetAt(0); DataTable dt = new DataTable(sheet.SheetName); // write header row IRow headerRow = sheet.GetRow(0); foreach (ICell headerCell in headerRow) { dt.Columns.Add(headerCell.ToString()); } // write the rest int rowIndex = 0; foreach (IRow row in sheet) { // skip header row if (rowIndex++ == 0) continue; DataRow dataRow = dt.NewRow(); dataRow.ItemArray = row.Cells.Select(c => c.ToString()).ToArray(); dt.Rows.Add(dataRow); } return dt;
根据文件转换成字节流生成DataTable
/// <summary> /// 根据上传文件得到DataTable /// </summary> /// <param name="file"></param> /// <returns></returns> public static DataTable GetDataTableByExcelFile(HttpPostedFileBase file) { DataTable result = new DataTable(); if (file.FileName.EndsWith(".xlsx")) { result = GetDataTableByStream(file.InputStream, ".xlsx"); return result; } else if (file.FileName.EndsWith(".xls")) { result = GetDataTableByStream(file.InputStream, ".xls"); return result; } else throw new Exception("文件格式不正确,只允许.xlsx或.xls"); } /// <summary> /// 根据字节流生成DataTable,默认只取第一张表格 /// </summary> /// <param name="stream"></param> /// <returns></returns> public static DataTable GetDataTableByStream(Stream stream,string type) { DataTable dt = new DataTable(); NPOI.SS.UserModel.ISheet sheet; switch (type) { case ".xlsx": { XSSFWorkbook workbook = new XSSFWorkbook(stream); sheet = workbook.GetSheetAt(0); dt = new DataTable(sheet.SheetName); break; } case ".xls": { HSSFWorkbook workbook = new HSSFWorkbook(stream); sheet = workbook.GetSheetAt(0); dt = new DataTable(sheet.SheetName); break; } default: { throw new Exception("传入参数不正确"); } } // write header row IRow headerRow = sheet.GetRow(0); foreach (ICell headerCell in headerRow) { dt.Columns.Add(headerCell.ToString()); } // write the rest int rowIndex = 0; foreach (IRow row in sheet) { // skip header row if (rowIndex++ == 0) continue; DataRow dataRow = dt.NewRow(); dataRow.ItemArray = row.Cells.Select(c => c.ToString()).ToArray(); dt.Rows.Add(dataRow); } return dt; }
调用方式
DataTable dt =GetDataTableByExcelFile(file);
根据DataTable生成Excel文件
- 可传入单个DataTable或者List
/// <summary> /// 根据DataTable 生成Excel /// </summary> /// <param name="source"></param> /// <returns></returns> public static NpoiMemoryStream GetExcelFile( DataTable source) { //创建Excel文件的对象,XLSX XSSFWorkbook book = new XSSFWorkbook(); //添加一个sheet ISheet sheet = book.CreateSheet($"OA导出"); //行下标记录 int rowIndex = 0; //创建首行 IRow row0 = sheet.CreateRow(rowIndex++); ////创建单元格 //ICell cell0 = row0.CreateCell(0); ////设置单元格内容 //cell0.CellStyle.Alignment = HorizontalAlignment.CenterSelection; //cell0.SetCellValue("料品情况查询"); //sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, source.Columns.Count)); // IRow row1 = sheet.CreateRow(rowIndex++); for (var i = 0; i < source.Columns.Count; i++) { row0.CreateCell(i).SetCellValue(source.Columns[i].ToString()); } for (var i = 0; i < source.Rows.Count; i++) { IRow rowTemp = sheet.CreateRow(rowIndex++); for (var j = 0; j < source.Columns.Count; j++) { if (source.Rows[i][j].GetType().Name == "Decimal") { rowTemp.CreateCell(j).SetCellValue(Convert.ToDouble(source.Rows[i][j])); } else { rowTemp.CreateCell(j).SetCellValue(source.Rows[i][j].ToString()); } } } for (int columnNum = 0; columnNum < source.Columns.Count; columnNum++) { int columnWidth = sheet.GetColumnWidth(columnNum) / 256;//获取当前列宽度 for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)//在这一列上循环行 { IRow currentRow = sheet.GetRow(rowNum); ICell currentCell = currentRow.GetCell(columnNum); int length = Encoding.UTF8.GetBytes(currentCell.ToString()).Length;//获取当前单元格的内容宽度 if (columnWidth < length + 1) { columnWidth = length + 1; }//若当前单元格内容宽度大于列宽,则调整列宽为当前单元格宽度,后面的+1是我人为的将宽度增加一个字符 } //sheet.SetColumnWidth(columnNum, columnWidth * 256); if (columnWidth > 255) { columnWidth = 254; } else { sheet.SetColumnWidth(columnNum, columnWidth * 256); } } var ms = new NpoiMemoryStream(); ms.AllowClose = false; book.Write(ms); ms.Flush(); ms.Seek(0, SeekOrigin.Begin); ms.AllowClose = true; return ms; } /// <summary> /// 根据多个DataTable 生成一个Excel多个表 /// </summary> /// <param name="sources"></param> /// <returns></returns> public static NpoiMemoryStream GetExcelFile(List<DataTable> sources) { //创建Excel文件的对象,XLSX XSSFWorkbook book = new XSSFWorkbook(); int flag = 1; foreach(DataTable source in sources) { //添加一个sheet ISheet sheet = book.CreateSheet($"OA导出"+flag); //行下标记录 int rowIndex = 0; //创建首行 IRow row0 = sheet.CreateRow(rowIndex++); ////创建单元格 //ICell cell0 = row0.CreateCell(0); ////设置单元格内容 //cell0.CellStyle.Alignment = HorizontalAlignment.CenterSelection; //cell0.SetCellValue("料品情况查询"); //sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, source.Columns.Count)); // IRow row1 = sheet.CreateRow(rowIndex++); for (var i = 0; i < source.Columns.Count; i++) { row0.CreateCell(i).SetCellValue(source.Columns[i].ToString()); } for (var i = 0; i < source.Rows.Count; i++) { IRow rowTemp = sheet.CreateRow(rowIndex++); for (var j = 0; j < source.Columns.Count; j++) { if (source.Rows[i][j].GetType().Name == "Decimal") { rowTemp.CreateCell(j).SetCellValue(Convert.ToDouble(source.Rows[i][j])); } else { rowTemp.CreateCell(j).SetCellValue(source.Rows[i][j].ToString()); } } } for (int columnNum = 0; columnNum < source.Columns.Count; columnNum++) { int columnWidth = sheet.GetColumnWidth(columnNum) / 256;//获取当前列宽度 for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)//在这一列上循环行 { IRow currentRow = sheet.GetRow(rowNum); ICell currentCell = currentRow.GetCell(columnNum); int length = Encoding.UTF8.GetBytes(currentCell.ToString()).Length;//获取当前单元格的内容宽度 if (columnWidth < length + 1) { columnWidth = length + 1; }//若当前单元格内容宽度大于列宽,则调整列宽为当前单元格宽度,后面的+1是我人为的将宽度增加一个字符 } //sheet.SetColumnWidth(columnNum, columnWidth * 256); if (columnWidth > 255) { columnWidth = 254; } else { sheet.SetColumnWidth(columnNum, columnWidth * 256); } } flag++; } var ms = new NpoiMemoryStream(); ms.AllowClose = false; book.Write(ms); ms.Flush(); ms.Seek(0, SeekOrigin.Begin); ms.AllowClose = true; return ms; }
来源:https://www.cnblogs.com/Alex-Mercer/p/12102826.html