jxls--使用模版导出excel,单元格无法自动计算问题解决

在项目中使用jxls导出excel ,coding可以很少很少,excel报表格式可以很复杂同时也可以有很漂亮的样式,不再用网页导出这种很恶的方式来面对头痛的格式问题。

 jxls也是通过poi的api来操作excel,利用定义好格式的模版再加上一些标签语言就可以操作数据了。

 

public static void doExport(String attachName, String templeteFile, Map beans, HttpServletResponse response) { // response.setContentType("application/vnd.ms-excel"); response.setContentType("application/octet-stream;charset=UTF-8"); // FF乱码 response.setHeader("Content-Disposition", // "attachment; filename=" + java.net.URLEncoder.encode(fileName, // "UTF-8")); try { response.setHeader("Content-Disposition", "attachment;filename=" + new String(attachName.getBytes("gb2312"), "ISO8859-1") + ".xls"); Configuration config = new Configuration(); XLSTransformer transformer = new XLSTransformer(config); InputStream is = new BufferedInputStream(new FileInputStream( templeteFile)); HSSFWorkbook workbook = (HSSFWorkbook) transformer.transformXLS(is, beans); resetCellFormula(workbook); ServletOutputStream os = response.getOutputStream(); workbook.write(os); is.close(); os.flush(); os.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (ParsePropertyException e) { e.printStackTrace(); } catch (InvalidFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

具体的操作参考jxls的实例就好了,下面我要说的是jxls模版上的计算公式无法正常计算的解决办法。见以下模版rowstyle.xls,在E6,E7上分别有计算公式:$[C6*(1+D6)],$[sum(E6)],

 

对实例不做任何修改,直接运行main方法:

 

public static void main(String[] args) throws IOException, ParsePropertyException, InvalidFormatException { System.out.println("----begin---"); if (args.length >= 2) { templateFileName = args[0]; destFileName = args[1]; } Department department = new Department("IT"); Calendar calendar = Calendar.getInstance(); calendar.set(1970, 12, 2); Date d1 = calendar.getTime(); calendar.set(1980, 2, 15); Date d2 = calendar.getTime(); calendar.set(1976, 7, 20); Date d3 = calendar.getTime(); calendar.set(1968, 5, 6); Date d4 = calendar.getTime(); calendar.set(1978, 8, 17); Date d5 = calendar.getTime(); department.addEmployee(new Employee("Elsa", 28, 1500, 0.15, d1)); department.addEmployee(new Employee("Oleg", 32, 2300, 0.25, d3)); department.addEmployee(new Employee("Neil", 34, 2500, 0.00, d4)); department.addEmployee(new Employee("Maria", 34, 1700, 0.15, d5)); department.addEmployee(new Employee("John", 35, 2800, 0.20, d2)); Map beans = new HashMap(); beans.put("department", department); XLSTransformer transformer = new XLSTransformer(); transformer.registerRowProcessor(new StyleRowProcessor("department.staff")); transformer.transformXLS(templateFileName, beans, destFileName); }

 

结果计算单元格E6~E7并没有正常显示计算结果,而是显示的0,然而我们可以看到单元格内的计算公式仍然在那里,在公式最后我们敲回车则正常显示计算结果,显然这种显示方式一点也不直观。要解决这个问题的话我们就需要把单元格计算公式先计算再设置到单元格里。以下,提供一个通用的方法:

/** * * 重新设置单元格计算公式 * * */ public static void resetCellFormula(HSSFWorkbook wb) { HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(wb); int sheetNum = wb.getNumberOfSheets(); for (int i = 0; i < sheetNum; i++) { HSSFSheet sheet = wb.getSheetAt(i); int rows = sheet.getLastRowNum() + 1; for (int j = 0; j < rows; j++) { HSSFRow row = sheet.getRow(j); if (row == null) continue; int cols = row.getLastCellNum(); for (int k = 0; k < cols; k++) { HSSFCell cell = row.getCell(k); if(cell!=null) System.out.println("cell["+j+","+k+"]=:"+cell.getCellType()); if (cell == null) continue; if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { cell.setCellFormula(cell.getCellFormula()); System.out.println("----公式:"+cell.getCellFormula()); cell=e.evaluateInCell(cell); System.out.println("-----------"+cell.getNumericCellValue()); } } } } }

 

这里主要是:

HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(wb);  

cell=e.evaluateInCell(cell);

代码还是比较简单滴。

 

再修改main方法,再输出excel之间调用一哈:

public static void main(String[] args) throws IOException, ParsePropertyException, InvalidFormatException { System.out.println("----begin---"); if (args.length >= 2) { templateFileName = args[0]; destFileName = args[1]; } Department department = new Department("IT"); Calendar calendar = Calendar.getInstance(); calendar.set(1970, 12, 2); Date d1 = calendar.getTime(); calendar.set(1980, 2, 15); Date d2 = calendar.getTime(); calendar.set(1976, 7, 20); Date d3 = calendar.getTime(); calendar.set(1968, 5, 6); Date d4 = calendar.getTime(); calendar.set(1978, 8, 17); Date d5 = calendar.getTime(); department.addEmployee(new Employee("Elsa", 28, 1500, 0.15, d1)); department.addEmployee(new Employee("Oleg", 32, 2300, 0.25, d3)); department.addEmployee(new Employee("Neil", 34, 2500, 0.00, d4)); department.addEmployee(new Employee("Maria", 34, 1700, 0.15, d5)); department.addEmployee(new Employee("John", 35, 2800, 0.20, d2)); Map beans = new HashMap(); beans.put("department", department); XLSTransformer transformer = new XLSTransformer(); transformer.registerRowProcessor(new StyleRowProcessor("department.staff")); // transformer.transformXLS(templateFileName, beans, destFileName); InputStream is = new BufferedInputStream(new FileInputStream( templateFileName)); OutputStream out=new BufferedOutputStream(new FileOutputStream(destFileName)); HSSFWorkbook workbook = (HSSFWorkbook) transformer.transformXLS(is, beans); resetCellFormula(workbook); workbook.write(out); System.out.println("----end---"); is.close(); out.close(); }

跟着代码测试的童鞋们是不是还发现了一个问题昵?含有$[sum(E6)]计算公式滴单元格仍然没有计算, department.addEmployee五条记录put 进入了map beans占了5行,再加上表头占4行,而最后一行sum计算公式并没有动态的算进去,如果我们把row的size改为10,那么sum就会计算了。

你可能感兴趣的:(java.util)