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