POI刷新数据后的函数(公式)更新问题

使用POI将Excel模板中的数据进行更新,这应该是很常见的操作

下面就贴上我的一小段代码

public class ModifyExcel {
	
	/**
	 * @param fileName	Excel报表路径
	 * @param sheetName Excel中需要修改的sheet名
	 * @param modify_from	从哪一个坐标点开始刷新数据
	 * @param crs	从Oracle中读取出来的缓存数据集
	 * @throws Exception
	 */
	public void doModify(String fileName,String sheetName,int[] modify_from,CachedRowSet crs) throws Exception{
		Workbook	wb=WorkbookFactory.create(new FileInputStream(fileName));
		Sheet sheet=wb.getSheet(sheetName);
		
		int i=0;
		while(crs.next()){	
			if(sheet.getRow(i+modify_from[0])==null)
				sheet.createRow(i+modify_from[0]);
			for(int j=0;j<crs.getMetaData().getColumnCount();j++){
				Cell cell=sheet.getRow(i+modify_from[0]).getCell(j+modify_from[1]);
				if(cell==null)
					cell=sheet.getRow(i+modify_from[0]).createCell(j+modify_from[1]);
				
				String content=crs.getString(j+1);
				try{
					cell.setCellValue(Double.parseDouble(content));
				}catch(Exception e){
					cell.setCellValue(content);
				}
				
			}
			i++;
		}
		
		FileOutputStream fout = new FileOutputStream(fileName);
		wb.write(fout);
		fout.flush();
		fout.close();
		
		wb.close();	
	}
}

这一段代码是使用POI将从数据库中取到的结果集更新到报表中的一个隐藏sheet中去

然而遇到一个问题

隐藏的sheet作为数据源,为多个非隐藏的报表sheet提供基础数据,也就是说Excel中还有很多sheet是要调用这个隐藏sheet中的数据的

使用POI将数据源的sheet更新后,你的Excel模板并没有触发任何的数据修改事件,因为你本身并没有打开WPS或者Office

所以报表sheet中那些代入,那些引用,那些函数和公式,全部都不会有更新

除非你在  wb.write(fout);  之前加上一句

wb.setForceFormulaRecalculation(true);

强制整个Excel在你打开WPS或者Office的一瞬间,重新计算更新一下函数公式

接着又会碰到另一个问题

如果我不打开WPS或者Office,一直不打开,那在单纯的Excel文件里,那些报表的函数公式会更新吗?

答案是否定的

想做个这个测试很简单,先在隐藏sheet中修改数据源,然后不打开WPS或者Office

再一次使用POI去读这个文件,将读到的公式数据输出,你会发现他们还是原来的值,并没有因为数据源的变化而重新计算

经过博主的不断研究,终于发现如果要在不打开WPS或者Office的情况下,更新完数据源后强制所有sheet中的公式重新计算

需要对指定的Cell进行如下操作:

wb.getCreationHelper().createFormulaEvaluator().evaluateFormulaCell(cell);

博主最终将这行代码添加在读取公式单元格的操作中,在读的时候强制计算新值

实现代码如下:

                   // 设置文本
				String strCell = "";
				switch (cells[i][j].getCell().getCellType()) {
				case HSSFCell.CELL_TYPE_NUMERIC:										
					strCell = String.valueOf(cells[i][j].getCell().getNumericCellValue());
					break;
				case HSSFCell.CELL_TYPE_STRING:
					strCell = cells[i][j].getCell().getStringCellValue();
					break;
				case HSSFCell.CELL_TYPE_BOOLEAN:
					strCell = String.valueOf(cells[i][j].getCell().getBooleanCellValue());
					break;
				case HSSFCell.CELL_TYPE_FORMULA:
					//刚写入的数据无法及时更新,需要人为打开WPS或者Office才能更新
					//使用evaluateFormulaCell对函数单元格进行强行更新计算
					wb.getCreationHelper().createFormulaEvaluator().evaluateFormulaCell(cells[i][j].getCell());
					
					try {
						strCell = String.valueOf(cells[i][j].getCell().getNumericCellValue());
					} catch (IllegalStateException e) {
						strCell = String.valueOf(cells[i][j].getCell().getRichStringCellValue());
					}
					break;
				default:
					strCell = "";
				}

  

posted on 2015-10-31 22:44  丁丁·全栈工程师  阅读(5426)  评论(0编辑  收藏  举报

导航