C#通过NPOI操作Excel的实例代码
程序员文章站
2022-06-17 21:19:43
c#操作excel的方法有很多种,常见的有微软官方的ole automation,apache的poi等。这里介绍的是poi翻译成c#的npoi。
poi是apache的...
c#操作excel的方法有很多种,常见的有微软官方的ole automation,apache的poi等。这里介绍的是poi翻译成c#的npoi。
poi是apache的通过java操作office的一个api,可以对excel,word,ppt等进行操作,十分的强大。然后就被翻译成c#版本的npoi了,和log4j与log4net很相似。
好像在npoi的.net4.0版本之前是不支持office2007及以上的xml格式的,但是最新的版本已经支持了。只需要下载并引用下面五个程序集就能使用了。
这里提供一个操作excel的类,类中提供了4个方法,两个导出,两个导入。可以通过dataset导出拥有多个sheet的excel文件,也可以通过datatable导出拥有一个sheet的excel。导入也是一样,通过指定sheet索引,导出datatable,或者直接导出所有sheet返回一个dataset。
public class excelhelper { /// <summary> /// 根据excel和sheet返回datatable /// </summary> /// <param name="filepath">excel文件地址</param> /// <param name="sheetindex">sheet索引</param> /// <returns>datatable</returns> public static datatable getdatatable(string filepath, int sheetindex) { return getdataset(filepath, sheetindex).tables[0]; } /// <summary> /// 根据excel返回dataset /// </summary> /// <param name="filepath">excel文件地址</param> /// <param name="sheetindex">sheet索引,可选,默认返回所有sheet</param> /// <returns>dataset</returns> public static dataset getdataset(string filepath, int? sheetindex = null) { dataset ds = new dataset(); iworkbook fileworkbook; using (filestream fs = new filestream(filepath, filemode.open, fileaccess.read)) { if (filepath.last() == 's') { try { fileworkbook = new hssfworkbook(fs); } catch (exception ex) { throw ex; } } else { try { fileworkbook = new xssfworkbook(fs); } catch { fileworkbook = new hssfworkbook(fs); } } } for (int i = 0; i < fileworkbook.numberofsheets; i++) { if (sheetindex != null && sheetindex != i) continue; datatable dt = new datatable(); isheet sheet = fileworkbook.getsheetat(i); //表头 irow header = sheet.getrow(sheet.firstrownum); list<int> columns = new list<int>(); for (int j = 0; j < header.lastcellnum; j++) { object obj = getvaluetypeforxls(header.getcell(j) as hssfcell); if (obj == null || obj.tostring() == string.empty) { dt.columns.add(new datacolumn("columns" + j.tostring())); } else dt.columns.add(new datacolumn(obj.tostring())); columns.add(j); } //数据 ienumerator rows = sheet.getenumerator(); while (rows.movenext()) { int j = sheet.firstrownum + 1; datarow dr = dt.newrow(); bool hasvalue = false; foreach (int k in columns) { dr[k] = getvaluetypeforxls(sheet.getrow(k).getcell(k) as hssfcell); if (dr[k] != null && dr[k].tostring() != string.empty) { hasvalue = true; } } if (hasvalue) { dt.rows.add(dr); } j++; } ds.tables.add(dt); } return ds; } /// <summary> /// 根据datatable导出excel /// </summary> /// <param name="dt">datatable</param> /// <param name="file">保存地址</param> public static void getexcelbydatatable(datatable dt, string file) { dataset ds = new dataset(); ds.tables.add(dt); getexcelbydataset(ds, file); } /// <summary> /// 根据dataset导出excel /// </summary> /// <param name="ds">dataset</param> /// <param name="file">保存地址</param> public static void getexcelbydataset(dataset ds, string file) { iworkbook fileworkbook = new hssfworkbook(); int index = 0; foreach (datatable dt in ds.tables) { index++; isheet sheet = fileworkbook.createsheet("sheet" + index); //表头 irow row = sheet.createrow(0); for (int i = 0; i < dt.columns.count; i++) { icell cell = row.createcell(i); cell.setcellvalue(dt.columns[i].columnname); } //数据 for (int i = 0; i < dt.rows.count; i++) { irow row1 = sheet.createrow(i + 1); for (int j = 0; j < dt.columns.count; j++) { icell cell = row1.createcell(j); cell.setcellvalue(dt.rows[i][j].tostring()); } } } //转为字节数组 memorystream stream = new memorystream(); fileworkbook.write(stream); var buf = stream.toarray(); //保存为excel文件 using (filestream fs = new filestream(file, filemode.create, fileaccess.write)) { fs.write(buf, 0, buf.length); fs.flush(); } } /// <summary> /// 根据单元格将内容返回为对应类型的数据 /// </summary> /// <param name="cell">单元格</param> /// <returns>数据</returns> private static object getvaluetypeforxls(hssfcell cell) { if (cell == null) return null; switch (cell.celltype) { case celltype.blank: //blank: return null; case celltype.boolean: //boolean: return cell.booleancellvalue; case celltype.numeric: //numeric: return cell.numericcellvalue; case celltype.string: //string: return cell.stringcellvalue; case celltype.error: //error: return cell.errorcellvalue; case celltype.formula: //formula: default: return "=" + cell.cellformula; } } }
这里面可以有一些有意思的操作,比如版本兼容问题。这里通过多态很好的实现了兼容,但是如果是2007版本的xlsm被修改为xsl的后缀怎么办呢,或者2003版本的被修改为xlsm后缀怎么办呢。2003版本改为xlsm还是可以将其视为xls来处理的,但是2007改为xls就不行了。这时候可以强行修改文件的后缀名再打开。
但是上面的代码没有实现这个功能,两个原因:一、这样做不是很安全。二、这时候需要修改系统中其它地方此文件的文件名,放在类中实现不是很方便。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。