zoukankan      html  css  js  c++  java
  • 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了。

    源码下载 猛戳!!!!

  • 相关阅读:
    Building Java Projects with Gradle
    Vert.x简介
    Spring及Spring Boot 国内快速开发框架
    dip vs di vs ioc
    Tools (StExBar vs Cmder)which can switch to command line window on context menu in windows OS
    SSO的定义、原理、组件及应用
    ModSecurity is an open source, cross-platform web application firewall (WAF) module.
    TDD中测试替身学习总结
    Spring事务银行转账示例
    台式机(华硕主板)前面板音频接口(耳机和麦克风)均无声的解决办法
  • 原文地址:https://www.cnblogs.com/zhangxinhua/p/8319230.html
Copyright © 2011-2022 走看看