使用NPOI操作Excel
Posted 守望星空的那一边
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用NPOI操作Excel相关的知识,希望对你有一定的参考价值。
Excel表格是工作中经常用到的数据整理工具。有时候我们可能会需要把数据库中的数据导出到Excel文件中或者将Excel文件中的数据导入到数据库,如果我们使用手动方式去操作,既费时又费力,这种大量重复的工作我们可以完全使用代码编程来完成。在.net下有多种方法可以操作Excel表格,如引用com组件:Microsoft.Office.Interop.Excel.dll、采用OleDB读取Excel文件,开源的EPPlus(.xlsx)等。这里为大家介绍下一使用开源的NPOI(.xls)来进行数据库的操作。
一、什么是NPOI
1.NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。
2.开源的项目,可以完全免费使用。
3.NPOI支持导出Excel和导入Excel,并能“理解”OLE2文档结构。
官网下载链接:http://npoi.codeplex.com/documentation
二、简介NOPI
NPOI中操作Excel常用的的类和方法
1.工作簿HSSFWorkbook
描述工作簿的类:IWorkbook(接口),HSSFWorkbook(具体的实现类,一个HSSFWorkbook就表示了一个Excel文件,读写Excel文件都需要首先创建这个类的实例对象)
构造方法,无参数表示创建一个新的工作本,可以接受一个流对象用于打开一个现有的工作簿
方法CreateSheet(索引):创建指定索引的sheet对象
方法GetSheetAt(索引):根据索引获取sheet对象
方法CreateCellStyle();创建单元格样式对象
方法CreateFont():创建字体对象
方法Write(stream):将工作簿输出到流中
2.工作表HSSFSheet
描述工作表的类ISheet(接口),HSSFSheet(具体实现类)描述工作表的类ISheet(接口),HSSFSheet(具体实现类)
方法CreateRow(索引):创建指定索引的行
方法GetRow(索引):根据索引获取行
方法AddMergedRegion():设置合并区域,参数包括开始行索引,开始列索引,结束行索引,结束列索引
方法SetColumnWidth(索引,宽度):设置指定列的宽度
属性FirstRowNum、LastRowNum:获取第一行、最后一行的索引
3.行对象HSSFRow
方法CreateCell(索引):创建指定索引的列
方法GetCell(索引):根据索引获取指定列
属性HeightInPoints:指顶或获取高度
4.单元格对象HSSFCell
方法SetCellValue():设置单元格中的值
属性***CellValue:获取单元格中指定类型的值如果不匹配会抛出异常
属性CellStyle:获取或设置单元格样式
5.单元格样式对象HSSFCellStyle
方法SetFont(字体对象):设置字体样式
属性Alignment:水平对齐,1左,2中,3右
6.字体对象HSSFFont
属性FontHeightInPoints:获取或设置字体大小
属性Boldweight:获取或设置字体加粗
三、从数据库导出数据到Excel
1.引入dll文件(2.0和4.0的两个版本可以根据需要选用)
2.代码
using System; using System.Collections.Generic; using System.Data.SqlClient; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; namespace NPOITesst { class Program { static void Main(string[] args) { //从数据库中读取数据 List<PhoneNum> phoneNums = GetAllPhoneNum(); //保存到Excel中 SaveToExcel(phoneNums); Console.WriteLine("OK!"); Console.Read(); } static List<PhoneNum> GetAllPhoneNum() { //数据库的简单查询,可以使用EF或者其他的微型ORM框架(代码很简单,就几行) List<PhoneNum> phoneNumList = new List<PhoneNum>(); string constr = "Data source=localhost;Initial catalog=PhoneNumManager;Integrated security=true"; string sql = "select pn.*,pt.ptName from PhoneNum as pn inner join PhoneType as pt on pn.pTypeId=pt.ptId"; using (SqlConnection con = new SqlConnection(constr)) { using (SqlCommand command = new SqlCommand(sql, con)) { con.Open(); using (SqlDataReader reader = command.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { PhoneNum model = new PhoneNum { PID = reader.GetInt32(0), PType = new PhoneType() { PTID = reader.GetInt32(1), PTName = reader.GetString(5) }, PName = reader.GetString(2), PCellPhone = reader.GetString(3), PHomePhone = reader.GetString(4) }; phoneNumList.Add(model); } } } } } return phoneNumList; } static void SaveToExcel(List<PhoneNum> phoneNumList) { //1.创建工作簿对象, IWorkbook workBook = new HSSFWorkbook(); //2.在工作簿中创建工作表对象 ISheet sheet = workBook.CreateSheet("PhoneNum"); //第一行列名 IRow firstRow = sheet.CreateRow(0); firstRow.CreateCell(0).SetCellValue("序号"); firstRow.CreateCell(1).SetCellValue("姓名"); firstRow.CreateCell(2).SetCellValue("手机"); firstRow.CreateCell(3).SetCellValue("固话"); firstRow.CreateCell(4).SetCellValue("备注"); //剩下的数据 for (int i = 0; i < phoneNumList.Count; i++) { IRow row = sheet.CreateRow(i + 1); row.CreateCell(0).SetCellValue(phoneNumList[i].PID); row.CreateCell(1).SetCellValue(phoneNumList[i].PName); row.CreateCell(2).SetCellValue(phoneNumList[i].PCellPhone); row.CreateCell(3).SetCellValue(phoneNumList[i].PHomePhone); row.CreateCell(4).SetCellValue(phoneNumList[i].PType.PTName); } //文件流写入 using (FileStream fw = File.Open("PhoneNum.xls", FileMode.OpenOrCreate, FileAccess.Write)) { workBook.Write(fw); } } } class PhoneNum { public int PID { get; set; } public string PName { get; set; } public string PCellPhone { get; set; } public string PHomePhone { get; set; } public PhoneType PType { get; set; } } class PhoneType { public int PTID { get; set; } public string PTName { get; set; } } }
结果图片:
四、从Excel导入数据到数据库
直接上代码:
class ExcelToDB { public static List<Person> GetAllDataFromExcel(string excelPath) { List<Person> personList = new List<Person>(); //1.创建IWorkbook using (FileStream fr = File.OpenRead(excelPath)) { IWorkbook wkbook = new XSSFWorkbook(fr); //遍历每个Sheet for (int i = 0; i < wkbook.NumberOfSheets; i++) { //获取每个Sheet对象 ISheet sheet = wkbook.GetSheetAt(i); //获取每个工作表中的行 //第一行是列名舍去,从第二行开始读取 for (int j = 1; j <= sheet.LastRowNum; j++) { IRow row = sheet.GetRow(j); Person model = new Person { Name = row.GetCell(0).ToString(), Age = Convert.ToInt32(row.GetCell(1).ToString()) }; personList.Add(model); } } } return personList; } public static void InsertToDB(List<Person> personList) { string constr = "Data source=localhost;Initial catalog=DataModel;Integrated security=true"; string sql = "insert into Person values(@name,@age)"; foreach (var person in personList) { using (SqlConnection con = new SqlConnection(constr)) { using (SqlCommand command = new SqlCommand(sql, con)) { con.Open(); SqlParameter[] pms = new SqlParameter[] { new SqlParameter("@name", SqlDbType.NVarChar, 50) {Value = person.Name}, new SqlParameter("@age", SqlDbType.Int) {Value = person.Age}, }; command.Parameters.AddRange(pms); command.ExecuteNonQuery(); } } } } } class Person { public int AutoId { get; set; } public string Name { get; set; } public int Age { get; set; } }
五、其他的常见问题
1.空值的问题
在SqlServer数据库中,空值读取出来后是DBNull,这时可以先通过IsDBNull方法判断是不是DBNull,然后结合可空值类型与NOPI提供的CellType.BLANK结合来进行Excel写入(currentRow.CreateCell(i).SetCellType(CellType.BLANK);)。同理,读取Excel时,应该先判断是否是空值currentCell.CellType==CellType.BLANK,再根据情况向数据库中插入DBNull还是非空值。
2.单元格数据格式样式问题
有些类型的数据直接从Excel读取或者向Excel插入时需要做特殊的处理,如日期格式的数据,向Excel插入时,需要设置单元格样式
{
ICellStyle cellStyle = wk.CreateCellStyle();
cellStyle.DataFormat=HSSFDataFormat.GetBuiltinFormat("mm/dd/yyyy hh:mm:ss");
ICell cell = currentRow.CreateCell(5);
cell.CellStyle = cellStyle;
cell.SetValue((DateTime)lockDate);
}
从Excel读取日期数据时,需要这样处理
DateTime.FromOADate(currentCell.NumericCellValue);
类似的细节还有很多,遇到的时候可以参考NOPI文档:http://npoi.codeplex.com/documentation
以上是关于使用NPOI操作Excel的主要内容,如果未能解决你的问题,请参考以下文章
NPOI操作Excel 005:写入空Excel(Winform版)