Npoi 使用总结 回顾 反思

简介: 好几天没有写博客了,突然间有种写博客的冲动,虽然我的技术能力还是在努力的进步,但是和那些大牛比起来,我确实是小菜一枚,不过这并没有打击我的积极性,反而让我有种冲动,去超越他们。哈哈 我记得在几天前我说过一个Lucene.net,是从java中借鉴过来的,现在我来说一下Npoi吧,当然这个也是从java借鉴过来的,不过这个语法没有Lucene.net那么恶心,Lucene.net是完全的java版,但是npoi.net最起码有点和.net联系在了一起。

好几天没有写博客了,突然间有种写博客的冲动,虽然我的技术能力还是在努力的进步,但是和那些大牛比起来,我确实是小菜一枚,不过这并没有打击我的积极性,反而让我有种冲动,去超越他们。哈哈

我记得在几天前我说过一个Lucene.net,是从java中借鉴过来的,现在我来说一下Npoi吧,当然这个也是从java借鉴过来的,不过这个语法没有Lucene.net那么恶心,Lucene.net是完全的java版,但是npoi.net最起码有点和.net联系在了一起。好东西都是java的,.net大牛们,你们在干嘛,开发一些优秀的东西吧,别总让java鄙视我们。

好了,说说Npoi.net吧,Npoi是对Excel(或者叫office比较合适)进行操作的一个类库框架,我们可以不再使用office提供的那个恶心的接口(速度慢)来操作了,我们对于office的操作解放了。现在最新版的应该是1.2.5.如果你安装了NuGet的话,可以很容易的获取。

因为Excel 2003极其以前的版本采用的底层代码和Excel 2007 及其以后的不同,所以对于这个分界点是需要我们注意的。为什么会出现这个分界点,大家想一下,现在微软的所有东西都在.net 架构之下,以前的Excel版本和这个架构肯定是不同的。

我们重点来说excel。毕竟这是在我们的工作中用的最多的一个,Excel包括文件(file,在Npoi.net中称为workBook 工作簿)、工作表(sheet)以及里面的单元格,按照从大到小的分类就是文件中包含若干个sheet,每个sheet中包含很多单元格。这是Excel的分类。

为了操作Excel,npoi.net当然也需要对应的类来对应不同的分类,其中

HSSFWorkbook对应的就是Excel文件  工作簿,

HSSFSheet对应的就是Excel中sheet 工作表,

HSSFCell对应的就是Excel的单元格,

HSSFRow对应的就是Excel的行。

有了这几个不同的类,我们就可以创建Excel文件,创建sheet,给sheet重命名或删除sheet,创建行,添加单元格,为单元格设置格式,我个人感觉其他的都很简单,唯独这个给单元格设置格式的做法很令人讨厌,没办法用的别人的,只能有苦自己承受了。

下面我就举一个很简单的例子来说明一下npoi.net的整体使用,如果有任何说错的地方,还请你指出来,小菜谢过了。

我个人认为会遇到的问题我都在注释中写了,

  1     public class NpoiNet
  2     {
  3         public void CreateWorkBook()
  4         {
  5             string filePath = HttpContext.Current.Server.MapPath("~/npoi.xls");
  6             //表示一个文件流
  7             FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
  8             HSSFWorkbook workBook = new HSSFWorkbook();//相当于创建了一个内存中的Excel 只是还没有写到硬盘上
  9             try
 10             {
 11                 /*按照约定在每个Excel文件中至少要包含一个sheet,如果没有任何sheet,打开Excel文件的时候会报错。
 12                在以前的npoi版本中,如果不是自己手动的创建一个sheet,npoi框架是不会自动创建一个的,但是在最新版的1.2.5中,
 13                我发现即使你忘记了创建sheet的操作,框架会自动创建一个sheet,当然如果你手动创建了一个sheet,则框架就不会
 14                 自动的创建一个sheet,这就像构造函数,如果没有写任何一个,.Net会默认存在一个,但是你创建了一个构造函数,则
 15                  * 框架就不会自动创建了
 16                  * */
 17 
 18                 workBook.CreateSheet("guozhiqi");//sheet的名称为guozhiqi
 19                 workBook.CreateSheet();//sheet的名称为sheet1  从1开始命名
 20                 workBook.CreateSheet("yuanjinzhou");
 21                 workBook.CreateSheet();//这个sheet的名称应该为什么?答案是sheet3
 22                 //创建了sheet 下面我们来创建单元格
 23                 HSSFSheet sheetGuozhiqi = (HSSFSheet)workBook.GetSheet("guozhiqi");//获取到sheet名称为guozhiqi的那个工作簿
 24                 //创建了工作簿 添加单元格之前首先要添加行
 25                 //在这里请注意  行和列的下标都是从0开始的 而不是Excel文件中的1
 26                 for (int i = 0; i <= 10; i++)
 27                 {
 28                     sheetGuozhiqi.CreateRow(i);//创建了11行
 29                 }
 30 
 31                 //创建了行之后 就要在每个行中创建单元格
 32                 //如果没有在之前创建行
 33                 //  HSSFRow newRow = (HSSFRow)sheetGuozhiqi.GetRow(12);这是错误的 程序会报异常 这就告诉我们 如果行还没有创建
 34                 //就不可以获取
 35                 HSSFRow newRow = (HSSFRow)sheetGuozhiqi.GetRow(0);
 36 
 37                 HSSFCell[] cells = new HSSFCell[11];
 38                 //在第0行的位置创建单元格
 39                 for (int i = 0; i <= 10; i++)
 40                 {
 41                     cells[i] = (HSSFCell)newRow.CreateCell(i);//为第0行创建了10个单元格 
 42                 }
 43                 //这里取得单元格的异常出现位置相同 就是如果没有创建就不要试图获取
 44                 HSSFCell newCell = (HSSFCell)newRow.GetCell(0);//取得第0行第0个单元格
 45 
 46                 //获取到了单元格 赋值 为了方便说明 我多获取几个单元格的值
 47                 //Excel单元格有很多类型 例如字符串 数字 bool等类型,
 48                 cells[0].SetCellValue(false);//赋值为bool型
 49                 cells[1].SetCellValue(DateTime.Now);//赋值为日期型
 50                 cells[2].SetCellValue(3.1415926);//赋值为double类型
 51                 cells[3].SetCellValue("guozhiqi");//赋值为字符串guozhiqi
 52 
 53                 //为单元格赋值以后 我们就要开始取值了
 54                 bool cell0 = cells[0].BooleanCellValue;
 55                // string cell00 = cells[0].StringCellValue; 错误 这句话的意思就是说存储的时候是什么类型 就必须用对应的
 56                 //取值方法取值
 57                 DateTime dateTime = cells[1].DateCellValue;
 58                 double cell2 = cells[2].NumericCellValue;
 59                 string cell3 = cells[3].StringCellValue;
 60 
 61                 //可以正常创建单元格 从单元格取值是远远不够的 还有就是客户可能会要求合并单元格  为单元格设置样式
 62                 //合并单元格的操作不必要创建所有的行或列,只需要制定范围即可
 63                 sheetGuozhiqi.AddMergedRegion(new NPOI.SS.Util.Region(1,1,20,20));//合并单元格
 64 
 65                 HSSFCellStyle cellStyle = (HSSFCellStyle)workBook.CreateCellStyle();
 66                 cellStyle.Alignment = HorizontalAlignment.CENTER;//居中显示
 67                 cellStyle.FillBackgroundColor = 244;
 68                 cellStyle.FillPattern = FillPatternType.BRICKS;//填充模式
 69                 cellStyle.IsHidden = false;//单元格是否隐藏
 70                 cellStyle.IsLocked = false;//单元格是否锁定
 71                 cellStyle.VerticalAlignment = VerticalAlignment.CENTER;//垂直居中
 72                 
 73                 //设置单元格字体
 74                 HSSFFont font =(HSSFFont) workBook.CreateFont();
 75                 font.Color = 200;
 76                 font.FontHeight = 18;//设置字体大小
 77                 font.FontName = "黑体";//设置字体为黑体
 78                 font.IsItalic = false;//是否是斜体
 79                 font.IsStrikeout = true;//是否有中间线
 80                 font.Underline = (byte)FontUnderlineType.DOUBLE;//设置下划线
 81 
 82                 cellStyle.SetFont(font);
 83                 //将设置好的样式应用到对应的单元格上 否则是没有效果的
 84                 cells[0].CellStyle = cellStyle;
 85 
 86                 if (!workBook.IsWriteProtected)
 87                 {
 88                     workBook.Write(fileStream);
 89                 }
 90             }
 91             catch (Exception ex)
 92             {
 93                 HttpContext.Current.Response.Write(ex.Message+ex.Source+ex.StackTrace);
 94             }
 95             finally
 96             {
 97                 if (fileStream != null)
 98                 {
 99                     fileStream.Close();
100                 }
101             }
102         }
103     }

总结,既然这篇博客是Npoi.net的总结,那么我不可能就是举了一个例子就算了事,毕竟博客园中园友们举得例子已经够多了,下面我就把在使用npoi.net会遇到的一些小问题总结一下。

  1. 在实例化了一个WorkBook之后,最好添加一个sheet,虽然在最新版的Npoi.net中自动添加了,但是遇到迁移到原来版本就会出现问题。所以我建议还是最少添加一个sheet
  2. 在从单元格取值时要注意单元格的类型,一定要用对应的类型的方法来取单元格中的对应类型的值,如果不确定,那只能是强制转换成为string类型,毕竟string类型是excel中其他类型都可以转换过来的
  3. 在获取sheet中的某一行或者某一行的某一个单元格的时候,还要注意就是一定要确保创建了该行,并且取单元格还要确保创建了单元格,否则会报Null reference not to object 这个我们经常会看到的异常信息。在外层一定要加上try捕获异常
  4. 合并单元格是sheet的工作,因此需要获取对应的sheet,然后调用其AddMergedRegion方法合并单元格,在合并单元格的时候,我们不需要确保该单元格已经存在或创建。
  5. 在为单元格设置样式的过程中,我们会发现所有和样式相关的类的创建都是通过workBook.Create(Font)..这种方式来执行的,我们不可以直接new一个类的实例。
  6. 如果前面的工作都已经做好,需要把内存中的excel表写到硬盘上时,需要调用workBook.write()方法,传入一个文件流进行创建。在这里有可能会出现一个问题,就是你要创建的文件你已经打开了,这时程序就会出现异常,因此我们在调试程序的时候一定要记得打开了excel文件以后要关闭
  7. 最后需要注意的就是文件流,在我们把excel写到硬盘上以后,要显式的调用其close()方法关闭文件流。因为如果不关闭文件流的话,以后就会出现无法重新创建该文件的错误,并且会提示 某文件正由另一进程使用,因此该进程无法访问此文件

好了,我能想到的基本上都写出来了,感觉好多了,一会再分析一下c#类和结构的区别。相信很多园友都知道,但是不一定会很明确,那么我就来帮大家回忆一下曾经的学习。夜深人静,确实是写作的好时候。

我又回来了,回到了技术最前线,
相关文章
|
3月前
|
存储 测试技术 Python
软件测试/测试开发全日制|Pytest结合Excel实现数据驱动
软件测试/测试开发全日制|Pytest结合Excel实现数据驱动
40 0
|
12月前
|
消息中间件 存储 JavaScript
如何写出一手让同事膜拜的漂亮代码?
如何写出一手让同事膜拜的漂亮代码?
|
程序员 前端开发
关于程序员写好 ppt 的几点总结
程序员日常工作中最多的应该是接收需求、编码实现需求。但也有些时候需要做一些非代码的文字工作。
96 0
关于程序员写好 ppt 的几点总结
|
数据可视化 数据挖掘 数据处理
用数据讲故事:13条Excel进阶技巧总结
本文将分享笔者在学习过程中总结的一些不常见但很好用的Excel函数、图表及展现方式,希望能对你的数据处理及可视化有用。
274 0
用数据讲故事:13条Excel进阶技巧总结
|
监控 前端开发 jenkins
我用这一招让团队的开发效率提升了 100%!
我在一家做微信营销的公司干技术 leader,带 40 多个人,公司名就不说了。在这个位置上做了好几年,把团队从小带大,公司虽然不算风口浪尖上的高增长业务,但技术这块儿也从来没出过什么问题,我还是蛮自豪的。
|
前端开发 测试技术
干货 | 原来升职加薪的测试工程师都擅长做接口测试
干货 | 原来升职加薪的测试工程师都擅长做接口测试
Excel的这几小技巧,你绝对想不到!
Excel的这几小技巧,你绝对想不到!
Excel的这几小技巧,你绝对想不到!
|
Java 数据库连接
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!(二)
各位网友,大家好,我是阿粉! 最近刚入职一个新团队,还没来得及熟悉业务,甲方爸爸就要求项目要在2个月内完成开发并上线! 本想着往后推迟1个月在交付,但是甲方爸爸不同意,只能赶鸭子上架了! 然后根据业务需求,设计出了大概30多张表,如果这30多张表,全靠开发人员手写 crud,开发所需的时间肯定会大大的延长,甚至可能直接会影响交付时间! 于是就想着,能不能通过代码生成器一键搞定全部的 crud,开发团队只需要根据业务需求编写逻辑代码就可以?
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!(二)
|
Java 关系型数据库 MySQL
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!(一)
各位网友,大家好,我是阿粉! 最近刚入职一个新团队,还没来得及熟悉业务,甲方爸爸就要求项目要在2个月内完成开发并上线! 本想着往后推迟1个月在交付,但是甲方爸爸不同意,只能赶鸭子上架了! 然后根据业务需求,设计出了大概30多张表,如果这30多张表,全靠开发人员手写 crud,开发所需的时间肯定会大大的延长,甚至可能直接会影响交付时间! 于是就想着,能不能通过代码生成器一键搞定全部的 crud,开发团队只需要根据业务需求编写逻辑代码就可以?
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!(一)
团队里的妹子让阿粉跟她说说怎样写出好的代码
昨天,团队里的妹子很突然地就让阿粉跟她说说怎么才能写出一手好的代码 阿粉本着负责任的态度,专门写了一篇文章出来,妹子嘛,就是要宠的嘛