• POI通用导出Excel数据(包括样式设计)


    前言

    • 前一段时间我写过通用的导入Excel,前几天也写了导出pdf格式的,还有我之前搞得导出Word,我在之前的博客也都介绍了导出和导入是一个道理,无非是一个获取一个是赋值。昨天有一位同仁看了我的Excel通用导入导出那个源码,说不是太懂。顺道今天整理了一下导出那块的知识,导入我之前已经介绍的很详细了。今天我们就来说说Excel导出的那些事!

    前期准备

    • jar包下载,我们使用对Excel,Word操作的都是借助poi来实现的,所以首先我们需要下载jar包。
      POI 下载 猛戳我

    代码解析

    通过javabean来实现数据的导出

    • 数据准备:

      String[] headers = { "学号", "姓名", "年龄", "性别", "出生日期" };
            List<Student> dataset = new ArrayList<Student>();
            dataset.add(new Student(10000001, "张三", 20, true, new Date()));
            dataset.add(new Student(20000002, "李四", 24, false, new Date()));
            dataset.add(new Student(30000003, "王五", 22, true, new Date()));
    • 然后我用导出的工具类开始导数据

      ExportExcel<Student> ex = new ExportExcel<Student>();
      ex.exportExcel(headers, dataset, out);
    • ExportExcel是我写的一个模板,这个模板下面有两个exportExcel这个方法,一个是穿map数据的,另一个是传javabean的,我们上面穿的是javabean所以会调用javabean的方法。也就是说exportExcel会调用下面这个方法

      这里写图片描述
      最终我们调用的是exportExcelByBean这个方法。

    下面我们详细解说exportExcelByBean这个方法内容。

    • 1、首先声明一个Excel工作簿

      HSSFWorkbook workbook = new HSSFWorkbook();
    • 2、生成一个表格,传的title就是表格sheet也得名字

      HSSFSheet sheet = workbook.createSheet(title);
    • 3、设置表格默认宽度

      sheet.setDefaultColumnWidth((short) 15);
    • 4、设置样式

      HSSFCellStyle style = workbook.createCellStyle();
          // 设置这些样式
      style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
      style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
      style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
      style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
      style.setBorderRight(HSSFCellStyle.BORDER_THIN);
      style.setBorderTop(HSSFCellStyle.BORDER_THIN);
      style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

      需要补充一下,我设置这个样式就是让导出Excel变得美观一点,你可以不要这个。

    • 设置导出的字体样式并把这个字体加入到上面那个样式中

      // 生成另一个字体
          HSSFFont font2 = workbook.createFont();
          font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
          // 把字体应用到当前的样式
          style2.setFont(font2);
      
    • 其他的一些样式设置

      “`
      // 声明一个画图的顶级管理器
      HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
      // 定义注释的大小和位置,详见文档
      HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0,
      0, 0, 0, (short) 4, 2, (short) 6, 5));
      // 设置注释内容
      comment.setString(new HSSFRichTextString(“可以在POI中添加注释!”));
      // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容.
      comment.setAuthor(“leno”);

    • 设置表格的表头

      // 产生表格标题行
          HSSFRow row = sheet.createRow(0);
          for (short i = 0; i < headers.length; i++) {
              HSSFCell cell = row.createCell(i);
              cell.setCellStyle(style);
              HSSFRichTextString text = new HSSFRichTextString(headers[i]);
              cell.setCellValue(text);
          }

      到这里表格的容器样式已经设置完了,下面就是导出数据到我们准备的Excel中了。

    • 拿到集合中的所有javabean

      Iterator<T> it = dataset.iterator();
    • 在遍历数据的时候我们用的既然javabean就需要用到反射机制,这个简单的介绍一下反射这个神奇的东西。

      // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
              Field[] fields = t.getClass().getDeclaredFields();
    • 然后遍历属性,拿到单一属性后判断该用get还是is方法

        Field field = fields[i];
                    String fieldName = field.getName();
                    String[] split=field.toString().split(" ");
                    String getMethodName="";
                    if("boolean".equalsIgnoreCase(split[1])||"bool".equalsIgnoreCase(split[1])){
                        getMethodName = "is"
                                + fieldName.substring(0, 1).toUpperCase()
                                + fieldName.substring(1);
                    }else {
                        getMethodName = "get"
                                + fieldName.substring(0, 1).toUpperCase()
                                + fieldName.substring(1);
                    }
    • 然后就是通过反射区调用javabean的方法获取值了

      Class tCls = t.getClass();
                      Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
                      Object value = getMethod.invoke(t, new Object[] {});
    • 我们获取到了值,现在我们就需要对值进行判断了,如果是日期类型的,我们需要指定格式输出到Excel中,如果是数字我们就输出数字,如果是字符串我们输出字符串,如果是bool那么我们根据需求输出两种值得其中一种。

      // 判断值的类型后进行强制类型转换
                      String textValue = null;
                      if (value instanceof Boolean) {
                          boolean bValue = (Boolean) value;
                          textValue = "男";
                          if (!bValue) {
                              textValue = "女";
                          }
                      } else if (value instanceof Date) {
                          Date date = (Date) value;
                          SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                          textValue = sdf.format(date);
                      } else if (value instanceof byte[]) {
                          // 有图片时,设置行高为60px;
                          row.setHeightInPoints(60);
                          // 设置图片所在列宽度为80px,注意这里单位的一个换算
                          sheet.setColumnWidth(i, (short) (35.7 * 80));
                          // sheet.autoSizeColumn(i);
                          byte[] bsValue = (byte[]) value;
                          HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,
                          1023, 255, (short) 6, index, (short) 6, index);
                          anchor.setAnchorType(2);
                          patriarch.createPicture(anchor, workbook.addPicture(
                          bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                      } else {
                          // 其它数据类型都当作字符串简单处理
                          textValue = value.toString();
                      }
    • 然后就是将数据写入Excel

      
                      if (textValue != null) {
                          Pattern p = Pattern.compile("^\d+(\.\d+)?$");
                          Matcher matcher = p.matcher(textValue);
                          if (matcher.matches()) {
                              // 是数字当作double处理
                              cell.setCellValue(Double.parseDouble(textValue));
                          } else {
                              HSSFRichTextString richString = new HSSFRichTextString(
                                      textValue);
                              HSSFFont font3 = workbook.createFont();
                              font3.setColor(HSSFColor.BLUE.index);
                              richString.applyFont(font3);
                              cell.setCellValue(richString);
                          }
                      }
    • 最后写出这个工作簿

    try {
                workbook.write(out);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    • 调用说明,OutputStream out = new FileOutputStream(“D://zxh//test//a.xls”);
    • 给一个输出流 工Excel输出,如果是JavaWeb中应用,那就直接将这个工作簿输出到前台让浏览器下载就行了。

    通过Map来实现数据的导出

    • 通过Map的好处就是我们不用去准备javabean了,也就自然没有反射那块难点了,既方便有易懂,何乐而不为呢。
      这里写图片描述

    也就是说最后我们选择的是

    exportExcelByMap

    这个方法

    • 基于上面javabean介绍的很详细了,我这个map就不在赘述了,我只说一下关键点的地方,通过Map和通过javabean的,我们的表格样式是不变的,所以不一样的地方就是在遍历数据的时候讲数据赋值到Excel中的,最后输出的那个也不便,说白了就是获取数据的方式不一样了,javabean我是通过反射获取的,如果用了map我们直接用get就行了。
    for(int i=0;i<list.size();i++){
                        Map<String, Object> map = list.get(i);
                        HSSFCell cell = row.createCell(i);
                        cell.setCellStyle(style2);
                        //拿到第一个数据
                        for(String field : headers){
                            //遍历字段进行顺序赋值
                            Object value = map.get(field);
                            // 判断值的类型后进行强制类型转换
                            String textValue = null;
                            if (value instanceof Boolean) {
                                boolean bValue = (Boolean) value;
                                textValue = "男";
                                if (!bValue) {
                                    textValue = "女";
                                }
                            } else if (value instanceof Date) {
                                Date date = (Date) value;
                                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                                textValue = sdf.format(date);
                            } else if (value instanceof byte[]) {
                                // 有图片时,设置行高为60px;
                                row.setHeightInPoints(60);
                                // 设置图片所在列宽度为80px,注意这里单位的一个换算
                                sheet.setColumnWidth(i, (short) (35.7 * 80));
                                // sheet.autoSizeColumn(i);
                                byte[] bsValue = (byte[]) value;
                                HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,
                                1023, 255, (short) 6, index, (short) 6, index);
                                anchor.setAnchorType(2);
                                patriarch.createPicture(anchor, workbook.addPicture(
                                bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                            } else {
                                // 其它数据类型都当作字符串简单处理
                                textValue = value.toString();
                            }
                            // 如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成
                            if (textValue != null) {
                                Pattern p = Pattern.compile("^\d+(\.\d+)?$");
                                Matcher matcher = p.matcher(textValue);
                                if (matcher.matches()) {
                                    // 是数字当作double处理
                                    cell.setCellValue(Double.parseDouble(textValue));
                                } else {
                                    HSSFRichTextString richString = new HSSFRichTextString(
                                            textValue);
                                    HSSFFont font3 = workbook.createFont();
                                    font3.setColor(HSSFColor.BLUE.index);
                                    richString.applyFont(font3);
                                    cell.setCellValue(richString);
                                }
                            }
                        }
                    }
                    try {
                        workbook.write(out);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

    总结

    整个博客我一直强调,用Map好,因为现在JavaWeb中框架主流是mybatis等框架,而这些框架封装的数据库数据正好就是通过map格式传输的,所以我们直接获取的就是Map数据,然后直接传到我的方法中就可以导出了,就不用javabean了。

    源码下载 猛戳!!!!

  • 相关阅读:
    spring事物管理五种配置方式
    解决html中内部元素mouse事件干扰
    普通类获取ApplicationContext(附带servletContext)的方法
    SQL学习基础知识
    vs 工具技巧手册
    wcf client与webservice通信备注
    BackgroundWorker学习一
    silverlight发布注意事项
    将wcf 以webservice的方式调用
    Visual Studio 2005 Team Foundation Server (TFS)单服务器安装记
  • 原文地址:https://www.cnblogs.com/zhangxinhua/p/8319230.html
Copyright © 2020-2023  润新知