一、NPOI简介

1.1、NPOI是什么

  NPOI是POI的.NET版本,POI是一套用Java写成的库,我们在开发中经常用到导入导出表格、文档的情况,NPOI能够帮助我们在没有安装微软Office的情况下读写Office文件,如xls, doc, ppt等。NPOI采用的是Apache 2.0许可证(poi也是采用这个许可证),这意味着它可以被用于任何商业或非商业项目,我们不用担心因为使用它而必须开放你自己的源代码,所以它对于很多从事业务系统开发的公司来说绝对是很不错的选择。

1.2、NPOI简单使用

  NPOI的API十分人性化,使用起来非常容易上手。首先创建一个控制台应用程序,通过nuget获取NPOI,这里使用的是最新版本2.5.4,如下:

1.2.1、创建Excel的Sheet和给单元格添加数据【基础1】

        //创建Sheet和给单元格添加数据【基础1】private void CreateSheetAndCell_BaseOne(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;//创建workbook,说白了就是在内存中创建一个Excel文件IWorkbook workbook = new HSSFWorkbook();//要添加至少一个sheet,没有sheet的excel是打不开的ISheet sheet1 = workbook.CreateSheet("sheet1");ISheet sheet2 = workbook.CreateSheet("sheet2");IRow row1 = sheet1.CreateRow(0);//添加第1行,注意行列的索引都是从0开始的ICell cell1 = row1.CreateCell(0);//给第1行添加第1个单元格cell1.SetCellValue("hello npoi!");//给单元格赋值//上边3个步骤合在一起:sheet1.CreateRow(0).CreateCell(0).SetCellValue("hello npoi");//获取第一行第一列的string值Console.WriteLine(sheet1.GetRow(0).GetCell(0).StringCellValue); //输出:hello npoi//写入文件using (FileStream file = new FileStream(filePathAndName, FileMode.Create)){workbook.Write(file);}//导出成功提示ExportSuccessTips(filePathAndName);}

运行后在选择的路径创建对应的Excel文件且格式如下:

二、NPOI使用详解

2.1 单元格数据格式

  用过Excel的人都知道,单元格是Excel最有意义的东西,我们做任何操作恐怕都要和单元格打交道。在Excel中我们经常要设置格式,比如说日期格式(2018-1-1)、小数点格式(1.20)、货币格式($2000)、百分比格式(99.99%)等等,这些东西在过去我们恐怕只能在服务器端生成好,不但增加了服务器端的代码量,还造成了不必要的字符串替换操作,如今NPOI将让服务器从这种完全没有必要的操作中解放出来,一切都将由Excel在客户端处理。

  使用NPOI时要注意,所有的格式都是通过 CellStyle.DataFormat 赋给单元格的,而不是直接赋给单元格,设置单元格数据展示的格式有两种方法。

2.1.1、设置excel中内置的格式:

excel内部设置了很多格式,如下图所示:

如果我们想使用这些内置的格式,可用通过 DataFormat.GetBuildinFormat('格式') 来使用,使用实例如下:

cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");  //两位小数,内置格式

2.1.2、设置自定义格式

  有时候内置的格式不能满足我们的要求,这时候就可以使用 workbook.CreateDataFormat().GetFormat("格式") 自定义格式了,使用语法如下:

cellStyle.DataFormat= workbook.CreateDataFormat().GetFormat("yyyy年m月d日 hh时mm分ss秒");//显示中文日期和时间,自定义格式
        //导出数据到Excel基础_单元格格式转换private void ExportExcel_CellFormat(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;IWorkbook workbook = new HSSFWorkbook();ISheet sheet = workbook.CreateSheet("new sheet");//设置日期格式,2018年5月5日格式ICell cell = sheet.CreateRow(0).CreateCell(0);cell.SetCellValue(new DateTime(2018, 5, 5, 11, 31, 56));ICellStyle cellStyle = workbook.CreateCellStyle();cellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("yyyy年m月d日 hh时mm分ss秒");//cellStyle.DataFormat = workbook.CreateDataFormat().GetFormat("yyyy/mm/dd hh:mm:ss"); cell.CellStyle = cellStyle;//保留2位小数ICell cell2 = sheet.CreateRow(1).CreateCell(0);cell2.SetCellValue(12.346666);ICellStyle cellStyle2 = workbook.CreateCellStyle();cellStyle2.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00");cell2.CellStyle = cellStyle2;//货币格式ICell cell3 = sheet.CreateRow(2).CreateCell(0);cell3.SetCellValue(1234.66666);ICellStyle cellStyle3 = workbook.CreateCellStyle();cellStyle3.DataFormat = workbook.CreateDataFormat().GetFormat("¥#,##0.00");//美元的话格式为 $#,##0.00,其中#,##0表示千分号cell3.CellStyle = cellStyle3;//百分比ICell cell4 = sheet.CreateRow(3).CreateCell(0);cell4.SetCellValue(1.236666);ICellStyle cellStyle4 = workbook.CreateCellStyle();//cellStyle4.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00%");//保留两位小数cellStyle4.DataFormat = HSSFDataFormat.GetBuiltinFormat("0%");cell4.CellStyle = cellStyle4;//中文大写数字ICell cell5 = sheet.CreateRow(4).CreateCell(0);cell5.SetCellValue(111);ICellStyle cellStyle5 = workbook.CreateCellStyle();cellStyle5.DataFormat = workbook.CreateDataFormat().GetFormat("[DbNum2][$-804]0.00");//不保留小数: [DbNum2][$-804]0cell5.CellStyle = cellStyle5;//科学计数法ICell cell6 = sheet.CreateRow(5).CreateCell(0);cell6.SetCellValue(1234.6666);ICellStyle cellStyle6 = workbook.CreateCellStyle();cellStyle6.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00E+00");cell6.CellStyle = cellStyle6;using (FileStream file = new FileStream(filePathAndName, FileMode.Create)){workbook.Write(file);}//导出成功提示ExportSuccessTips(filePathAndName);}

运行程序生成的Excel文件效果如下:

2.2、单元格合并及设置风格

  单元格的合并和风格这部分内容比较多,但是Api十分的简单,为了看起来清晰,我们分成两个栗子来演示这部分的功能,代码中的注释很详细,这里就直接上代码了

2.2.1、第一个栗子演示单元格合并,内容停靠,字体风格颜色大小等

        //导出数据到Excel基础_单元格合并及风格设置1private void ExportExcel_MergeCellStyleSettingsOne(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;HSSFWorkbook workbook = new HSSFWorkbook();ISheet sheet = workbook.CreateSheet("sheet1");//------------------单元格合并sheet.AddMergedRegion(new CellRangeAddress(1, 2, 1, 5));//合并单元格,4个参数依次为为startRow,endRow,startCol,endColICell cell = sheet.CreateRow(1).CreateCell(1);cell.SetCellValue("合并的区域");cell.Row.HeightInPoints = 40;//行高ICellStyle cellstyle = workbook.CreateCellStyle();//----------------设置单元格常用风格cellstyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;//水平居左,可选Right,Centercellstyle.VerticalAlignment = VerticalAlignment.Bottom;//垂直居中,可选Top,Centercellstyle.WrapText = true;//自动换行cellstyle.Indention = 4;//缩进4个字节//cellstyle.Rotation = 90;//字体旋转90度,取值范围是[-90,90]//---------------字体,字体大小、颜色IFont font = workbook.CreateFont();font.FontHeightInPoints = 24;//字号为24,可以用font.FontHeight = 24 * 20;FontHeight的单位是1/20点font.FontName = "幼圆";//字体font.Boldweight = 700;//加粗font.Color = HSSFColor.Blue.Index;//字体颜色cellstyle.SetFont(font);cell.CellStyle = cellstyle;using (FileStream file = new FileStream(filePathAndName, FileMode.Create)){workbook.Write(file);}//导出成功提示ExportSuccessTips(filePathAndName);}

生成的excel文件如下图所示:

2.2.2、第二个栗子演示单元格的宽高、背景色、边框风格等

        //导出数据到Excel基础_单元格合并及风格设置2private void ExportExcel_MergeCellStyleSettingsTwo(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;IWorkbook workbook = new HSSFWorkbook();ISheet sheet = workbook.CreateSheet("sheet1");ICell cell = sheet.CreateRow(1).CreateCell(1);cell.SetCellValue("hello");ICellStyle cellstyle = workbook.CreateCellStyle();//设置宽度,把第2列设成20字节宽;参数1指定列的索引;参数2指定宽度,单位是1/256个字符宽度sheet.SetColumnWidth(1, 20 * 256);//高度设成40,单位是点;也可以用cell2.Row.Height = 40 * 20;Height的单位是1/20点cell.Row.HeightInPoints = 40;//右边框设置成点画线cellstyle.BorderRight = NPOI.SS.UserModel.BorderStyle.MediumDashDot;//右边框设成粉色cellstyle.RightBorderColor = HSSFColor.Pink.Index;//前景色填充模式,实心cellstyle.FillPattern = FillPattern.SolidForeground;//前景色填充颜色,黄色cellstyle.FillForegroundColor = HSSFColor.Yellow.Index;//背景色//cellstyle2.FillBackgroundColor = HSSFColor.Green.Index;//背景色设成greencell.CellStyle = cellstyle;using (FileStream file = new FileStream(filePathAndName, FileMode.Create)){workbook.Write(file);}//导出成功提示ExportSuccessTips(filePathAndName);}

运行程序,生成的excel文件如下:

其实在NPOI中除了操作单元格的内容和风格外,还提供了添加excel文件摘要,添加批注,画图,使用公式等功能,但是这些功能我们用的比较少,所以就不一一展示了,NPOI的公式我自己很少去使用,一般通过程序直接计算结果,个人感觉在程序中计算更加灵活,当excel的结构发生变化时修改起来也更方便些。

三、封装的ExcelHelper帮助类

3.1、使用ExcelHelper帮助类导出文件

使用Nuget添加几个包:NPOI,log4net(其他的日志记录组件也可以),System.Text.Encoding.CodePages(为了支持gb2312),具体代码如下:

//导出数据到Excelprivate void ExportExcel(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;//用于支持gb2312         Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//测试dataTable数据源 DataTable dataTable = new DataTable();dataTable.Columns.Add("id", typeof(int));dataTable.Columns.Add("uname", typeof(string));dataTable.Columns.Add("sex", typeof(string));dataTable.Columns.Add("age", typeof(int));dataTable.Columns.Add("pwd", typeof(string));dataTable.Columns.Add("email", typeof(string));dataTable.Columns.Add("address", typeof(string));Random r = new Random();for (int i = 0; i < 1000; i++){DataRow row = dataTable.NewRow();row["id"] = i;row["uname"] = "hellox" + i.ToString();row["sex"] = r.Next(2) % 2 == 0 ? "男" : "女";row["age"] = r.Next(40) + 18;row["pwd"] = "pwd" + r.Next(5000).ToString();row["email"] = r.Next(100000) + "@qq.com";row["address"] = $"北京市,西{r.Next(4) + 1}环,xx路{r.Next(100)}号";dataTable.Rows.Add(row);}//DataTable的列名和excel的列名对应字典,因为excel的列名一般是中文的,DataTable的列名是英文的,字典主要是存储excel和DataTable列明的对应关系,当然我们也可以把这个对应关系存在配置文件或者其他地方Dictionary<string, string> dir = new Dictionary<string, string>();dir.Add("id", "编号");dir.Add("uname", "用户");dir.Add("sex", "性别");dir.Add("age", "年龄");dir.Add("pwd", "密码");dir.Add("email", "邮箱");dir.Add("address", "住址");//使用helper类导出DataTable数据到excel表格中,参数依次是 (DataTable数据源;  excel表名;  excel存放位置的绝对路径; 列名对应字典; 是否清空以前的数据,设置为false,表示内容追加; 每个sheet放的数据条数,如果超过该条数就会新建一个sheet存储)ExcelHelper.ExportDTtoExcel(dataTable, "考勤信息表", filePathAndName, dir, false, 400);//导出成功提示ExportSuccessTips(filePathAndName);}

运行程序,当一个sheet的数目满了后会新生产一个sheet1来存储,效果如下:

3.2、使用ExcelHelper帮助类导入文件

        //从Excel中导入数据到界面private void ImportUIfFromExcel(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;//用于支持gb2312    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//DataTable的列名和excel的列名对应字典Dictionary<string, string> dir = new Dictionary<string, string>();dir.Add("id", "编号");dir.Add("uname", "用户");dir.Add("sex", "性别");dir.Add("age", "年龄");dir.Add("pwd", "密码");dir.Add("email", "邮箱");dir.Add("address", "住址");//读取数据到DataTable,参数依此是(excel文件路径,列名对应字典,列名所在行,sheet索引)DataTable dt = ExcelHelper.ImportExceltoDt(filePathAndName, dir, 1, 0);//遍历DataTable---------------------------string tmpInfo = null;foreach (DataColumn item in dt.Columns){//显示dataTable的列名tmpInfo+=(item.ColumnName + new string('-', 10));}tmpInfo += "\r\n";//遍历DataTable中的数据foreach (DataRow row in dt.Rows){for (int i = 0; i < dt.Columns.Count; i++){tmpInfo+=(row[i].ToString() + new string(' ', 10));}tmpInfo += "\r\n";}//显示数据ShowInfo(tmpInfo);//导入成功提示ImportSuccessTips(filePathAndName);}

运行程序后的效果如下:

3.3、ExcelHelper帮助类

兼容xls和xlsx两种格式

/***
*   Title:"基础工具" 项目
*       主题:Excel帮助类
*   Description:
*       功能:
*           1、导出数据到Excel文件中
*           2、将Excel文件的数据导入到DataTable中
*   Date:2021
*   Version:0.1版本
*   Author:Coffee
*   Modify Recoder:
*/using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Eval;
using NPOI.SS.UserModel;
using System.Linq;
using NPOI.SS.Util;
using System.Text.RegularExpressions;
using NPOI.XSSF.UserModel;namespace Utils
{public class ExcelHelper{#region 从DataTable导出到excel文件中,支持xls和xlsx格式#region 导出为xls文件内部方法/// <summary>/// 从datatable 中导出到excel/// </summary>/// <param name="strFileName">excel文件名</param>/// <param name="dtSource">datatabe源数据</param>/// <param name="strHeaderText">表名</param>/// <param name="sheetnum">sheet的编号</param>/// <returns></returns>static MemoryStream ExportDT(String strFileName, DataTable dtSource, string strHeaderText, Dictionary<string, string> dir, int sheetnum){//创建工作簿和sheetIWorkbook workbook = new HSSFWorkbook();using (Stream writefile = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Read)){if (writefile.Length > 0 && sheetnum > 0){workbook = WorkbookFactory.Create(writefile);}}ISheet sheet = null;ICellStyle dateStyle = workbook.CreateCellStyle();IDataFormat format = workbook.CreateDataFormat();dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");int[] arrColWidth = new int[dtSource.Columns.Count];foreach (DataColumn item in dtSource.Columns){arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;}for (int i = 0; i < dtSource.Rows.Count; i++){for (int j = 0; j < dtSource.Columns.Count; j++){int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length;if (intTemp > arrColWidth[j]){arrColWidth[j] = intTemp;}}}int rowIndex = 0;foreach (DataRow row in dtSource.Rows){#region 新建表,填充表头,填充列头,样式if (rowIndex == 0){string sheetName = strHeaderText + (sheetnum == 0 ? "" : sheetnum.ToString());if (workbook.GetSheetIndex(sheetName) >= 0){workbook.RemoveSheetAt(workbook.GetSheetIndex(sheetName));}sheet = workbook.CreateSheet(sheetName);#region 表头及样式{sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1));IRow headerRow = sheet.CreateRow(0);headerRow.HeightInPoints = 25;headerRow.CreateCell(0).SetCellValue(strHeaderText);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 20;font.Boldweight = 700;headStyle.SetFont(font);headerRow.GetCell(0).CellStyle = headStyle;rowIndex = 1;}#endregion#region 列头及样式if (rowIndex == 1){IRow headerRow = sheet.CreateRow(1);//第二行设置列名ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 10;font.Boldweight = 700;headStyle.SetFont(font);//写入列标题foreach (DataColumn column in dtSource.Columns){headerRow.CreateCell(column.Ordinal).SetCellValue(dir[column.ColumnName]);headerRow.GetCell(column.Ordinal).CellStyle = headStyle;//设置列宽sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256 * 2);}rowIndex = 2;}#endregion}#endregion#region 填充内容IRow dataRow = sheet.CreateRow(rowIndex);foreach (DataColumn column in dtSource.Columns){ICell newCell = dataRow.CreateCell(column.Ordinal);string drValue = row[column].ToString();switch (column.DataType.ToString()){case "System.String": //字符串类型double result;if (isNumeric(drValue, out result)){//数字字符串double.TryParse(drValue, out result);newCell.SetCellValue(result);break;}else{newCell.SetCellValue(drValue);break;}case "System.DateTime": //日期类型DateTime dateV;DateTime.TryParse(drValue, out dateV);newCell.SetCellValue(dateV);newCell.CellStyle = dateStyle; //格式化显示break;case "System.Boolean": //布尔型bool boolV = false;bool.TryParse(drValue, out boolV);newCell.SetCellValue(boolV);break;case "System.Int16": //整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(drValue, out intV);newCell.SetCellValue(intV);break;case "System.Decimal": //浮点型case "System.Double":double doubV = 0;double.TryParse(drValue, out doubV);newCell.SetCellValue(doubV);break;case "System.DBNull": //空值处理newCell.SetCellValue("");break;default:newCell.SetCellValue(drValue.ToString());break;}}#endregionrowIndex++;}using (MemoryStream ms = new MemoryStream()){workbook.Write(ms);ms.Flush();ms.Position = 0;return ms;}}#endregion#region 导出为xlsx文件内部方法/// <summary>/// 从datatable 中导出到excel/// </summary>/// <param name="dtSource">datatable数据源</param>/// <param name="strHeaderText">表名</param>/// <param name="fs">文件流</param>/// <param name="readfs">内存流</param>/// <param name="sheetnum">sheet索引</param>static void ExportDTI(DataTable dtSource, string strHeaderText, FileStream fs, MemoryStream readfs, Dictionary<string, string> dir, int sheetnum){IWorkbook workbook = new XSSFWorkbook();if (readfs.Length > 0 && sheetnum > 0){workbook = WorkbookFactory.Create(readfs);}ISheet sheet = null;ICellStyle dateStyle = workbook.CreateCellStyle();IDataFormat format = workbook.CreateDataFormat();dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");//取得列宽int[] arrColWidth = new int[dtSource.Columns.Count];foreach (DataColumn item in dtSource.Columns){arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;}for (int i = 0; i < dtSource.Rows.Count; i++){for (int j = 0; j < dtSource.Columns.Count; j++){int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length;if (intTemp > arrColWidth[j]){arrColWidth[j] = intTemp;}}}int rowIndex = 0;foreach (DataRow row in dtSource.Rows){#region 新建表,填充表头,填充列头,样式if (rowIndex == 0){#region 表头及样式{string sheetName = strHeaderText + (sheetnum == 0 ? "" : sheetnum.ToString());if (workbook.GetSheetIndex(sheetName) >= 0){workbook.RemoveSheetAt(workbook.GetSheetIndex(sheetName));}sheet = workbook.CreateSheet(sheetName);sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1));IRow headerRow = sheet.CreateRow(0);headerRow.HeightInPoints = 25;headerRow.CreateCell(0).SetCellValue(strHeaderText);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 20;font.Boldweight = 700;headStyle.SetFont(font);headerRow.GetCell(0).CellStyle = headStyle;}#endregion#region 列头及样式{IRow headerRow = sheet.CreateRow(1);ICellStyle headStyle = workbook.CreateCellStyle();headStyle.Alignment = HorizontalAlignment.Center;IFont font = workbook.CreateFont();font.FontHeightInPoints = 10;font.Boldweight = 700;headStyle.SetFont(font);foreach (DataColumn column in dtSource.Columns){headerRow.CreateCell(column.Ordinal).SetCellValue(dir[column.ColumnName]);headerRow.GetCell(column.Ordinal).CellStyle = headStyle;//设置列宽sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256 * 2);}}#endregionrowIndex = 2;}#endregion#region 填充内容IRow dataRow = sheet.CreateRow(rowIndex);foreach (DataColumn column in dtSource.Columns){ICell newCell = dataRow.CreateCell(column.Ordinal);string drValue = row[column].ToString();switch (column.DataType.ToString()){case "System.String": //字符串类型double result;if (isNumeric(drValue, out result)){double.TryParse(drValue, out result);newCell.SetCellValue(result);break;}else{newCell.SetCellValue(drValue);break;}case "System.DateTime": //日期类型DateTime dateV;DateTime.TryParse(drValue, out dateV);newCell.SetCellValue(dateV);newCell.CellStyle = dateStyle; //格式化显示break;case "System.Boolean": //布尔型bool boolV = false;bool.TryParse(drValue, out boolV);newCell.SetCellValue(boolV);break;case "System.Int16": //整型case "System.Int32":case "System.Int64":case "System.Byte":int intV = 0;int.TryParse(drValue, out intV);newCell.SetCellValue(intV);break;case "System.Decimal": //浮点型case "System.Double":double doubV = 0;double.TryParse(drValue, out doubV);newCell.SetCellValue(doubV);break;case "System.DBNull": //空值处理newCell.SetCellValue("");break;default:newCell.SetCellValue(drValue.ToString());break;}}#endregionrowIndex++;}workbook.Write(fs);fs.Close();}#endregion#region 导出excel表格/// <summary>///  DataTable导出到Excel文件,xls文件/// </summary>/// <param name="dtSource">数据源</param>/// <param name="strHeaderText">表名</param>/// <param name="strFileName">excel文件名</param>/// <param name="dir">datatable和excel列名对应字典</param>/// <param name="sheetRow">每个sheet存放的行数</param>public static void ExportDTtoExcel(DataTable dtSource, string strHeaderText, string strFileName, Dictionary<string, string> dir, bool isNew, int sheetRow = 50000){int currentSheetCount = GetSheetNumber(strFileName);//现有的页数sheetnumif (sheetRow <= 0){sheetRow = dtSource.Rows.Count;}string[] temp = strFileName.Split('.');string fileExtens = temp[temp.Length - 1];int sheetCount = (int)Math.Ceiling((double)dtSource.Rows.Count / sheetRow);//sheet数目if (temp[temp.Length - 1] == "xls" && dtSource.Columns.Count < 256 && sheetRow < 65536){if (isNew){currentSheetCount = 0;}for (int i = currentSheetCount; i < currentSheetCount + sheetCount; i++){DataTable pageDataTable = dtSource.Clone();int hasRowCount = dtSource.Rows.Count - sheetRow * (i - currentSheetCount) < sheetRow ? dtSource.Rows.Count - sheetRow * (i - currentSheetCount) : sheetRow;for (int j = 0; j < hasRowCount; j++){pageDataTable.ImportRow(dtSource.Rows[(i - currentSheetCount) * sheetRow + j]);}using (MemoryStream ms = ExportDT(strFileName, pageDataTable, strHeaderText, dir, i)){using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)){byte[] data = ms.ToArray();fs.Write(data, 0, data.Length);fs.Flush();}}}}else{if (temp[temp.Length - 1] == "xls")strFileName = strFileName + "x";if (isNew){currentSheetCount = 0;}for (int i = currentSheetCount; i < currentSheetCount + sheetCount; i++){DataTable pageDataTable = dtSource.Clone();int hasRowCount = dtSource.Rows.Count - sheetRow * (i - currentSheetCount) < sheetRow ? dtSource.Rows.Count - sheetRow * (i - currentSheetCount) : sheetRow;for (int j = 0; j < hasRowCount; j++){pageDataTable.ImportRow(dtSource.Rows[(i - currentSheetCount) * sheetRow + j]);}FileStream readfs = new FileStream(strFileName, FileMode.OpenOrCreate, FileAccess.Read);MemoryStream readfsm = new MemoryStream();readfs.CopyTo(readfsm);readfs.Close();using (FileStream writefs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)){ExportDTI(pageDataTable, strHeaderText, writefs, readfsm, dir, i);}readfsm.Close();}}}#endregion#endregion#region 从excel文件中将数据导出到datatable/datatable/// <summary>/// 将制定sheet中的数据导出到datatable中/// </summary>/// <param name="sheet">需要导出的sheet</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <returns></returns>static DataTable ImportDt(ISheet sheet, int HeaderRowIndex, Dictionary<string, string> dir){DataTable table = new DataTable();IRow headerRow;int cellCount;try{//没有标头或者不需要表头用excel列的序号(1,2,3..)作为DataTable的列名if (HeaderRowIndex < 0){headerRow = sheet.GetRow(0);cellCount = headerRow.LastCellNum;for (int i = headerRow.FirstCellNum; i <= cellCount; i++){DataColumn column = new DataColumn(Convert.ToString(i));table.Columns.Add(column);}}//有表头,使用表头做为DataTable的列名else{headerRow = sheet.GetRow(HeaderRowIndex);cellCount = headerRow.LastCellNum;for (int i = headerRow.FirstCellNum; i <= cellCount; i++){//如果excel某一列列名不存在:以该列的序号作为Datatable的列名,如果DataTable中包含了这个序列为名的列,那么列名为重复列名+序号if (headerRow.GetCell(i) == null){if (table.Columns.IndexOf(Convert.ToString(i)) > 0){DataColumn column = new DataColumn(Convert.ToString("重复列名" + i));table.Columns.Add(column);}else{DataColumn column = new DataColumn(Convert.ToString(i));table.Columns.Add(column);}}//excel中的某一列列名不为空,但是重复了:对应的Datatable列名为“重复列名+序号”else if (table.Columns.IndexOf(headerRow.GetCell(i).ToString()) > 0){DataColumn column = new DataColumn(Convert.ToString("重复列名" + i));table.Columns.Add(column);}else//正常情况,列名存在且不重复:用excel中的列名作为datatable中对应的列名{string colName = dir.Where(s => s.Value == headerRow.GetCell(i).ToString()).First().Key;DataColumn column = new DataColumn(colName);table.Columns.Add(column);}}}int rowCount = sheet.LastRowNum;for (int i = (HeaderRowIndex + 1); i <= sheet.LastRowNum; i++)//excel行遍历{try{IRow row;if (sheet.GetRow(i) == null)//如果excel有空行,则添加缺失的行{row = sheet.CreateRow(i);}else{row = sheet.GetRow(i);}DataRow dataRow = table.NewRow();for (int j = row.FirstCellNum; j <= cellCount; j++)//excel列遍历{try{if (row.GetCell(j) != null){switch (row.GetCell(j).CellType){case CellType.String://字符串string str = row.GetCell(j).StringCellValue;if (str != null && str.Length > 0){dataRow[j] = str.ToString();}else{dataRow[j] = default(string);}break;case CellType.Numeric://数字if (DateUtil.IsCellDateFormatted(row.GetCell(j)))//时间戳数字{dataRow[j] = DateTime.FromOADate(row.GetCell(j).NumericCellValue);}else{dataRow[j] = Convert.ToDouble(row.GetCell(j).NumericCellValue);}break;case CellType.Boolean:dataRow[j] = Convert.ToString(row.GetCell(j).BooleanCellValue);break;case CellType.Error:dataRow[j] = ErrorEval.GetText(row.GetCell(j).ErrorCellValue);break;case CellType.Formula://公式switch (row.GetCell(j).CachedFormulaResultType){case CellType.String:string strFORMULA = row.GetCell(j).StringCellValue;if (strFORMULA != null && strFORMULA.Length > 0){dataRow[j] = strFORMULA.ToString();}else{dataRow[j] = null;}break;case CellType.Numeric:dataRow[j] = Convert.ToString(row.GetCell(j).NumericCellValue);break;case CellType.Boolean:dataRow[j] = Convert.ToString(row.GetCell(j).BooleanCellValue);break;case CellType.Error:dataRow[j] = ErrorEval.GetText(row.GetCell(j).ErrorCellValue);break;default:dataRow[j] = "";break;}break;default:dataRow[j] = "";break;}}}catch (Exception exception){//loger.Error(exception.ToString());}}table.Rows.Add(dataRow);}catch (Exception exception){//loger.Error(exception.ToString());}}}catch (Exception exception){//loger.Error(exception.ToString());}return table;}/// <summary>/// 读取Excel文件特定名字sheet的内容到DataTable/// </summary>/// <param name="strFileName">excel文件路径</param>/// <param name="sheet">需要导出的sheet</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <returns></returns>public static DataTable ImportExceltoDt(string strFileName, Dictionary<string, string> dir, string SheetName, int HeaderRowIndex = 1){DataTable table = new DataTable();using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)){if (file.Length > 0){IWorkbook wb = WorkbookFactory.Create(file);ISheet isheet = wb.GetSheet(SheetName);table = ImportDt(isheet, HeaderRowIndex, dir);isheet = null;}}return table;}/// <summary>/// 读取Excel文件某一索引sheet的内容到DataTable/// </summary>/// <param name="strFileName">excel文件路径</param>/// <param name="sheet">需要导出的sheet序号</param>/// <param name="HeaderRowIndex">列头所在行号,-1表示没有列头</param>/// <param name="dir">excel列名和DataTable列名的对应字典</param>/// <returns></returns>public static DataTable ImportExceltoDt(string strFileName, Dictionary<string, string> dir, int HeaderRowIndex = 1, int SheetIndex = 0){DataTable table = new DataTable();using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)){if (file.Length > 0){IWorkbook wb = WorkbookFactory.Create(file);ISheet isheet = wb.GetSheetAt(SheetIndex);table = ImportDt(isheet, HeaderRowIndex, dir);isheet = null;}}return table;}#endregion/// <summary>/// 获取excel文件的sheet数目/// </summary>/// <param name="outputFile"></param>/// <returns></returns>public static int GetSheetNumber(string outputFile){int number = 0;using (FileStream readfile = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.Read)){if (readfile.Length > 0){IWorkbook wb = WorkbookFactory.Create(readfile);number = wb.NumberOfSheets;}}return number;}/// <summary>/// 判断内容是否是数字/// </summary>/// <param name="message"></param>/// <param name="result"></param>/// <returns></returns>public static bool isNumeric(String message, out double result){Regex rex = new Regex(@"^[-]?\d+[.]?\d*$");result = -1;if (rex.IsMatch(message)){result = double.Parse(message);return true;}elsereturn false;}/// <summary>/// 验证导入的Excel是否有数据/// </summary>/// <param name="excelFileStream"></param>/// <returns></returns>public static bool HasData(Stream excelFileStream){using (excelFileStream){IWorkbook workBook = new HSSFWorkbook(excelFileStream);if (workBook.NumberOfSheets > 0){ISheet sheet = workBook.GetSheetAt(0);return sheet.PhysicalNumberOfRows > 0;}}return false;}}//Class_end}

3.4、导入导出提示

        //导出成功提示private void ExportSuccessTips(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;MessageBox.Show("导出成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);if (MessageBox.Show("保存成功,是否打开文件?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes){System.Diagnostics.Process.Start(filePathAndName);}}//导入成功提示private void ImportSuccessTips(string filePathAndName){if (string.IsNullOrEmpty(filePathAndName)) return;MessageBox.Show("导入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}//信息提示private void ShowInfo(string info){memoEdit1.Text = info;}

3.5、Winform中获取选择的目录、文件的路径和名称

Winform中获取选择的目录、文件的路径和名称

C#使用NPOI实现导入导出Excel数据相关推荐

  1. toad导入数据_Oracle 使用TOAD实现导入导出Excel数据

    在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作,对数据库进行日常管理也是需要很多SQL脚本才能完成的.Quest Software为此提供了高效的Orac ...

  2. java 导入excel工具类_java Excel工具类,导入导出Excel数据

    java Excel工具类,导入导出Excel数据,导入数据对合并表格有判断获取数据: 导出数据到Excel,Excel文件不存在会创建. 使用的是poi处理,兼容Excel. 对反射不够理解,目前先 ...

  3. python导入excel数据-Python数据处理之导入导出excel数据

    欢迎点击上方"AntDream"关注我 .Python的一大应用就是数据分析了,而数据分析中,经常碰到需要处理Excel数据的情况.这里做一个Python处理Excel数据的总结, ...

  4. java excel data 导入数据_java实现导入导出excel数据

    项目需要,要实现一个导入导出excel的功能,于是,任务驱动着我学习到了POI和JXL这2个java操作Excel的插件. 一.POI和JXL介绍 1.POI:是对所有office资源进行读写的一套工 ...

  5. java 动态导入excel_java实现导入导出excel数据

    项目需要,要实现一个导入导出excel的功能,于是,任务驱动着我学习到了POI和JXL这2个java操作Excel的插件. 一.POI和JXL介绍 1.POI:是对所有office资源进行读写的一套工 ...

  6. 使用NPOI库导入导出EXCEL

    一.EXCEL  导入(Excel 导入导出实际项目中会被封装成**Helper 本示例只对简单功能做演示) NPOI 包引用 视图view @{ViewBag.Title = "NPOIE ...

  7. toad mysql导入excel_Oracle 使用TOAD实现导入导出Excel数据

    在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作,对数据库进行日常管理也是需要很多SQL脚本才能完成的.Quest Software为此提供了高效的Orac ...

  8. 用toad实现oracle数据迁移,Oracle 使用TOAD实现导入导出Excel数据

    在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作,对数据库进行日常管理也是需要很多SQL脚本才能完成的.Quest Software为此提供了高效的Orac ...

  9. 导Excel数据到Oracle的脚本,Oracle使用TOAD实现导入导出Excel数据

    在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工作,对数据库进行日常管理也是需要很多SQL脚本才能完成的.Quest Software为此提供了高效的Orac ...

最新文章

  1. postgis学习笔记
  2. cancase lin管脚_汽车里有什么信号是传送到总线(CAN/LIN)上?
  3. python顺序结构实验报告_Python 数据结构 之 串 的顺序存储结构
  4. 触发器创建删除等操作
  5. elementUI中radio的相关使用
  6. 第八篇: UpdateProgress 控件--显示正在处理中的信息
  7. 邮件里直接显示图片_利用邮件合并带图片功能批量制作准考证、工作证、成绩通知单等...
  8. 自签名证书的安装(一)
  9. 什么是视频分配器 编码器
  10. hibernate创建配置遇到问题:!-- https://mvnrepository.com/artifact/javassist/javassist -- dependency
  11. Win7-Win10快捷键
  12. 仿网易新闻顶部菜单html,iOS仿网易新闻滚动导航条效果
  13. ECharts+高德卫星地图-飞线图效果
  14. 关机整蛊小程序(c语言实现)
  15. java取石子_HDU 1527 取石子游戏
  16. html语言加入图片背景音乐,如何插入背景音乐和背景图片(附HTML语法教程地址)...
  17. Oracle数据库综合试题
  18. Android手机发生了SSL连接错误该怎么解决
  19. 家庭食品包装密实袋的前世今生和未来
  20. 似墨迹天气 widget翻页时钟实现

热门文章

  1. 在暗影精灵游戏本上安装 Centos7
  2. Flask一对多学生课程表项目搭建
  3. 每日生产万亿消息数据入库,腾讯如何突破大数据分析架构瓶颈
  4. 英雄联盟皮肤图片爬取
  5. HotSpot VM
  6. 虚拟机VMware6.5将厚置备转成精简置备
  7. POJ-2395 Out of Hay
  8. 洛谷P2017 [USACO09DEC]晕牛Dizzy Cows [拓扑排序]
  9. camera log分析
  10. MySQL新手入门:MySQL数据库的启动与连接