C# NPOI读写Excel
来源:互联网 发布:网络任务兼职 编辑:程序博客网 时间:2024/04/29 09:08
上次写了一个java POI读写excel的工具类,JAVA中读写excel有同样的方法,即是NPOI,NPOI的DLL下载地址NPOI下载地址,这两个应该是一个东西,用法相同,这个封装的方法其实是和JAVA的那个封装了同样的功能,但也稍微有点不同,这个封装了应该比java那个稍微好用一点,其他废话不说了,直接上代码:
1、读取Excel
<span style="font-size:14px;"> /// <summary> /// 读取excel /// </summary> /// <typeparam name="T">实体类</typeparam> /// <param name="path">文件路径</param> /// <param name="stream">文件流</param> /// <param name="skipTitls">是否跳过首行</param> /// <returns>返回集合</returns> public static List<T> ReadExcelFile<T>(string path, Stream stream, bool skipTitls = true) { List<T> listT = new List<T>(); //if (stream == null && string.IsNullOrEmpty(path)) //{ // return listT; //} if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path)) //判断文件存在 { FileStream fStream = new FileStream(path, FileMode.Open, FileAccess.Read); stream = fStream; } if (stream == null) { return listT; } Type ttype = typeof(T); PropertyInfo[] pinfo = ttype.GetProperties();//获取实体属性数组 HSSFWorkbook wk = new HSSFWorkbook(stream); for (int i = 0; i < wk.NumberOfSheets; i++) { ISheet sheet = wk.GetSheetAt(i); //读取sheet int j = 0; if (skipTitls) //跳过首行 { j = 1; } for (int lastRow = sheet.LastRowNum; j <= lastRow; j++) { IRow row = sheet.GetRow(j); if (row == null) { continue; } T tobj = (T)Activator.CreateInstance(ttype); //新建对象 for (int k = 0, rowlastnum = row.LastCellNum; k <= rowlastnum; k++) { ICell cell = row.GetCell(k); if (cell == null || cell.ToString().Trim() == "") { //pinfo[k].SetValue(tobj, ""); continue; } try { var cellvalue = Convert.ChangeType(cell.ToString().Trim(), pinfo[k].PropertyType);//类型强转 pinfo[k].SetValue(tobj, cellvalue);//属性赋值 } catch (Exception e) { //string cellindex = "sheet=" + i + "++row=" + j + "+cell=+" + k; //throw e; } } listT.Add(tobj); } } return listT; }</span>
同样用的反射来进行读取,里面代码就不介绍了,就只强调一点,这里读取分为路径读取和流读取,当路径为空的时候,默认以流参数为准,如果流为空则返回集合,如果路径不为空,且路径文件存在,则以路径参数为准,JAVA的那个介绍的已经很清楚了,接下来excel的导出方法:
2、Excel导出
<span style="font-size:14px;"> /// <summary> /// 导出excel /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="list">要导出的集合</param> /// <param name="excelname">文件及sheet名</param> /// <param name="isUsetitles">是否用标题,true用,false 不用</param> /// <param name="titles">标题</param> /// <returns>返回导出状态</returns> public static bool ExportExcel<T>(List<T> list, String excelname, bool isUsetitles = false, params String[] titles) { bool resultBool = false; if (list == null || list.Count <= 0) { return resultBool; //空集合返回false } if (string.IsNullOrEmpty(excelname)) { excelname = DateTime.Now.ToString("yyyyMMddhhmmss");//无文件名默认取当前的时间 } HSSFWorkbook hbook = Hssbook<T>(list, excelname, isUsetitles, titles);//要导出的sheet HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.xls", excelname));//设置导出头信息 MemoryStream mStream = null; try { mStream = new MemoryStream(); hbook.Write(mStream); //写入内存流 HttpContext.Current.Response.BinaryWrite(mStream.ToArray()); hbook = null; mStream.Close(); mStream.Dispose(); //释放关闭流信息 resultBool = true; } catch (Exception e) { if (mStream != null) { hbook = null; mStream.Close(); mStream.Dispose(); } } //HttpContext.Current.Response.End(); return resultBool; }</span>
同样的最后的可变参数用来设置要导出内容每列的标头,但是不同的是加了一个bool的参数isUseTitles,默认为false,不使用自定义的每列的标头,即你集合是什么内容,结果就导出什么内容,不会有每列的标题信息,当这个参数为ture的时候是使用标题列,因此,每列第一行会设置你自定义的标题。
private static HSSFWorkbook Hssbook<T>(List<T> list, String excelname, bool isUsetitles = false, params String[] titles) { Type ttype = typeof(T); PropertyInfo[] pinfos = ttype.GetProperties(); HSSFWorkbook workbook = new HSSFWorkbook(); ISheet sheet = workbook.CreateSheet(excelname);//新建sheet ICellStyle hstyle = workbook.CreateCellStyle(); hstyle.VerticalAlignment = VerticalAlignment.Center; //水平居中 int count = titles.Length; int celllen = pinfos.Length; //IRow row = sheet.CreateRow(0); if (isUsetitles) //判断是否使用自定义头信息 { IRow row = sheet.CreateRow(0); for (int i = 0; i < count; i++) { ICell cell = row.CreateCell(i); cell.SetCellValue(titles[i]); cell.CellStyle = hstyle; sheet.AutoSizeColumn(i); } celllen = count; } else { //或者可以在不使用头的时候用字段的属性值,但这样感觉没必要 //IRow row = sheet.CreateRow(0); //for (int i = 0; i < celllen; i++) //{ // ICell cell = row.CreateCell(i); // cell.SetCellValue(pinfos[i].Name); // cell.CellStyle = hstyle; // sheet.AutoSizeColumn(i); //} } // int celllen = pinfos.Length > count&&isUsetitles? count : pinfos.Length; for (int i = 0, rowlen = list.Count; i < rowlen; i++) { int forindex = i; if (isUsetitles) { forindex++; } // IRow rowitem = sheet.CreateRow(i + 1); IRow rowitem = sheet.CreateRow(forindex); for (int j = 0; j < celllen; j++) { //String fileString = ""; ICell itemcell = rowitem.CreateCell(j); object obvalue = pinfos[j].GetValue(list[i]);//取值 if (obvalue == null) { continue; } //if (obvalue != null) //{ String fileString = obvalue.ToString(); // } itemcell.SetCellValue(fileString); sheet.AutoSizeColumn(j); } } return workbook; }
有一点要注意,当你把isUseTitles设置为true的时候,要导出的列的数量就不会根据你list集合对象字段的数量来确定,而是根据你设置的标头的数量来确定,你有两个标头,他就会导出两列,四个标头导出四列,如果你在可变参数中没有自定义设置标头,那么他一列都不会导出,直接是空画布。
导出的用法都一样,就直接把那个复制过来了,如下:
<input type="button" onclick="ExportExcel()" value="导出EXCEL" /> <script type="text/javascript"> function ExportExcel(){ location.href="ExportExcel";//请求地址 } </script>
好了,写到这里吧,要睡觉了,有啥不明白的可以看我写的那个java POI读写Excel的文章,那个写的详细一点,用法基本相同。结束了,有啥不对或者需要优化的地方请大家批评指出,我会尽快改正。谢谢!!
1 0
- C# NPOI读写Excel
- C# NPOI 读写 Excel
- C#使用NPOI读写excel
- C# WPF 利用NPOI读写Excel文件。
- 用npoi,读写excel
- NPOI 读写excel
- Excel读写NPOI
- NPOI读写Excel
- NPOI读写Excel
- NPOI读写Excel
- NPOI 读写excel
- NPOI读写Excel
- NPOI读写Excel
- NPOI读写Excel
- C# 使用 NPOI 库读写 Excel 文件(转载)
- C# NPOI 操作excel
- C# NPOI 操作excel
- C# NPOI导入Excel
- ubuntu下编译openjdk7
- SRM540
- 数据结构与算法基本概念总结
- 【RESTful】Yii2实现RESTful架构配置最佳实践
- Swift 中的过滤器详解
- C# NPOI读写Excel
- android发送邮件
- Angular2 RC1 在vs2013下的环境搭建
- 正则表达式
- android 屏幕适配实用的
- Fragment Home键返回桌面再打开程序,无法开启
- 卸载oracle11g client
- Groovy下载文件并实时显示下载进度
- Python if 和 for 的多种写法