使用POI导出Excel(二)-利用模板

一、基本操作见:使用POI导出Excel

二、本次功能需求

  给了一个模板,里面有6个sheet页,每页里面都需要填充相应的数据。如图:

图片描述

图片描述

三、需求分析

  1、分了6个sheet页,每页的数据都不一样,首先代码里要获得它们的数据,然后6个sheet页只能一个个填进去,没法批量操作。

  2、如果直接代码创建Excel并画表格样式和数据,那么工程量将会很大,而且会导致代码很乱。我采用的方法是把模板保存到项目里,再通过路径获取到该模板文件,把其内容全部复制到新创建的Excel中,再往里填充数据。

  3、注意到第一张图中有总计这一行,我的建议是先在代码中计算出相应的数据,再填充,我也是这样做的。当然,我的第一想法是给它设置函数公式,但是后来我并没有这么做。

  4、从第二张图中可以看得出要填充的数据的行是不固定的,除非规定了只填充前几条数据。而在11、12行中的数据是已经有了的,当填充的数据太多,就会覆盖掉那行数据。有两种方法解决,一是把它获取到,先填充数据覆盖掉,再在最后一条数据的下一行把它再填充回去。二是根据数据的总条数通过代码往中间插入空白行。两种方法都可行,我采用了第二种。

四、上代码

     public void exportAll() {
         OutputStream out = null;
         try {
             // 获取数据
             List<BaseTalentFlowAnalysisGridVo> talentFlows = this.talentFlowQuestionnaireService.listAnalysis();
             List<BaseBasicSituationAnalysisGridVo> basicSituations = this.basicSituationService.listAnalysis();
             List<BaseTalentInputAnalysisGridVo> talentInputs = this.talentInputService.listAnalysis();
             List<BaseTalentDemandAnalysisGridVo> talentDemands = this.talentDemandService.listAnalysis();
             List<BaseHighLevelTalentsRosterAnalysisGridVo> talentRosters = this.rosterService.listAnalysis();
             Map<String, Object> results = new HashMap<>();
             results.put("talentFlows", talentFlows);
             results.put("basicSituations", basicSituations);
             results.put("talentInputs", talentInputs);
             results.put("talentDemands", talentDemands);
             results.put("talentRosters", talentRosters);
 
             // 拿到模板文件
             String path = ServletActionContext.getServletContext().getRealPath("/");
             String filePath = path + "\\resources\\temp\\人才统计报表模板.xls";
             FileInputStream tps = new FileInputStream(new File(filePath));
             final HSSFWorkbook tpWorkbook = new HSSFWorkbook(tps);
             out = response.getOutputStream();
             response.reset();
             response.setHeader("content-disposition",
                     "attachment;filename=" + new String(("人才统计报表").getBytes("gb2312"), "ISO8859-1") + ".xls");
             response.setContentType("APPLICATION/msexcel");
             // 新建一个Excel的工作空间
             HSSFWorkbook workbook = new HSSFWorkbook();
             // 把模板复制到新建的Excel
             workbook = tpWorkbook;
             // 填充数据
             this.excelService.addData(workbook, results);
             // 输出Excel内容,生成Excel文件
             workbook.write(out);
         } catch (final IOException e) {
             LOGGER.error(e);
         } catch (final IllegalArgumentException e) {
             LOGGER.error(e);
         } catch (final Exception e) {
             LOGGER.error(e);
         } finally {
             try {
                 // 最后记得关闭输出流
                 response.flushBuffer();
                 if (out != null) {
                     out.flush();
                     out.close();
                 }
             } catch (final IOException e) {
                 LOGGER.error(e);
             }
         }
     }
     /**
      * 第二个sheet页:人才流动情况表
      * 
      * @param workbook
      * @param talentFlows
      */
     private void addTalentFlows(HSSFWorkbook workbook, List<BaseTalentFlowAnalysisGridVo> talentFlows) {
         // 获取第二个sheet页
         Sheet talentFlowSheet = workbook.getSheetAt(1);
         Row talentFlowRow = talentFlowSheet.getRow(0);
         // 声明总计的那几个数据
         Integer totalLastYearTotal = 0;
         Integer totalHighLevelTalent = 0;
         Integer totalUndergraduateAndGraduate = 0;
         Integer totalCollegeStudents = 0;
         Integer totalSocialTalent = 0;
         Integer totalMilitaryTransferCadres = 0;
         Integer totalReturnees = 0;
         Integer totalRetirement = 0;
         Integer totalResignation = 0;
         Integer totalDismiss = 0;
         Integer totalOther = 0;
         Integer totalAverageIncrease = 0;
         Integer totalAverageReduction = 0;
         // 循环数据
         for (BaseTalentFlowAnalysisGridVo baseTalentFlowAnalysisGridVo : talentFlows) {
             // 循环行
             for (int tr = 4; tr < 11; tr++) {
                 talentFlowRow = talentFlowSheet.getRow(tr);
                 // 当数据的项目字段和行的第一列内容相等,则把该条数据填入该行
                 if (talentFlowRow.getCell(0).getStringCellValue()
                         .equals(baseTalentFlowAnalysisGridVo.getFkProjectName())) {
                     talentFlowRow.getCell(1).setCellValue(baseTalentFlowAnalysisGridVo.getLastYearTotal());
                     // 给总计做计算
                     totalLastYearTotal += baseTalentFlowAnalysisGridVo.getLastYearTotal();
                     talentFlowRow.getCell(2).setCellValue(baseTalentFlowAnalysisGridVo.getHighLevelTalent());
                     totalHighLevelTalent += baseTalentFlowAnalysisGridVo.getHighLevelTalent();
                     talentFlowRow.getCell(3).setCellValue(baseTalentFlowAnalysisGridVo.getUndergraduateAndGraduate());
                     totalUndergraduateAndGraduate += baseTalentFlowAnalysisGridVo.getUndergraduateAndGraduate();
                     talentFlowRow.getCell(4).setCellValue(baseTalentFlowAnalysisGridVo.getCollegeStudents());
                     totalCollegeStudents += baseTalentFlowAnalysisGridVo.getCollegeStudents();
                     talentFlowRow.getCell(5).setCellValue(baseTalentFlowAnalysisGridVo.getSocialTalent());
                     totalSocialTalent += baseTalentFlowAnalysisGridVo.getSocialTalent();
                     talentFlowRow.getCell(6).setCellValue(baseTalentFlowAnalysisGridVo.getMilitaryTransferCadres());
                     totalMilitaryTransferCadres += baseTalentFlowAnalysisGridVo.getMilitaryTransferCadres();
                     talentFlowRow.getCell(7).setCellValue(baseTalentFlowAnalysisGridVo.getReturnees());
                     totalReturnees += baseTalentFlowAnalysisGridVo.getReturnees();
                     talentFlowRow.getCell(8).setCellValue(baseTalentFlowAnalysisGridVo.getRetirement());
                     totalRetirement += baseTalentFlowAnalysisGridVo.getRetirement();
                     talentFlowRow.getCell(9).setCellValue(baseTalentFlowAnalysisGridVo.getResignation());
                     totalResignation += baseTalentFlowAnalysisGridVo.getResignation();
                     talentFlowRow.getCell(10).setCellValue(baseTalentFlowAnalysisGridVo.getDismiss());
                     totalDismiss += baseTalentFlowAnalysisGridVo.getDismiss();
                     talentFlowRow.getCell(11).setCellValue(baseTalentFlowAnalysisGridVo.getOther());
                     totalOther += baseTalentFlowAnalysisGridVo.getOther();
                     talentFlowRow.getCell(12).setCellValue(baseTalentFlowAnalysisGridVo.getAverageIncrease());
                     totalAverageIncrease += baseTalentFlowAnalysisGridVo.getAverageIncrease();
                     talentFlowRow.getCell(13).setCellValue(baseTalentFlowAnalysisGridVo.getAverageReduction());
                     totalAverageReduction += baseTalentFlowAnalysisGridVo.getAverageReduction();
                     break;
                 }
             }
         }
         // 给总计行填充数据
         talentFlowRow = talentFlowSheet.getRow(11);
         talentFlowRow.getCell(1).setCellValue(totalLastYearTotal);
         talentFlowRow.getCell(2).setCellValue(totalHighLevelTalent);
         talentFlowRow.getCell(3).setCellValue(totalUndergraduateAndGraduate);
         talentFlowRow.getCell(4).setCellValue(totalCollegeStudents);
         talentFlowRow.getCell(5).setCellValue(totalSocialTalent);
         talentFlowRow.getCell(6).setCellValue(totalMilitaryTransferCadres);
         talentFlowRow.getCell(7).setCellValue(totalReturnees);
         talentFlowRow.getCell(8).setCellValue(totalRetirement);
         talentFlowRow.getCell(9).setCellValue(totalResignation);
         talentFlowRow.getCell(10).setCellValue(totalDismiss);
         talentFlowRow.getCell(11).setCellValue(totalOther);
         talentFlowRow.getCell(12).setCellValue(totalAverageIncrease);
         talentFlowRow.getCell(13).setCellValue(totalAverageReduction);
     }
     /**
      * 第四个sheet页:人才需求情况调查表
      * 
      * @param workbook
      * @param talentFlows
      */
     private void addalentDemands(HSSFWorkbook workbook, List<BaseTalentDemandAnalysisGridVo> talentDemands)
             throws IllegalArgumentException, IllegalAccessException {
         Sheet talentDemandSheet = workbook.getSheetAt(3);
         Row talentDemandRow = talentDemandSheet.getRow(4);
         // 如果数据大于模板中的行数,插入行并复制第一行数据的格式
         if (talentDemands.size() > 5) {
             // 插入行,5是模板中已有的行数
             talentDemandSheet.shiftRows(5, talentDemandSheet.getLastRowNum(), talentDemands.size() - 5, true, false);
             Row sourceRow = talentDemandSheet.getRow(4);
             for (int i = 0; i < talentDemands.size() - 5; i++) {
                 Row newRow = talentDemandSheet.createRow(4 + i + 1);
                 newRow.setHeight(sourceRow.getHeight());
                 for (int j = 0; j < sourceRow.getLastCellNum(); j++) {
                     Cell templateCell = sourceRow.getCell(j);
                     if (templateCell != null) {
                         Cell newCell = newRow.createCell(j);
                         copyCell(templateCell, newCell);
                     }
                 }
             }
         }
         // 填充数据
         for (int i = 0; i < talentDemands.size(); i++) {
             talentDemandRow = talentDemandSheet.getRow(4 + i);
             talentDemandRow.getCell(0).setCellValue(talentDemands.get(i).getPositionTitle());
             talentDemandRow.getCell(2).setCellValue(talentDemands.get(i).getDemand());
             talentDemandRow.getCell(3).setCellValue(talentDemands.get(i).getAge());
             talentDemandRow.getCell(4).setCellValue(talentDemands.get(i).getFkAcademicDegreeName());
             talentDemandRow.getCell(5).setCellValue(talentDemands.get(i).getTechnicalTitles());
             talentDemandRow.getCell(6).setCellValue(talentDemands.get(i).getProfession());
             talentDemandRow.getCell(7).setCellValue(talentDemands.get(i).getFkTalentCategoryName());
             talentDemandRow.getCell(8).setCellValue(talentDemands.get(i).getFkServiceFormName());
             talentDemandRow.getCell(9).setCellValue(talentDemands.get(i).getProvide());
             talentDemandRow.getCell(10).setCellValue(talentDemands.get(i).getOtherCases());
             talentDemandRow.getCell(11).setCellValue(talentDemands.get(i).getFkIntentionToChooseName());
         }
     }

五、缺点:一手烂代码,应该给对象设置对应的中文注释,和模板中的列头一样,然后再通过循环填充数据。这样一个个填上去太傻了。

六、通过实验测试,在getCell的时候,如果那是个合并的单元格,那么该单元格的数据存在了左上角,其他的格内容为空。