zoukankan      html  css  js  c++  java
  • 使用POI导出Excel

    先分享几个链接:(POI的中文API,别人总结的拿来用特别方便)

      http://blog.csdn.net/m0_37505412/article/details/71109503      

      https://www.cnblogs.com/fqfanqi/p/6172223.html

      https://blog.csdn.net/s_istvan/article/details/69266915  (单元格颜色) 

    我在项目中做这个功能的时候,其实项目中是有现成代码的,本来我以为我只需要修改一下,后来看过代码才发现和我要的不一样,于是只能重写一个。

    导出功能:

      1、在action层拿到要导出的数据  --  results

      2、同样在action层拿到要导出数据的字段集,即列   --  exportFields

        解释一下,一般我们在获取数据的时候,往往会把一些表中的冗余字段或者一些我不需要的字段也获取了,我们不可能也把它们导出来。其实这个字段集,就是我们在Excel表中要显示的列。在现成的功能中支持在页面选择要导出的字段,而我的导出功能不支持选择,导出的字段是写死的。

      3、拿到导出时一张表中存多少条数据  --  rowNum

        在现成的功能中还支持这个由用户选,就是导出到一张表,要太多条数据,然后我们根据这个值去划分数据,比如这个值是5000,然后我们就每5000条数据新建一个工作表,再继续存放数据。我的功能……这个值同样写死的。

      4、调用Service层方法,传入上面的参数和HttpServletResponse 。传哪些参数大家随意,当然  results是肯定不能少的。

      5、在Service层写方法,接受刚才的四个参数

     1     @Override
     2     public void createExcelWorkBookInfo(HttpServletResponse response, List<BaseAlumni> results, String exportFields,
     3             Integer rowNum) {
     4         String nowStr = new Date().getTime() + "";
     5         //这个out我还不太了解就不给你们说了,大致意思就是导出动作吧
     6         OutputStream out = null;
     7         try {
     8             out = response.getOutputStream();
     9             response.reset();
    10             //设置表名
    11             response.setHeader("content-disposition",
    12                     "attachment;filename=" + new String(("校友信息" + nowStr).getBytes("gb2312"), "ISO8859-1") + ".xls");
    13             response.setContentType("APPLICATION/msexcel");
    14             //创建Excel表
    15             HSSFWorkbook workbook = new HSSFWorkbook();
    16             //调用导出方法
    17             excelSrv.export(results, exportFields, workbook, rowNum);
    18             workbook.write(out);
    19         } catch (IOException e) {
    20             e.printStackTrace();
    21         } finally {
    22             try {
    23                 // 强行将响应缓存中的内容发送到目的地
    24                 response.flushBuffer();
    25                 if (out != null) {
    26                     out.flush();
    27                     out.close();
    28                 }
    29             } catch (IOException e) {
    30                 LOGGER.error(e);
    31             }
    32         }
    33     }

      5、写export方法,在现成的方法中,封装好了一个方法,行,列的生成都是通过foreach,很高大上。在这里,我先附上我写的,后面再附上现成的,给自己做一个对比。

     1     @Override
     2     public void alumniBranchExport(List<BaseAlumniBranch> results, Map<String, String> fildsMap, HSSFWorkbook wb) {
     3         //因为之前没有传,所以在这写死,这个功能大家不想要也是可以的  -- rowMaxNum = 10000
     4         Integer rowNum = rowMaxNum;
     5         for (int i = 0; i < results.size(); i += rowNum) {
     6             List<BaseAlumniBranch> newlist = new ArrayList<>();
     7             if ((i + rowNum) < results.size()) {
     8                 //数据的截取
     9                 newlist = results.subList(i, i + rowNum);
    10             } else {
    11                 newlist = results.subList(i, results.size());
    12             }
    13             //创建工作表
    14             HSSFSheet sheet = wb.createSheet();
    15             for (int j = 0; j < fildsMap.size(); j++) {
    16                 //设置列宽,第一个参数是列,第二个参数是宽值
    17                 sheet.setColumnWidth(i, 5000);
    18             }
    19             //填充表头
    20             this.fillClubExcelHeader(wb, sheet, fildsMap);
    21             //填充内容
    22             this.fillClubExcelBody(newlist, sheet, wb, fildsMap);
    23         }
    24     }

    6、其实现成的代码和我这个是差不多一样的,不一样的地方就是在填充的那两个方法里面

      这是现成的header填充:

     1     private void fillCommonHeader(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> fildsMap) {
     2         //创建样式
     3         HSSFCellStyle style = wb.createCellStyle();
     4         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
     5         //字体的颜色,大小
     6         HSSFFont font = wb.createFont();
     7         font.setColor(HSSFColor.BLACK.index);
     8         font.setFontHeightInPoints((short) 18);
     9         style.setFont(font);
    10         //创建第一行,从0开始,参数是第几行的索引,第一行是0
    11         HSSFRow row = sheet.createRow(0);
    12         //在这里说一下,foreach是拿不到index的,这里在外面声明一个i,在表示第几列
    13         int i = 0;
    14         //循环传过来的字段集
    15         for (String key : fildsMap.keySet()) {
    16             //创建一个单元格,创建完后i自增1
    17             HSSFCell cell = row.createCell(i++);
    18             String value = fildsMap.get(key);
    19             //给单元格赋值
    20             cell.setCellValue(value);
    21             //给单元格设置样式
    22             cell.setCellStyle(style);
    23         }
    24         //在这里有一个顺序的问题,我也是用传参的方式,但是我的fildsMap的顺序就是乱了,我又不会调,尴尬
    25     }

      这是我的header填充:

     1     private void fillClubExcelHeader(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> fildsMap) {
     2         HSSFCellStyle style = wb.createCellStyle();
     3         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
     4         HSSFFont font = wb.createFont();
     5         font.setColor(HSSFColor.BLACK.index);
     6         font.setFontHeightInPoints((short) 18);
     7         style.setFont(font);
     8         // 创建第一行
     9         HSSFRow row = sheet.createRow(0);
    10         // 创建第一列
    11         HSSFCell cell = row.createCell(0);
    12         // 赋值
    13         cell.setCellValue(fildsMap.get("clubName"));
    14         cell.setCellStyle(style);
    15         // 创建第二列,在这里不能再出现HSSFCell声明,为什么……我也是一知半解,就不说了
    16         cell = row.createCell(1);
    17         cell.setCellValue(fildsMap.get("clubWechatId"));
    18         cell.setCellStyle(style);
    19         // 创建第三列……
    20         cell = row.createCell(2);
    21         cell.setCellValue(fildsMap.get("clubAddress"));
    22         cell.setCellStyle(style);
    23         cell = row.createCell(3);
    24         cell.setCellValue(fildsMap.get("clubEmail"));
    25         cell.setCellStyle(style);
    26         cell = row.createCell(4);
    27         cell.setCellValue(fildsMap.get("clubEstablishedTime"));
    28         cell.setCellStyle(style);
    29         cell = row.createCell(5);
    30         cell.setCellValue(fildsMap.get("name"));
    31         cell.setCellStyle(style);
    32         cell = row.createCell(6);
    33         cell.setCellValue(fildsMap.get("staff"));
    34         cell.setCellStyle(style);
    35         cell = row.createCell(7);
    36         cell.setCellValue(fildsMap.get("phone"));
    37         cell.setCellStyle(style);
    38         cell = row.createCell(8);
    39         cell.setCellValue(fildsMap.get("email"));
    40         cell.setCellStyle(style);
    41     }

      这是现成的body填充:

     1     private <T> void fillCommonBody(List<T> results, HSSFSheet sheet, HSSFWorkbook wb, Map<String, String> fildsMap) {
     2         HSSFCellStyle style = wb.createCellStyle();
     3         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
     4         HSSFFont font = wb.createFont();
     5         font.setColor(HSSFColor.BLACK.index);
     6         font.setFontHeightInPoints((short) 16);
     7         style.setFont(font);
     8         int i = 1;
     9         for (T inst : results) {
    10             HSSFRow row = sheet.createRow(i++);
    11             row.setRowStyle(style);
    12             int j = 0;
    13             for (String key : fildsMap.keySet()) {
    14                 HSSFCell cell = row.createCell(j++);
    15                 String val = setCell(key, inst);  //在里我这差点被骗了,也不知道是谁命名的,还以为单元格带有的get,set方法
    16                 cell.setCellValue(val);
    17             }
    18         }
    19     }

      这个方法主要是写如何从results中拿值的,我看了半天没看懂

     1     @SuppressWarnings("rawtypes")
     2     private <T> String setCell(String field, T data) {
     3         String val = "";
     4 
     5         Class clazz = data.getClass();
     6         Field[] fields = ArrayUtils.addAll(clazz.getDeclaredFields(), clazz.getSuperclass().getDeclaredFields());
     7         for (int i = 0; i < fields.length; i++) {
     8             if (fields[i].getName().equals(field)) {
     9                 try {
    10                     Object resultObject = invokeMethod(data, fields[i].getName(), null);
    11                     if (resultObject == null) {
    12                         resultObject = "";
    13                     }
    14                     val = resultObject.toString();
    15                     break;
    16                 } catch (SecurityException | NoSuchMethodException | IllegalArgumentException | IllegalAccessException
    17                         | InvocationTargetException e) {
    18                     e.printStackTrace();
    19                 }
    20             }
    21         }
    22 
    23         return val;
    24     }

      我的body方法:

     1     private <T> void fillClubExcelBody(List<BaseAlumniBranch> results, HSSFSheet sheet, HSSFWorkbook wb,
     2             Map<String, String> fildsMap) {
     3         HSSFCellStyle style = wb.createCellStyle();
     4         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
     5         HSSFFont font = wb.createFont();
     6         font.setColor(HSSFColor.BLACK.index);
     7         font.setFontHeightInPoints((short) 16);
     8         style.setFont(font);
     9         int k = 1;
    10         if (results.size() < 2 || "null".equals(results.size())) {
    11             LOGGER.error("alumniBranchExport but results is empty !");
    12             return;
    13         }
    14         for (int i = 0; i < results.size(); i++) {
    15             BaseAlumniBranch inst = results.get(i);
    16             if (inst.getStaffList().size() < 1 || "null".equals(inst.getStaffList().size())) {
    17                 HSSFRow row = sheet.createRow(k++);
    18                 row.setRowStyle(style);
    19                 HSSFCell cell = row.createCell(0);
    20                 cell.setCellValue(inst.getName());
    21                 cell.setCellStyle(style);
    22                 cell = row.createCell(1);
    23                 cell.setCellValue(inst.getWechatId());
    24                 cell.setCellStyle(style);
    25                 cell = row.createCell(2);
    26                 cell.setCellValue(inst.getAddress());
    27                 cell.setCellStyle(style);
    28                 cell = row.createCell(3);
    29                 cell.setCellValue(inst.getEmail());
    30                 cell.setCellStyle(style);
    31                 cell = row.createCell(4);
    32                 cell.setCellValue(inst.getEstablishedTime());
    33                 cell.setCellStyle(style);
    34                 cell = row.createCell(5);
    35                 cell.setCellValue("");
    36                 cell.setCellStyle(style);
    37                 cell = row.createCell(6);
    38                 cell.setCellValue("");
    39                 cell.setCellStyle(style);
    40                 cell = row.createCell(7);
    41                 cell.setCellValue("");
    42                 cell.setCellStyle(style);
    43                 cell = row.createCell(8);
    44                 cell.setCellValue("");
    45                 cell.setCellStyle(style);
    46             } else {
    47                 for (int j = 0; j < inst.getStaffList().size(); j++) {
    48                     HSSFRow row = sheet.createRow(k++);
    49                     row.setRowStyle(style);
    50                     HSSFCell cell = row.createCell(0);
    51                     cell.setCellValue(inst.getName());
    52                     cell.setCellStyle(style);
    53                     cell = row.createCell(1);
    54                     cell.setCellValue(inst.getWechatId());
    55                     cell.setCellStyle(style);
    56                     cell = row.createCell(2);
    57                     cell.setCellValue(inst.getAddress());
    58                     cell.setCellStyle(style);
    59                     cell = row.createCell(3);
    60                     cell.setCellValue(inst.getEmail());
    61                     cell.setCellStyle(style);
    62                     cell = row.createCell(4);
    63                     cell.setCellValue(inst.getEstablishedTime());
    64                     cell.setCellStyle(style);
    65                     cell = row.createCell(5);
    66                     cell.setCellValue(inst.getStaffList().get(j).getName());
    67                     cell.setCellStyle(style);
    68                     cell = row.createCell(6);
    69                     cell.setCellValue(inst.getStaffList().get(j).getStaff());
    70                     cell.setCellStyle(style);
    71                     cell = row.createCell(7);
    72                     cell.setCellValue(inst.getStaffList().get(j).getPhone());
    73                     cell.setCellStyle(style);
    74                     cell = row.createCell(8);
    75                     cell.setCellValue(inst.getStaffList().get(j).getEmail());
    76                     cell.setCellStyle(style);
    77                 }
    78                 for (int column = 0; column < 5; column++) {
    79                     mergeCell(sheet, k - inst.getStaffList().size(), k - 1, column, column);
    80                 }
    81 
    82             }
    83         }
    84     }

      7、我在方法的最后做了合并单元格,这是在原方法上改不动的,所以我必须再写一个方法。

        传的参数中,从左到右:工作表名,起始行,结束行,起始列,结束行

        就是要合并单元格,合并从哪行开始到哪行,从哪列开始到哪列

    1     public void mergeCell(HSSFSheet sheet, int rolStart, int rolEnd, int cowStart, int cowEnd) {
    2         CellRangeAddress region = new CellRangeAddress(rolStart, rolEnd, cowStart, cowEnd);
    3         sheet.addMergedRegion(region);
    4     }

      8、到此,导出结束。

      9、过程中碰到的坎坷:

        Excel表我声明了两次,导致到后来导出的内容是没有行的,如图:(要注意,不止是表,行,列也不能重复,否则就会出错)

      

      10、最后的成功:

  • 相关阅读:
    jQuery插件开发模式
    优化布局
    jquery easyui 选项卡
    easy ui 点击行展开与折叠
    考拉海购技术支持的前世今生
    跑的好好的 Java 进程,怎么突然就瘫痪了
    Dubbo 如何成为连接异构微服务体系的最佳服务开发框架
    微服务治理实践:如何对单点异常进行自动摘除
    盘点阿里巴巴 15 款开发者工具
    千万创业者的自白:踩过坑才明白这些真相!
  • 原文地址:https://www.cnblogs.com/qq765065332/p/7811760.html
Copyright © 2011-2022 走看看