使用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 = "";
}

  

POI刷新数据后的函数(公式)更新问题的更多相关文章

  1. 添加数据库数据后(SVN的更新和启动)、SVN启动

    一.添加数据库数据: 1.修改Excel表格,添加字段 2.修改数据库,添加字段 3.修改程序 4.使用Excel生成Tabletotable文件,并修改生成文件的内容. (1)删除cpp文件所有的H ...

  2. UWP 自然灾害App在刷新数据后卡死的解决方案

    一直以为都在纳闷,为啥我的其他app崩溃次数几乎为0,而单单这个App的崩溃次数简直逆天了,我都不敢相信. 每天都有至少上千次crash...我也是服的 不甘心,趁着这次重构的机会,把代码好好捋了1下 ...

  3. Adapter刷新数据的坑

    adapter刷新数据的时候,要能够刷新成功,要保证每次刷新的时候都是改变数据源. 于是,我这样做了,在适配器的构造方法里面写到: private List<ListBean> listI ...

  4. DataGridView重新加载数据后,选中上次选中的行。

    public int SelecedRow;//记录当前鼠标点中的行索引(用于解决用户获取看板数据,刷新数据后,当前选中行回到默认行) private void dataGridView1_CellC ...

  5. IDEA 修改JSP和后端数据后,页面刷新可以实时更新

    情况:刚开始使用IDEA进行开发时,发现修改JSP页面或者后端数据后,再刷新浏览器页面,发现没有变化,页面无更新. 这样就导致不得不频繁重启tomcat服务器.非常麻烦 解决方法: 步骤1. 先设置t ...

  6. 关于ListView中notifyDataSetChanged()刷新数据不更新原因

    使用Listview的时候: 当要动态显示更改后的数据(例如数据库改动), 很多人应该都用过notifyDataSetChanged();这个方法来刷新Listview,显示改后的数据. 这时候就要注 ...

  7. js实现非模态窗口增加数据后刷新父窗口数据

    父窗口是由两个部分组成,一个html的table,一部分是extjs的gird. 点击grid面板[增加]按钮将会弹出非模态窗口进行新数据的编辑页面 下面是按钮的触发函数代码: var a = win ...

  8. [转]MFC子线程更改图像数据后更新主窗口图像显示方法

    程序思路是由外部的输入输出控制卡发出采集图像信号,之后相机采集图像得到图像数据指针,接收图像数据指针创建成图像最后显示到MFC对话框应用程序的Picture Control控件上,同时,为了标定相机位 ...

  9. 解决Vuex持久化插件-在F5刷新页面后数据不见的问题

    页面刷新后,想保存页面未保存的数据.我们总是习惯于放在浏览器的sessionStorage和localStorage中.但是用了vue后,vuex便可以被应用了. vuex优势:相比sessionSt ...

随机推荐

  1. Spring boot教程

    1.首先是新建Maven工程 2.引入Pom依赖 3.新建一个Controller 4.运行Main方法 5.浏览器访问 pom.xml <project xmlns="http:// ...

  2. AngularJs学习笔记--concepts(概念)

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/concepts 继续.. 一.总括 本文主要是angular组件(components)的概览,并说明 ...

  3. self._raiseerror(v) File "D:\GameDevelopment\Python27\lib\xml\etree\ElementTree.py", line 1506, in _raiseerror

    D:\BaiDuYun\Plist>python unpack_plist.py lobbyRelieveTraceback (most recent call last): File &quo ...

  4. 导出含有图片的项目成jar文件后运行,图片不显示

    在编写完Java程序后,打包成Jar时发布,会发现找不到Jar文件中的图片和文本文件,其原因是程序中载入图片或文本文件时,使用了以当前工作路径为基准的方式来指定文件和路径.这与用户运行Jar包时的当前 ...

  5. POJ 3253 Fence Repair(优先队列,哈夫曼树,模拟)

    题目 //做哈夫曼树时,可以用优先队列(误?) //这道题教我们优先队列的一个用法:取前n个数(最大的或者最小的) //哈夫曼树 //64位 //超时->优先队列,,,, //这道题的优先队列用 ...

  6. JavaWeb-JDK下载安装

    JDK官方下载地址:http://www.oracle.com/index.html JDK下载: 64位的下64的 JDK安装:(这是32位的) JDK部署测试:(配置环境变量) JAVA_HOME ...

  7. JUC回顾之-ThreadPoolExecutor的原理和使用

    Spring中的ThreadPoolTaskExecutor是借助于JDK并发包中的java.util.concurrent.ThreadPoolExecutor来实现的.基于ThreadPoolEx ...

  8. ***PHP implode() 函数,将数组合并为字符串;explode() 函数,把字符串打散为数组

    实例 把数组元素组合为字符串: <?php $arr = array('Hello','World!','I','love','Shanghai!'); echo implode(" ...

  9. jmeter中线程之间传递参数

    JMeter 变量作用域局限于所属线程.这样设计是经过深思熟虑的,目的是让测试线程能够独立运转.有时候用户可能需要在不同线程间(可能属于同一个线程组,也可能不属于同一个线程组)传递变量. 其中一种方法 ...

  10. http://blog.sina.com.cn/s/blog_5b9b4abe01017638.html

    http://blog.sina.com.cn/s/blog_5b9b4abe01017638.html