温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

SpringBoot项目中利用POI实现导出Excel

发布时间:2020-11-07 16:45:11 来源:亿速云 阅读:181 作者:Leah 栏目:开发技术

这期内容当中小编将会给大家带来有关SpringBoot项目中利用POI实现导出Excel,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一、准备工作

1、pom依赖

在pom.xml中加入POI的依赖

<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi-ooxml</artifactId>
 <version>3.11-beta1</version>
</dependency>
<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi-ooxml-schemas</artifactId>
 <version>3.11-beta1</version>
</dependency>

2、自定义注解

自定义注解,用于定义excel单元格的相关信息,用在需要导出的类上。

大家可以根据自己的实际需求来定义更多的内容。

@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelResources {
 
 int order() default 9999;//定义字段在excel的单元格列坐标位置

 String title() default "";//定义列坐标对应的标题

 int cloumn() default 100;//定义列宽

 String pattern() default "";//定义日期显示格式

}

3、定义需要导出的实体

举例说明@ExcelResources 的应用场景,我们创建一个demoModel,包含姓名、年龄、性别、日期。

后边的excel导出例子也采用这个实体类来举例。

@Data
public class ExcelDemoModel {

  @ExcelResources(order=0,title = "姓名",cloumn = 10)
  private String name;

  @ExcelResources(order=1,title = "年龄",cloumn = 10)
  private Integer age;

  @ExcelResources(order=2,title = "创建时间",cloumn = 24,pattern = "yyyy-MM-dd HH:mm:ss")
  private Date createTime;

  @ExcelResources(order=3,title = "性别",cloumn = 10)
  private SexType sex;//枚举
  
}

4、定义导出辅助类

用于存放导出的excel对应标题和列宽

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TitleAndCloumn {

  private String title;//标题
  private int cloumn;//列宽

}

二、具体的导出方法

1、导出主要方法

@Service
public class ExcelService {

  private static float title_row_height=30;//标题行高
  private static float data_row_height=25;//数据行高

 public void exportExcel(HttpServletRequest request, HttpServletResponse response, String fileName ,List<&#63;> excelDatas,Class<&#63;> clz ) {
 
    try {

      HSSFWorkbook resultWb=new HSSFWorkbook();
      HSSFSheet sheet=resultWb.createSheet();//创建sheet

  //根据类类型信息获取导出的excel对应的标题和列宽 key-列号,value-标题和列宽
      HashMap<Integer, TitleAndCloumn> orderTitleAndCloumnMap=getTitleAndCloumnMap(clz);

      //设置列宽
      orderTitleAndCloumnMap.forEach((k,v) -> {
        sheet.setColumnWidth(k, v.getCloumn()*256);
      });

      HSSFRow row0=sheet.createRow(0);
      //设置标题行高
      row0.setHeightInPoints(title_row_height);

  //创建标题单元格格式
      HSSFCellStyle titleCellStyle=getCellStyle(resultWb,11,true,HSSFColor.BLACK.index);
      //填充标题行内容
      orderTitleAndCloumnMap.forEach((k,v) -> {
        HSSFCell row0Cell=row0.createCell(k);
        row0Cell.setCellValue(v.getTitle());
        row0Cell.setCellStyle(titleCellStyle);
      });

  //创建正文单元格格式
      HSSFCellStyle dataStyle = getCellStyle(resultWb,11,false,HSSFColor.BLACK.index);

  //将正文转换为excel数据
      int rowNum=1;
      for(Object data:excelDatas){

        HSSFRow row=sheet.createRow(rowNum++);
        row.setHeightInPoints(data_row_height);
  //获取对象值 key-列号 value-String值
        HashMap<Integer,String> orderValueMap=getValueMap(data);
        orderValueMap.forEach((k,v) ->{
          HSSFCell cell=row.createCell(k);
          cell.setCellValue(v);
          cell.setCellStyle(dataStyle);
            }
        );
      }

      String downFileName=fileName+".xls";
      response.setContentType("application/vnd.ms-excel; charset=UTF-8");// application/x-download
      response.setHeader("Content-Disposition", "attachment; "
          +encodeFileName(request, downFileName));

      OutputStream outputStream = response.getOutputStream();
      resultWb.write(outputStream);
      outputStream.flush();
      outputStream.close();
      resultWb.close();

    }catch (Exception e1) {
      e1.printStackTrace();
    }

  }
}

2、通过反射获取excel标题和列宽

/**
   * 获取类的属性对应单元格标题和列宽
   * @param
   * @return
   */
  private static HashMap<Integer, TitleAndCloumn> getTitleAndCloumnMap(Class<&#63;> clz) {

    HashMap<Integer, TitleAndCloumn> orderTitleAndCloumnMap=new HashMap<>();

    Field[] fs = clz.getDeclaredFields();
    for(Field f:fs) {
      f.setAccessible(true);
      if(f.isAnnotationPresent(ExcelResources.class)) {
        Integer order=f.getAnnotation(ExcelResources.class).order();
        String title=f.getAnnotation(ExcelResources.class).title();
        int cloumn=f.getAnnotation(ExcelResources.class).cloumn();

        TitleAndCloumn titleAndCloumn=new TitleAndCloumn(title,cloumn);
        orderTitleAndCloumnMap.put(order,titleAndCloumn);
      }
    }

    return orderTitleAndCloumnMap;

  }

3、创建CellStyle

通过传入参数定义简单地CellStyle

public HSSFCellStyle getCellStyle(HSSFWorkbook workbook,int fontSize,boolean isBoleaWeight,short color){

    HSSFCellStyle style = workbook.createCellStyle();
    style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
    style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中

    style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
    style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
    style.setBorderRight(HSSFCellStyle.BORDER_THIN);
    style.setBorderTop(HSSFCellStyle.BORDER_THIN);

    HSSFFont font = workbook.createFont();
    font.setFontHeightInPoints((short) fontSize);//字号
    font.setColor(color);//颜色
    font.setFontName("宋体");//字体

    if(isBoleaWeight){
      font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //字体加粗
    }

    style.setWrapText(true);
    style.setFont(font);

    return style;

  }

4、通过反射获取对象信息并处理成String字符串

我这里只涉及到基本数据类型和Date以及枚举的值获取和转换,小伙伴可以根据自己的实际情况进行修改。

/**
   * 获取对象的属性对应单元格坐标和值的键值对
   * @param obj
   * @return
   */
  private static HashMap<Integer, String> getValueMap(Object obj) throws IllegalAccessException {

    HashMap<Integer, String> result=new HashMap<>();

    Class<&#63;> clz=obj.getClass();
    Field[] fs = clz.getDeclaredFields();
    for(Field f:fs) {
      f.setAccessible(true);
      if(f.isAnnotationPresent(ExcelResources.class)) {
        Integer order=f.getAnnotation(ExcelResources.class).order();
        String value="";

        Object valueObj=f.get(obj);
        if(valueObj!=null) {
   //日期格式进行特殊处理
          if(f.getType()==Date.class){

            String pattern=f.getAnnotation(ExcelResources.class).pattern();
            if(StringUtils.isEmpty(pattern)){
              pattern="yyyy-MM-dd HH:mm:ss";
            }
            SimpleDateFormat sdf=new SimpleDateFormat(pattern);
            value=sdf.format(valueObj);
          }else{
            value=valueObj.toString();//其他格式调用toString方法,这里枚举就需要定义自己的toString方法
          }

        }

        result.put(order, value);

      }
    }

    return result;
  }

5、枚举的定义

如果有用到枚举存储在数据库的小伙伴,可以自定义枚举的toString方法来实现excel导出时候相应的内容

public enum SexType {
 
 male("男"),
 female("女"),
 ;

 private String typeName;

 SexType(String typeName) {
 this.typeName = typeName;
 }

 @Override
 public String toString() {
 return typeName;
 }

}

6、encodeFileName

 /**
   * 根据不同的浏览器生成不同类型中文文件名编码
   *
   * @param request
   * @param fileName
   * @return
   * @throws UnsupportedEncodingException
   */
  public static String encodeFileName(HttpServletRequest request, String fileName)
      throws UnsupportedEncodingException
  {

    String new_filename = URLEncoder.encode(fileName, "UTF8").replaceAll("\\+", "%20");

    String agent = request.getHeader("USER-AGENT").toLowerCase();
    if (null != agent && -1 != agent.indexOf("msie"))
    {
      /**
       * IE浏览器,只能采用URLEncoder编码
       */
      return "filename=\"" + new_filename +"\"";
    }else if (null != agent && -1 != agent.indexOf("applewebkit")){
      /**
       * Chrome浏览器,只能采用ISO编码的中文输出
       */
      return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";
    } else if (null != agent && -1 != agent.indexOf("opera")){
      /**
       * Opera浏览器只可以使用filename*的中文输出
       * RFC2231规定的标准
       */
      return "filename*=" + new_filename ;
    }else if (null != agent && -1 != agent.indexOf("safari")){
      /**
       * Safani浏览器,只能采用iso编码的中文输出
       */
      return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";
    }else if (null != agent && -1 != agent.indexOf("firefox"))
    {
      /**
       * Firfox浏览器,可以使用filename*的中文输出
       * RFC2231规定的标准
       */
      return "filename*=" + new_filename ;
    } else
    {
      return "filename=\"" + new_filename +"\"";
    }
  }

三、方法调用案例

1、方法调用

public void exportExcelDemo(HttpServletRequest request, HttpServletResponse response) {

  //一系列查询处理
    List<ExcelDemoModel> demoList=new ArrayList<>();
    
    excelService.exportExcel(request,response,"人员信息demo",demoList,ExcelDemoModel.class);

  }

2、导出效果

SpringBoot项目中利用POI实现导出Excel

上述就是小编为大家分享的SpringBoot项目中利用POI实现导出Excel了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI