NPOI读写
npoi 是开源的 poi 项目的.net版,可以用来读写excel,word,ppt文件。
在处理excel文件上,npoi 可以同时兼容 xls 和 xlsx。官网提供了一份 examples,
给出了很多应用场景的例子,打包好的二进制文件类库,也仅有几mb,使用非常方便。
读excel
npoi 使用 hssfworkbook
类来处理 xls,xssfworkbook
类来处理 xlsx,它们都继承接口 iworkbook
,因此可以通过 iworkbook
来统一处理 xls 和 xlsx 格式的文件
public void readfromexcelfile(string filepath) { iworkbook wk = null; string extension = system.io.path.getextension(filepath); try { filestream fs = file.openread(filepath); if (extension.equals(".xls")) { //把xls文件中的数据写入wk中 wk = new hssfworkbook(fs); } else { //把xlsx文件中的数据写入wk中 wk = new xssfworkbook(fs); } fs.close(); //读取当前表数据 isheet sheet = wk.getsheetat(0); irow row = sheet.getrow(0); //读取当前行数据 //lastrownum 是当前表的总行数-1(注意) int offset = 0; for (int i = 0; i <= sheet.lastrownum; i++) { row = sheet.getrow(i); //读取当前行数据 if (row != null) { //lastcellnum 是当前行的总列数 for (int j = 0; j < row.lastcellnum; j++) { //读取该行的第j列数据 string value = row.getcell(j).tostring(); console.write(value.tostring() + " "); } console.writeline("\n"); } } } catch (exception e) { //只在debug模式下才输出 console.writeline(e.message); } }
excel中的单元格是有不同数据格式的,例如数字,日期,字符串等,在读取的时候可以根据格式的不同设置对象的不同类型,方便后期的数据处理。
//获取cell的数据,并设置为对应的数据类型 public object getcellvalue(icell cell) { object value = null; try { if (cell.celltype != celltype.blank) { switch (cell.celltype) { case celltype.numeric: // date comes here if (dateutil.iscelldateformatted(cell)) { value = cell.datecellvalue; } else { // numeric type value = cell.numericcellvalue; } break; case celltype.boolean: // boolean type value = cell.booleancellvalue; break; case celltype.formula: value = cell.cellformula; break; default: // string type value = cell.stringcellvalue; break; } } } catch (exception) { value = ""; } return value; }
特别注意的是celltype
中没有date,而日期类型的数据类型是numeric
,其实日期的数据在excel中也是以数字的形式存储。可以使用dateutil.iscelldateformatted
方法来判断是否是日期类型。
有了getcellvalue
方法,写数据到excel中的时候就要有setcellvalue
方法,缺的类型可以自己补。
//根据数据类型设置不同类型的cell public static void setcellvalue(icell cell, object obj) { if (obj.gettype() == typeof(int)) { cell.setcellvalue((int)obj); } else if (obj.gettype() == typeof(double)) { cell.setcellvalue((double)obj); } else if (obj.gettype() == typeof(irichtextstring)) { cell.setcellvalue((irichtextstring)obj); } else if (obj.gettype() == typeof(string)) { cell.setcellvalue(obj.tostring()); } else if (obj.gettype() == typeof(datetime)) { cell.setcellvalue((datetime)obj); } else if (obj.gettype() == typeof(bool)) { cell.setcellvalue((bool)obj); } else { cell.setcellvalue(obj.tostring()); } }
cell.setcellvalue()
方法只有四种重载方法,参数分别是string
, bool
, datetime
, double
, irichtextstring
设置公式使用cell.setcellformula(string formula)
写excel
以下是简单的例子,更多信息可以参见官网提供的examples。
public void writetoexcel(string filepath) { //创建工作薄 iworkbook wb; string extension = system.io.path.getextension(filepath); //根据指定的文件格式创建对应的类 if (extension.equals(".xls")) { wb = new hssfworkbook(); } else { wb = new xssfworkbook(); } icellstyle style1 = wb.createcellstyle();//样式 style1.alignment = npoi.ss.usermodel.horizontalalignment.left;//文字水平对齐方式 style1.verticalalignment = npoi.ss.usermodel.verticalalignment.center;//文字垂直对齐方式 //设置边框 style1.borderbottom = npoi.ss.usermodel.borderstyle.thin; style1.borderleft = npoi.ss.usermodel.borderstyle.thin; style1.borderright = npoi.ss.usermodel.borderstyle.thin; style1.bordertop = npoi.ss.usermodel.borderstyle.thin; style1.wraptext = true;//自动换行 icellstyle style2 = wb.createcellstyle();//样式 ifont font1 = wb.createfont();//字体 font1.fontname = "楷体"; font1.color = hssfcolor.red.index;//字体颜色 font1.boldweight = (short)fontboldweight.normal;//字体加粗样式 style2.setfont(font1);//样式里的字体设置具体的字体样式 //设置背景色 style2.fillforegroundcolor = npoi.hssf.util.hssfcolor.yellow.index; style2.fillpattern = fillpattern.solidforeground; style2.fillbackgroundcolor = npoi.hssf.util.hssfcolor.yellow.index; style2.alignment = npoi.ss.usermodel.horizontalalignment.left;//文字水平对齐方式 style2.verticalalignment = npoi.ss.usermodel.verticalalignment.center;//文字垂直对齐方式 icellstyle datestyle = wb.createcellstyle();//样式 datestyle.alignment = npoi.ss.usermodel.horizontalalignment.left;//文字水平对齐方式 datestyle.verticalalignment = npoi.ss.usermodel.verticalalignment.center;//文字垂直对齐方式 //设置数据显示格式 idataformat dataformatcustom = wb.createdataformat(); datestyle.dataformat = dataformatcustom.getformat("yyyy-mm-dd hh:mm:ss"); //创建一个表单 isheet sheet = wb.createsheet("sheet0"); //设置列宽 int[] columnwidth = { 10, 10, 20, 10 }; for (int i = 0; i < columnwidth.length; i++) { //设置列宽度,256*字符数,因为单位是1/256个字符 sheet.setcolumnwidth(i, 256 * columnwidth[i]); } //测试数据 int rowcount = 3, columncount = 4; object[,] data = { {"列0", "列1", "列2", "列3"}, {"", 400, 5.2, 6.01}, {"", true, "2014-07-02", datetime.now} //日期可以直接传字符串,npoi会自动识别 //如果是datetime类型,则要设置cellstyle.dataformat,否则会显示为数字 }; irow row; icell cell; for (int i = 0; i < rowcount; i++) { row = sheet.createrow(i);//创建第i行 for (int j = 0; j < columncount; j++) { cell = row.createcell(j);//创建第j列 cell.cellstyle = j % 2 == 0 ? style1 : style2; //根据数据类型设置不同类型的cell object obj = data[i, j]; setcellvalue(cell, data[i, j]); //如果是日期,则设置日期显示的格式 if (obj.gettype() == typeof(datetime)) { cell.cellstyle = datestyle; } //如果要根据内容自动调整列宽,需要先setcellvalue再调用 //sheet.autosizecolumn(j); } } //合并单元格,如果要合并的单元格中都有数据,只会保留左上角的 //cellrangeaddress(0, 2, 0, 0),合并0-2行,0-0列的单元格 cellrangeaddress region = new cellrangeaddress(0, 2, 0, 0); sheet.addmergedregion(region); try { filestream fs = file.openwrite(filepath); wb.write(fs);//向打开的这个excel文件中写入表单并保存。 fs.close(); } catch (exception e) { debug.writeline(e.message); } }
如果想要设置单元格为只读或可写,可以参考,方法如下:
icellstyle unlocked = wb.createcellstyle(); unlocked.islocked = false;//设置该单元格为非锁定 cell.setcellvalue("未被锁定"); cell.cellstyle = unlocked; ... //保护表单,password为解锁密码 //cell.cellstyle.islocked = true;的单元格将为只读 sheet.protectsheet("password");
cell.cellstyle.islocked
默认就是true,
因此sheet.protectsheet("password")
一定要执行,
才能实现锁定单元格,对于不想锁定的单元格,
就一定要设置cell
的cellstyle
中的islocked = false
下一篇: java中的语法糖