wangchao.org
添加收藏 | 博客
 
购物视频论坛IT业界自然风光美女图片王朝网络小游戏BT下载生活百科编程设计手机图铃小说
 
笑话 | 水库 | 娱乐 | 体育 | 英语 | 宠物 | 美食 | 旅游 | 养生 | 手机 | 数码 | 汽车 | 珠宝 | 美容 | 装修 | 厨房 | 科普 | 动物 | 植物 | 影音 | 百科 | 知道 | 词典
  
 
 您好! 您现在位于: 王朝网络 → 编程设计 → 《使用poi操作Excel的几点注意事项返回上一页 
 
1楼 

使用poi操作Excel的几点注意事项

  网上购物、在线购物、购物搜索 欢迎光临本站购买图书、影视、音乐、数码、百货,手机等商品。

  上好的人肉包子新鲜出炉啦,各位妖魔鬼怪赶紧来尝尝鲜……
  首先说说现在我所知道的Java编辑Excel文件的两大开源工具:jakarta poi和JavaExcelAPI(简称JXL),这两套工具我都试用了一这段时间,感觉各有优劣吧。poi在某些细节有些小Bug并且不支持写入图片,其他方面都挺不错的;JXL就惨了,除了支持写入图片外,我暂时看不到它比POI好的地方,我碰到的主要的问题就是对公式支持不是很好,很多带有公式的Excel文件用JXL打开后,公式就丢失了(比如now(),today()),在网上看到其他大虾评论说JXL写入公式也有问题,另外,JXL操作Excel文件的效率比POI低一点。经过比较后,我选择了poi开发我的项目。
  现在我要做的东西基本完成啦,我把这段时间使用poi的一些心得总结出来,希望能对和我碰到相同问题的朋友有所帮助,少熬几个夜,多点时间陪MM:),至于poi基本的使用方法,自己去看文档吧。
  1、设置分页符的bug。
  poi里的HSSFSheet类提供了setRowBreak方法可以设置Sheet的分页符。
  Bug:假如你要设置分页符的Sheet是本来就有的,并且你没有在里面插入过分页符,那么调用setRowBreak时POI会抛出空指针的异常。
  解决方法:在Excel里给这个sheet插入一个分页符,用POI打开后再把它删掉,然后你就可以随意插入分页符了。
  假如sheet是由poi生成的则没有这个问题。我跟踪了setRowBreak的源代码,发现是Sheet.java下的PageBreakRecord rowBreaks这个变量在搞鬼,假如Sheet里原来没有分页符,开发这个模块的那位兄台忘了为这个对象new实例,所以只能我们先手工给Excel插入一个分页符来触发poi为rowBreaks创建实例。
  2、如何拷贝行。
  我在gmane.org的poi用户论坛翻遍了每个相关的帖子,找遍了api,也没看到一个拷贝行的方法,没办法,只能自己写:
  //注:this.fWorkbook是一个HSSHWorkbook,请自行在外部new
  public void copyRows(String pSourceSheetName, String pTargetSheetName, int pStartRow, int pEndRow, int pPosition)
  {
  HSSFRow sourceRow = null;
  HSSFRow targetRow = null;
  HSSFCell sourceCell = null;
  HSSFCell targetCell = null;
  HSSFSheet sourceSheet = null;
  HSSFSheet targetSheet = null;
  Region region = null;
  int cType;
  int i;
  short j;
  int targetRowFrom;
  int targetRowTo;
  if ((pStartRow == -1) (pEndRow == -1))
  {
  return;
  }
  sourceSheet = this.fWorkbook.getSheet(pSourceSheetName);
  targetSheet = this.fWorkbook.getSheet(pTargetSheetName);
  //拷贝合并的单元格
  for (i = 0; i < sourceSheet.getNumMergedRegions(); i++)
  {
  region = sourceSheet.getMergedRegionAt(i);
  if ((region.getRowFrom() = pStartRow) && (region.getRowTo() <= pEndRow))
  {
  targetRowFrom = region.getRowFrom() - pStartRow + pPosition;
  targetRowTo = region.getRowTo() - pStartRow + pPosition;
  region.setRowFrom(targetRowFrom);
  region.setRowTo(targetRowTo);
  targetSheet.addMergedRegion(region);
  }
  }
  //设置列宽
  for (i = pStartRow; i <= pEndRow; i++)
  {
  sourceRow = sourceSheet.getRow(i);
  if (sourceRow != null)
  {
  for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)
  {
  targetSheet.setColumnWidth(j, sourceSheet.getColumnWidth(j));
  }
  break;
  }
  }
  //拷贝行并填充数据
  for (;i <= pEndRow; i++)
  {
  sourceRow = sourceSheet.getRow(i);
  if (sourceRow == null)
  {
  continue;
  }
  targetRow = targetSheet.createRow(i - pStartRow + pPosition);
  targetRow.setHeight(sourceRow.getHeight());
  for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)
  {
  sourceCell = sourceRow.getCell(j);
  if (sourceCell == null)
  {
  continue;
  }
  targetCell = targetRow.createCell(j);
  targetCell.setEncoding(sourceCell.getEncoding());
  targetCell.setCellStyle(sourceCell.getCellStyle());
  cType = sourceCell.getCellType();
  targetCell.setCellType(cType);
  switch (cType)
  {
  case HSSFCell.CELL_TYPE_BOOLEAN:
  targetCell.setCellValue(sourceCell.getBooleanCellValue());
  break;
  case HSSFCell.CELL_TYPE_ERROR:
  targetCell.setCellErrorValue(sourceCell.getErrorCellValue());
  break;
  case HSSFCell.CELL_TYPE_FORMULA:
  //parseFormula这个函数的用途在后面说明
  targetCell.setCellFormula(parseFormula(sourceCell.getCellFormula()));
  break;
  case HSSFCell.CELL_TYPE_NUMERIC:
  targetCell.setCellValue(sourceCell.getNumericCellValue());
  break;
  case HSSFCell.CELL_TYPE_STRING:
  targetCell.setCellValue(sourceCell.getStringCellValue());
  break;
  }
  }
  }
  }
  这个函数有两个问题暂时无法解决:
  a、只能在同一个Workbook里面使用,跨Workbook总是拷不过去,不知道为什么?
  b、由于在拷贝行时也把行高也拷过去了,假如往这些单元格里写入的数据长度超过单元格长度,那么他们不会自动调整行高!
  有哪位大侠知道上面两个问题任意一个的解决方法,请第一时间通知我!!!
  3、公式的问题。
  POI对Excel公式的支持是相当好的,但是我发现一个问题,假如公式里面的函数不带参数,比如now()或today(),那么你通过getCellFormula()取出来的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)),这样的值写入Excel是会出错的,这也是我上面copyRow的函数在写入公式前要调用parseFormula的原因,parseFormula这个函数的功能很简单,就是把ATTR(semiVolatile)删掉,我把它的代码贴出来:
  private String parseFormula(String pPOIFormula)
  {
  final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$
  StringBuffer result = null;
  int index;
  result = new StringBuffer();
  index = pPOIFormula.indexOf(cstReplaceString);
  if (index = 0)
  {
  result.append(pPOIFormula.substring(0, index));
  result.append(pPOIFormula.substring(index + cstReplaceString.length()));
  }
  else
  {
  result.append(pPOIFormula);
  }
  return result.toString();
  }
  至于为什么会出现ATTR(semiVolatile),希望哪位大侠现身跟我解释一下。
  4、向Excel写入图片的问题。
  我上poi论坛查相关帖子,得到两种结论:1、不支持写入图片;2、支持写入图片,通过EscherGraphics2d这个Class实现。于是我就去查EscherGraphics2d这个Class,发现这个Class提供了N个drawImage方法,喜出望外的我开始写代码,结果调了一天,一直看不到效果,黔驴技穷的我在万般无奈下只好跟踪进drawImage这个函数内部,经过N个函数调用后在最底层函数发现了最终答案(偶当场暴走!!!):
  public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
  int sx2, int sy2, Color bgColor, ImageObserver imageobserver)
  {
  if (logger.check( POILogger.WARN ))
  logger.log(POILogger.WARN,"drawImage() not supported");
  return true;
  }
  所以我强烈建议大家,以后使用第三方开发包一定尽量下载它的源代码,这样你在碰到问题时,看看它的的内部是怎么实现的,很多时候就可以不必重蹈我的覆辙了。既然POI不能写入图片,那我们只能把目光投向JXL,我用JXL写入图片功能是实现了,付出的代价是now()和today()这些函数丢失掉了,鱼与熊掌不能兼得吧,至于怎么解决JXL公式的问题,到下面这个帖子里和我一起守株待兔吧:
  http://community.csdn.net/EXPert/topic/3569/3569340.XML?temp=.8480646
  好了我所知道得就这些,我接触poi也才几星期时间,上面有些内容可能说得并不正确,希望各位大虾砸砖指正!

  上好的人肉包子新鲜出炉啦,各位妖魔鬼怪赶紧来尝尝鲜……      首先说说现在我所知道的Java编辑Excel文件的两大开源工具:jakarta poi和JavaExcelAPI(简称JXL),这两套工具我都试用了一这段时间,感觉各有优劣吧。poi在某些细节有些小Bug并且不支持写入图片,其他方面都挺不错的;JXL就惨了,除了支持写入图片外,我暂时看不到它比POI好的地方,我碰到的主要的问题就是对公式支持不是很好,很多带有公式的Excel文件用JXL打开后,公式就丢失了(比如now(),today()),在网上看到其他大虾评论说JXL写入公式也有问题,另外,JXL操作Excel文件的效率比POI低一点。经过比较后,我选择了poi开发我的项目。      现在我要做的东西基本完成啦,我把这段时间使用poi的一些心得总结出来,希望能对和我碰到相同问题的朋友有所帮助,少熬几个夜,多点时间陪MM:),至于poi基本的使用方法,自己去看文档吧。      1、设置分页符的bug。      poi里的HSSFSheet类提供了setRowBreak方法可以设置Sheet的分页符。      Bug:假如你要设置分页符的Sheet是本来就有的,并且你没有在里面插入过分页符,那么调用setRowBreak时POI会抛出空指针的异常。      解决方法:在Excel里给这个sheet插入一个分页符,用POI打开后再把它删掉,然后你就可以随意插入分页符了。      假如sheet是由poi生成的则没有这个问题。我跟踪了setRowBreak的源代码,发现是Sheet.java下的PageBreakRecord rowBreaks这个变量在搞鬼,假如Sheet里原来没有分页符,开发这个模块的那位兄台忘了为这个对象new实例,所以只能我们先手工给Excel插入一个分页符来触发poi为rowBreaks创建实例。      2、如何拷贝行。      我在gmane.org的poi用户论坛翻遍了每个相关的帖子,找遍了api,也没看到一个拷贝行的方法,没办法,只能自己写:      //注:this.fWorkbook是一个HSSHWorkbook,请自行在外部new   public void copyRows(String pSourceSheetName, String pTargetSheetName, int pStartRow, int pEndRow, int pPosition)   {   HSSFRow sourceRow = null;   HSSFRow targetRow = null;   HSSFCell sourceCell = null;   HSSFCell targetCell = null;   HSSFSheet sourceSheet = null;   HSSFSheet targetSheet = null;   Region region = null;   int cType;   int i;   short j;   int targetRowFrom;   int targetRowTo;      if ((pStartRow == -1) (pEndRow == -1))   {   return;   }   sourceSheet = this.fWorkbook.getSheet(pSourceSheetName);   targetSheet = this.fWorkbook.getSheet(pTargetSheetName);   //拷贝合并的单元格   for (i = 0; i < sourceSheet.getNumMergedRegions(); i++)   {   region = sourceSheet.getMergedRegionAt(i);   if ((region.getRowFrom() = pStartRow) && (region.getRowTo() <= pEndRow))   {   targetRowFrom = region.getRowFrom() - pStartRow + pPosition;   targetRowTo = region.getRowTo() - pStartRow + pPosition;   region.setRowFrom(targetRowFrom);   region.setRowTo(targetRowTo);   targetSheet.addMergedRegion(region);   }   }   //设置列宽   for (i = pStartRow; i <= pEndRow; i++)   {   sourceRow = sourceSheet.getRow(i);   if (sourceRow != null)   {   for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)   {   targetSheet.setColumnWidth(j, sourceSheet.getColumnWidth(j));   }   break;   }   }   //拷贝行并填充数据   for (;i <= pEndRow; i++)   {   sourceRow = sourceSheet.getRow(i);   if (sourceRow == null)   {   continue;   }   targetRow = targetSheet.createRow(i - pStartRow + pPosition);   targetRow.setHeight(sourceRow.getHeight());   for (j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++)   {   sourceCell = sourceRow.getCell(j);   if (sourceCell == null)   {   continue;   }   targetCell = targetRow.createCell(j);   targetCell.setEncoding(sourceCell.getEncoding());   targetCell.setCellStyle(sourceCell.getCellStyle());   cType = sourceCell.getCellType();   targetCell.setCellType(cType);   switch (cType)   {   case HSSFCell.CELL_TYPE_BOOLEAN:   targetCell.setCellValue(sourceCell.getBooleanCellValue());   break;   case HSSFCell.CELL_TYPE_ERROR:   targetCell.setCellErrorValue(sourceCell.getErrorCellValue());   break;   case HSSFCell.CELL_TYPE_FORMULA:   //parseFormula这个函数的用途在后面说明   targetCell.setCellFormula(parseFormula(sourceCell.getCellFormula()));   break;   case HSSFCell.CELL_TYPE_NUMERIC:   targetCell.setCellValue(sourceCell.getNumericCellValue());   break;   case HSSFCell.CELL_TYPE_STRING:   targetCell.setCellValue(sourceCell.getStringCellValue());   break;   }   }   }   }      这个函数有两个问题暂时无法解决:      a、只能在同一个Workbook里面使用,跨Workbook总是拷不过去,不知道为什么?      b、由于在拷贝行时也把行高也拷过去了,假如往这些单元格里写入的数据长度超过单元格长度,那么他们不会自动调整行高!      有哪位大侠知道上面两个问题任意一个的解决方法,请第一时间通知我!!!      3、公式的问题。      POI对Excel公式的支持是相当好的,但是我发现一个问题,假如公式里面的函数不带参数,比如now()或today(),那么你通过getCellFormula()取出来的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)),这样的值写入Excel是会出错的,这也是我上面copyRow的函数在写入公式前要调用parseFormula的原因,parseFormula这个函数的功能很简单,就是把ATTR(semiVolatile)删掉,我把它的代码贴出来:   private String parseFormula(String pPOIFormula)   {   final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$   StringBuffer result = null;   int index;      result = new StringBuffer();   index = pPOIFormula.indexOf(cstReplaceString);   if (index = 0)   {   result.append(pPOIFormula.substring(0, index));   result.append(pPOIFormula.substring(index + cstReplaceString.length()));   }   else   {   result.append(pPOIFormula);   }      return result.toString();   }   至于为什么会出现ATTR(semiVolatile),希望哪位大侠现身跟我解释一下。      4、向Excel写入图片的问题。      我上poi论坛查相关帖子,得到两种结论:1、不支持写入图片;2、支持写入图片,通过EscherGraphics2d这个Class实现。于是我就去查EscherGraphics2d这个Class,发现这个Class提供了N个drawImage方法,喜出望外的我开始写代码,结果调了一天,一直看不到效果,黔驴技穷的我在万般无奈下只好跟踪进drawImage这个函数内部,经过N个函数调用后在最底层函数发现了最终答案(偶当场暴走!!!):      public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,   int sx2, int sy2, Color bgColor, ImageObserver imageobserver)   {   if (logger.check( POILogger.WARN ))   logger.log(POILogger.WARN,"drawImage() not supported");   return true;   }   所以我强烈建议大家,以后使用第三方开发包一定尽量下载它的源代码,这样你在碰到问题时,看看它的的内部是怎么实现的,很多时候就可以不必重蹈我的覆辙了。既然POI不能写入图片,那我们只能把目光投向JXL,我用JXL写入图片功能是实现了,付出的代价是now()和today()这些函数丢失掉了,鱼与熊掌不能兼得吧,至于怎么解决JXL公式的问题,到下面这个帖子里和我一起守株待兔吧:      http://community.csdn.net/EXPert/topic/3569/3569340.XML?temp=.8480646      好了我所知道得就这些,我接触poi也才几星期时间,上面有些内容可能说得并不正确,希望各位大虾砸砖指正!

 
标签: Excel  poi  使用  几点  操作  注意事项  
 
您可以将本页贴到其他网站
UBB代码HTML代码
 
 
 
 
 
 
 更多内容
 ·基于角色的内容管理权限管理模型 ·Data Access Application Block  ·小技巧:在.NET下编写中文代码程 ·激情后的思考:.NET想说爱你不容
 ·DataGrid Web Control 基本操作 ·JBuilder2005实现重构之类内部提 ·在蹉跎中一路前行:谈微软.NET技 ·使用TreeView实现无限级扩展节点
 ·JAVA虚拟机实例学习笔记一 ·JBuilder2005实现重构之分布式重 ·简单介绍.Net远程方法调用研究 ·JAVA虚拟机实例学习笔记二
 ·用DataGrid浏览数据相关实例 ·如何控制DataGrid里的内容换行与 ·.NET中实现彩色光标,动画和自定 ·带图片的,多列的DropDownList的
 ·DX图形流程(基于MESH静态模型绘 ·分享——一个简单的MP3播放器的制 ·介绍——用户认证管理设计方案 ·初探.NET中的delegate类型与.NET
 ·跟你分享—— .Net项目制作安装程 ·复制文件夹内容和删除整个文件夹 ·怎样在Java实例开发的过程中使用 ·JBuilder2005创建开发文档之标签
 
 
最新评论  点此查看所有评论
 
 
 
 
发表评论(支持UBB码)


验证码:  
 
 
 
© 2005- 王朝网络 版权所有