分享
 
 
 

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

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

上好的人肉包子新鲜出炉啦,各位妖魔鬼怪赶紧来尝尝鲜……

首先说说现在我所知道的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也才几星期时间,上面有些内容可能说得并不正确,希望各位大虾砸砖指正!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有