POI工具操作excel(五)封装基于注解的excel导出工具类

       POI用来导出excel是工作当中经常用到的,但是如果每次导出都要自己写,会显得比较麻烦,代码基本上都是重复的。所以最近花了点时间,学习了一下,自己根据注解,基于反射技术,写了一个POI导出excel的工具类。基本能实现一级和二级表头两种情况的导出。

       这次写的这个例子,是一个简单的SpringBoot工程,关于SpringBoot不了解的,自行学习下。

1、创建SpringBoot工程

1.1 导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>POI_SpringBoot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 定义公共资源版本 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!-- 上边引入 parent,因此 下边无需指定版本 -->
        <!-- 包含 mvc,aop 等jar资源 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--spring操作数据库jpa  用于将数据存入数据库的类和方法的集-->
        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>-->

        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>true</scope>
        </dependency>

        <!--spring模板引擎-->
        <!--<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>-->

        <!--数据库相关-->
        <!--<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>-->

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>



    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 没有该配置,devtools 不生效 -->
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

1.2 启动类

package com.poi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PoiApplication {
    public static void main(String[] args) {
        SpringApplication.run(PoiApplication.class,args);
    }
}

1.3 配置文件application.yml

我这里的配置就只配置了端口号,其他都没进行设置,有需要的可以自己进行设置。

server:
  port: 9000

2、自定义注解

       在进行excel导出的时候,我们需要设置一些excel的单元格样式,比如:行高,列宽、字体和字体颜色等等属性。为了能灵活的设置,所以需要先定义一个注解,通过注解来设置每一列的属性。

package com.poi.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)//表示这个注解只能用到属性
@Retention(RetentionPolicy.RUNTIME)//表示这个注解在运行时会存在,自定义注解一般设置为这个值
public @interface ExcelColumn {
    /**
     * @Title: title
     * @Description: 表头列名 必填
     */
    public String title();

    /**
     * 列的序号,意思就是把添加这个注解的属性要放到excel的第几列,从1开始
     * 需要注意的是:这个值必须连续,比如:各个属性的sort必须是:1,3,2,4,6,5(可以乱序)
        但是不能出现:1,3,4,6,5(少了2)
     */
    public int sort();

    /**
     * @Title: width
     * @Description: 列宽 默认15
     */
    public short width() default 15;

    public enum Alignment {
        LEFT(0x1), CENTER(0x2), RIGHT(0x3);
        private int value;

        private Alignment(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
    };

    /**
     * @Title: alignment
     * @Description: 文字样式 默认居中(Alignment.CENTER)
     */
    public Alignment alignment() default Alignment.CENTER;

    /**
     * @Title: boder
     * @Description: 单元格是否需要边框 环绕包围 默认true
     */
    public boolean boder() default true;

    public enum StyleColor {
        WHITE(0x9), BLACK(0x8), BLUE(0xc), RED(0xa), YELLOW(0xd);
        private int value;

        private StyleColor(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
    };

    /**
     * @Title: styleColor
     * @Description: 单元格背景色 默认白色
     */
    public StyleColor styleColor() default StyleColor.WHITE;

    public enum FontColor {
        BLACK(0x8), BLUE(0xc), RED(0xa), YELLOW(0xd);
        private int value;

        private FontColor(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
    };

    /**
     * @Title: fontColor
     * @Description: 文字颜色 默认黑色(FontColor.BLACK) 暂支持 BLACK BLUE RED YELLO
     */
    public FontColor fontColor() default FontColor.BLACK;

    /**
     * @Title: fontSize
     * @Description: 字号大小 默认12
     */
    public short fontSize() default 12;

    /**
     * @Title: fontName
     * @Description: 字体 默认微软雅黑
     */
    public String fontName() default "微软雅黑";
}

3、导出excel的工具类

工具类中,用到了反射技术来获取类的属性以及注解,所以需要对反射有一定了解。

工具类直接进行excel文件的下载,而且下载不会出现中文乱码的问题,因为里面也做了相应的处理。

package com.poi.util;

import com.poi.annotation.ExcelColumn;
import org.apache.poi.hssf.usermodel.HSSFBorderFormatting;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;

/**
 * excel导出工具类
 */
@SuppressWarnings("all")
public class ExcelExpUtil<T> {

    private Logger log = LoggerFactory.getLogger(ExcelExpUtil.class);//日志记录

    private Class clazz;//导出目标类的Class对象
    private int colNum;//总列数
    private int startRowIndex;//导出内容开始的行号,不包括表头
    private Field[] fields;//所有是属性数组
    private String titleName;//标题内容
    private String[] headerArr;//要合并的表头数组


    private String[] headers;// 列名集合
    private Short[] columnWidth ;// 列宽集合
    private Integer[] alignList ;// 内文样式位置集合,左对齐,居中或右对齐
    private Boolean[] boderList ;// 是否需要边框  集合
    private Integer[] fontColorList;// 字体颜色集合
    private String[] fontNameList ;// 字体集合
    private Short[] fontSizeList;// 字号集合
    private Integer[] styleColorList ;// 单元格背景色  集合
    private Field[] excelFileds ;//存放有注解的字段  也就是需要导出的字段  无注解字段排除

    /**
     * 没有合并表头的构造方法
     * @param clazz         导出类的CLass对象,通过它来反射获取对应的属性和注解
     * @param titleName     标题名称
     * @param colNum        总列数,在导出之前我们应该已经知道总共的列数了
     * @param startRowIndex 导出内容开始的行号,不包括表头
     */
    public ExcelExpUtil(Class clazz,String titleName, int colNum, int startRowIndex){
        this.clazz=clazz;
        this.titleName = titleName;
        this.colNum = colNum;
        this.startRowIndex = startRowIndex-1;//从0开始的,所以减1
        this.fields = clazz.getDeclaredFields();//通过发射获取类的所有属性,包括私有属性
        this.headers = new String[colNum];
        this.columnWidth = new Short[colNum];
        this.alignList = new Integer[colNum];
        this.boderList = new Boolean[colNum];
        this.fontColorList = new Integer[colNum];
        this.fontNameList = new String[colNum];
        this.fontSizeList = new Short[colNum];
        this.styleColorList = new Integer[colNum];
        this.excelFileds = new Field[colNum];
    }

    /**
     * 有一行合并表头的构造方法
     * @param clazz         导出类的CLass对象
     * @param titleName     标题名称
     * @param colNum        总列数
     * @param startRowIndex 导出内容开始的行号,不包括表头
     * @param headerArr     要合并的表头数组
     */
    public ExcelExpUtil(Class clazz,String titleName, int colNum, int startRowIndex,String[] headerArr){
        this(clazz,titleName,colNum,startRowIndex);//调用另一个构造方法
        this.headerArr = headerArr;
    }

    /**
     * 导出excel的方法
     * @param dataList   导出的业务数据
     * @param response   浏览器下载的流
     * @param fileName   导出的文件名
     * @param ext        导出的文件的扩展名,.xls  .xlsx
     */
    public void excelExp(List<T> dataList,HttpServletRequest request, HttpServletResponse response, String fileName, String ext){
        //根据后缀名得到工作簿对象
        Workbook workbook = getWorkBook(ext);
        if(workbook != null){
            creatSheet(workbook, dataList);//创建sheet页
            //下载文件
            this.downloadFile(workbook,request,response,fileName,ext);
        }else{
            log.error("创建工作簿失败");
        }
    }

    //创建sheet
    private void creatSheet(Workbook workbook, List<T> dataList) {
        if(dataList==null || dataList.size()<=0){
            return;
        }
        Sheet sheet = workbook.createSheet();//sheet对象
        Row row =null;//行对象
        Cell cell = null;//列对象
        ExcelColumn excelColumn = null;
        int j=0;//相当于是列号,从0开始的
        for(short i = 0; i < fields.length; i++){//遍历属性的集合,得到有注解的属性的集合
            Field field = fields[i];//得到属性
            //判断属性上面是否有注解:ExcelColumn
            if(field.isAnnotationPresent(ExcelColumn.class)){
                excelColumn = (ExcelColumn)field.getAnnotation(ExcelColumn.class);//通过属性获取指定的注解信息
                j = excelColumn.sort()-1;//属性上注解的列号是从1开始的,其实poi中的列号是从0开始的,所以这里减1

                excelFileds[j] = field;//放入到要导出字段的集合中
                headers[j] = excelColumn.title();//把列名放入到列名集合中
                columnWidth[j]=excelColumn.width();//把宽度放入到宽度集合中
                alignList[j]=excelColumn.alignment().getValue();
                boderList[j]=excelColumn.boder();
                fontColorList[j]=excelColumn.fontColor().getValue();
                fontNameList[j]=excelColumn.fontName();
                fontSizeList[j]=excelColumn.fontSize();
                styleColorList[j]=excelColumn.styleColor().getValue();
            }
        }

        // 循环设置列宽
        int length = columnWidth.length;
        for (int i = 0; i < length; i++) {
            sheet.setColumnWidth(i, columnWidth[i] * 256);
        }

        // 产生表格标题行,标题行是第一行
        this.createTitle(workbook,sheet,row);

        // 合并表头行设置
        if(this.headerArr!=null){
            this.createHeBinHeader(workbook,sheet,row,cell);
        }

        //生成表头行,用的header中的数据
        this.createHeader(workbook,sheet,row,cell);

        // 遍历集合数据,产生数据行
        this.setDataToSheet(workbook,sheet,row,cell,dataList);
    }

    //根据表头数组信息合并行
    private void createHeBinHeader(Workbook workbook, Sheet sheet, Row row, Cell cell) {
        row = sheet.createRow(1);//第二行是合并表头的行,行号为1
        row.setHeightInPoints(25);//设置行高
        CellStyle boderStyle = workbook.createCellStyle();//创建一个样式
        Font font = workbook.createFont();// 生成一个字体 默认字体微软雅黑
        font.setFontHeightInPoints((short)20);// 设置字体大小
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);//字体加粗
        boderStyle.setFont(font);// 把字体应用到当前的样式

        //设置边框
        //boderStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        /*boderStyle.setBorderBottom(CellStyle.BORDER_THIN);
        boderStyle.setBorderLeft(CellStyle.BORDER_THIN);
        boderStyle.setBorderRight(CellStyle.BORDER_THIN);
        boderStyle.setBorderTop(CellStyle.BORDER_THIN);*/
        //垂直居中
        boderStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        boderStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式

        String[] zuoBiaoArr = null;
        int colIndex = 0;//列起始行号
        for(int i = 0; i<headerArr.length;i++){
            String[] valueArr = headerArr[i].split("#");
            String cellValue = valueArr[0];//单元格内容
            String zuoBiaoStr = valueArr[1];
            zuoBiaoArr = zuoBiaoStr.split(",");

            colIndex=this.colNum-(this.colNum-Integer.parseInt(zuoBiaoArr[3]))-1;
            cell = row.createCell(colIndex);//得到列
            cell.setCellStyle(boderStyle);//设置样式
            cell.setCellValue(cellValue);//设置内容
            sheet.addMergedRegion(new CellRangeAddress(Integer.parseInt(zuoBiaoArr[0]),
                    Integer.parseInt(zuoBiaoArr[1]), Integer.parseInt(zuoBiaoArr[2]), Integer.parseInt(zuoBiaoArr[3])));//设置合并
            //colIndex += Integer.parseInt(zuoBiaoArr[3])+1;//第二列的开始列号
        }
    }

    /**
     * 循环遍历,把数据设置到表格中的方法
     * @param workbook      工作簿
     * @param row           行对象
     * @param cell          单元格对象
     * @param sheet         sheet对象
     * @param dataList      数据集合
     * @param alignList     对齐方式集合
     * @param boderList     是否边框的集合
     * @param fontColorList 字体颜色的集合
     * @param fontNameList  字体名称的集合
     * @param fontSizeList  字体大小的集合
     * @param styleColorList 背景颜色的集合
     * @param excelFileds   需要导出的列 集合
     */
    private void setDataToSheet(Workbook workbook, Sheet sheet, Row row,Cell cell, List<T> dataList) {
        Iterator<T> it = dataList.iterator();
        while (it.hasNext()) {
            row = sheet.createRow(startRowIndex++);//从第几行开始
            T t = (T) it.next();
            // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
            for (int i = 0; i < excelFileds.length; i++) {
                cell = row.createCell(i);
                Field field = excelFileds[i];//获取属性
                field.setAccessible(true);//忽略检查,不加这个写入不了数据
                //调用方法进行样式设置
                this.setCellStyle(workbook, cell, alignList[i], boderList[i],styleColorList[i],
                                    fontColorList[i],  fontNameList[i],fontSizeList[i],false);
                String fieldName = field.getName();//得到属性名称
                //得到属性的get方法名称
                String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                try {
                    cell.setCellValue(field.get(t).toString());

                    //另外一种手动拼get方法的方式获取值
                    //得到对应的方法
                    /*Method getMethod = this.clazz.getMethod(getMethodName, new Class[] {});
                    //执行方法,得到返回值
                    Object value = getMethod.invoke(t, new Object[] {});
                    String textValue = value.toString();
                    if (textValue != null) {
                        RichTextString richString = new HSSFRichTextString(textValue);
                        cell.setCellValue(richString);
                    }*/
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //生成表头行
    private void createHeader(Workbook workbook, Sheet sheet,Row row,Cell cell) {
        row = sheet.createRow(this.startRowIndex-1);//内容开始行的上一行是表头行
        for (int i = 0; i < headers.length; i++) {
            cell = row.createCell(i);
            //调用方法设置样式
            this.setCellStyle(workbook, cell, alignList[i], boderList[i],styleColorList[i], fontColorList[i],  fontNameList[i],fontSizeList[i],true);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);//获取该列的值
            cell.setCellValue(text);//把值设置到单元格中
        }
    }

    /**
     * 创建标题行的方法
     * @param workbook
     * @param sheet
     * @param row
     */
    private void createTitle(Workbook workbook,Sheet sheet,Row row){
        row = sheet.createRow(0);//标题行
        row.setHeightInPoints(50);//设置行高
        Cell titleCell = row.createCell(0);//得到标题列

        CellStyle cellStyle = workbook.createCellStyle();
        // 生成一个字体 默认字体微软雅黑
        Font font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short)30);
        // 字体加粗
        font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        cellStyle.setFont(font);

        //垂直居中
        cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cellStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
        titleCell.setCellStyle(cellStyle);//设置样式

        titleCell.setCellValue(this.titleName);//设置内容
        sheet.addMergedRegion(new CellRangeAddress(row.getRowNum(),
                row.getRowNum(), row.getRowNum(), this.colNum-1));//设置合并
    }

    /**
     * @Title: 设置单元格样式的方法
     * @param workbook   工作簿
     * @param cell       要配置的单元格
     * @param alignment  单元格内文样式
     * @param needBoder  是否需要环绕边框
     * @param sytleColor 单元格背景色
     * @param fontColor  文字颜色
     * @param fontName   字体
     * @param fontSize   字号
     * @param isBold     表头是否加粗
     * @Description: 设置单元格以及字体的整体样式
     */
    private void setCellStyle(Workbook workbook, Cell cell, int alignment, Boolean needBoder, int sytleColor,int fontColor,
                              String fontName,short fontSize,boolean isBold) {
        // 生成一个通用样式 默认背景为白色
        CellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor((short)sytleColor);

        // 单元格内容样式
        style.setAlignment((short) alignment);

        // 单元格是否需要边框
        if (needBoder) {
            style.setFillPattern(CellStyle.SOLID_FOREGROUND);
            style.setBorderBottom(CellStyle.BORDER_THIN);
            style.setBorderLeft(CellStyle.BORDER_THIN);
            style.setBorderRight(CellStyle.BORDER_THIN);
            style.setBorderTop(CellStyle.BORDER_THIN);
        }

        // 生成一个字体 默认字体微软雅黑
        Font font = workbook.createFont();
        font.setFontName(fontName);
        font.setColor((short) fontColor);

        // 设置字体大小
        font.setFontHeightInPoints(fontSize);

        // 字体是否加粗
        if (isBold) {
            font.setBoldweight(Font.BOLDWEIGHT_BOLD);
        }

        // 把字体应用到当前的样式
        style.setFont(font);
        cell.setCellStyle(style);
    }

    //根据后缀名得到工作簿对象
    private Workbook getWorkBook(String ext){

        if(".xls".equals(ext)){
            return new HSSFWorkbook();
        }
        if(".xlsx".equals(ext)){
            return new SXSSFWorkbook();
        }
        log.error("扩展名只能为【.xls】或【.xlsx】");
        return null;
    }

    /**
     * 文件下载的方法
     * @param workbook  工作簿
     * @param request   请求
     * @param response  响应
     * @param filename  文件名称
     * @param ext       文件扩展名
     */
    private void downloadFile(Workbook workbook,HttpServletRequest request, HttpServletResponse response,String filename,String ext){
        filename = filename+ext;//文件名+扩展名
        //调用其他下载方法
        downloadFile(workbook,request,response,filename);
    }

    private void downloadFile(Workbook workbook,HttpServletRequest request, HttpServletResponse response,String filename){
        try {
            //从请求头中获取User-Agent判断当前使用的是否是火狐浏览器
            String agent = request.getHeader("User-Agent");
            //根据不同浏览器进行不同的编码
            String realFilename = "";
            if (agent.contains("MSIE")) {
                // IE浏览器
                realFilename = URLEncoder.encode(filename, "utf-8");
                realFilename = realFilename.replace("+", " ");
            } else if (agent.contains("Firefox")) {
                // 火狐浏览器,此处使用java8
                realFilename = "=?utf-8?B?" + Base64.getEncoder().encodeToString(filename.getBytes("utf-8")) + "?=";
            } else {
                // 其它浏览器
                realFilename = URLEncoder.encode(filename, "utf-8");
            }
            //设置要被下载的文件名
            response.setHeader("Content-Disposition","attachment;filename="+realFilename);
            response.setContentType("application/octet-stream");
            response.setHeader("filename", filename);
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、测试导出

4.1 在Java类中添加注解

package com.poi.pojo;

import com.poi.annotation.ExcelColumn;

import java.util.Date;

public class User {
    //如果这个属性需要导出,那么就在上面添加注解信息
    @ExcelColumn(title = "姓名",width = 20,alignment = ExcelColumn.Alignment.CENTER,sort=2)
    private String name;
    @ExcelColumn(title = "用户ID",width = 10,alignment = ExcelColumn.Alignment.LEFT,styleColor = ExcelColumn.StyleColor.RED,sort=1)
    private String id;

    @ExcelColumn(title = "年龄",width = 10,alignment = ExcelColumn.Alignment.CENTER,sort=4)
    private int age;
    //@ExcelColumn(title = "出生日期",width = 20,alignment = ExcelColumn.Alignment.LEFT,sort=4)
    private Date birthday;
    @ExcelColumn(title = "家庭住址",width = 50,alignment = ExcelColumn.Alignment.LEFT,fontColor = ExcelColumn.FontColor.BLUE,sort=5)
    private String address;
    @ExcelColumn(title = "身高",width = 10,alignment = ExcelColumn.Alignment.CENTER,sort=3)
    private double high;

    public User() {
    }

    public User(String id, String name, int age, Date birthday, String address, double high) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.birthday = birthday;
        this.address = address;
        this.high = high;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public double getHigh() {
        return high;
    }

    public void setHigh(double high) {
        this.high = high;
    }
}

4.2 创建控制器

package com.poi.controller;

import com.poi.pojo.User;
import com.poi.util.ExcelExpUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/excel")
public class UserExcelController {

    @RequestMapping("/userList")
    public void expUserList(HttpServletRequest request,HttpServletResponse response){
        //查询业务数据,实际工程中应该是从数据库中查询的
        List<User> userList = this.getDataList();

        //调用工具类方法进行导出
        new ExcelExpUtil(User.class,"用户列表",5,3)
                .excelExp(userList,request,response,"用户列表",".xlsx");
    }

    private List<User> getDataList() {

        List<User> userList = new ArrayList<>();
        User user1 = new User("1001","老庞",38,new Date(System.currentTimeMillis()-1000*60*60*24*365),"湖南省长沙市岳麓区岳麓书院1",180.5);
        User user2 = new User("1002","老王",38,new Date(System.currentTimeMillis()-1000*60*60*24),"湖南省长沙市岳麓区岳麓书院2",170.5);
        User user3 = new User("1003","老李",38,new Date(System.currentTimeMillis()-1000*60*60*24*365*2),"湖南省长沙市岳麓区岳麓书院3",160.5);
        User user4 = new User("1004","老周",38,new Date(System.currentTimeMillis()-1000*60*60*24*365*10),"湖南省长沙市岳麓区岳麓书院4",190.5);
        User user5 = new User("1005","老赵",38,new Date(System.currentTimeMillis()-1000*60*60*24*365*20),"湖南省长沙市岳麓区岳麓书院5",150.5);
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);
        userList.add(user5);

        return userList;
    }
}

4.3 效果

启动工程,访问:http://127.0.0.1:9000/excel/userList就可以进行excel文件的下载了,下载打开后的效果如下:

5、测试合并一级表头

5.1、创建新的测试java对象

package com.poi.pojo;

import com.poi.annotation.ExcelColumn;

public class Dog {
    @ExcelColumn(title = "宠物ID",sort = 2,width = 10)
    private int id;
    @ExcelColumn(title = "宠物名称",sort = 1,width = 20)
    private String name;
    @ExcelColumn(title = "宠物的颜色",sort = 3,width = 20)
    private String color;
    @ExcelColumn(title = "宠物主人ID",sort = 5,width = 10)
    private String userId;
    @ExcelColumn(title = "宠物喜欢吃的食物",sort = 4,width = 30)
    private String eat;
    @ExcelColumn(title = "宠物主人名称",sort = 6,width = 20)
    private String userName;


    public Dog(int id, String name, String color,String eat, String userId, String userName) {
        this.id = id;
        this.name = name;
        this.color = color;
        this.eat = eat;
        this.userId = userId;
        this.userName = userName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getEat() {
        return eat;
    }

    public void setEat(String eat) {
        this.eat = eat;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

5.2 创建控制器

package com.poi.controller;

import com.poi.pojo.Dog;
import com.poi.util.ExcelExpUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/excel")
public class DogController {

    @RequestMapping("/dogList")
    public void excelExport(HttpServletRequest request, HttpServletResponse response){

        //构造合并的表头行信息
        String[] headerArr = new String[3];
        headerArr[0] = "宠物信息1#1,1,0,1";
        headerArr[1] = "宠物信息2#1,1,2,3";
        headerArr[2] = "主人信息#1,1,4,5";

        List<Dog> dogList = new ArrayList<>();
        Dog dog1 = new Dog(1,"小坏猫咪","五颜六色的好好看","就是喜欢吃死老鼠","1001","老庞");
        Dog dog2 = new Dog(1,"小乖兔兔","纯白纯白的好漂亮","就是喜欢吃胡萝卜","1001","老庞");
        dogList.add(dog1);
        dogList.add(dog2);
        //这里调用的是可以合并表头的构造方法
        new ExcelExpUtil(Dog.class,"宠物列表",6,4,headerArr)
                .excelExp(dogList,request,response,"宠物列表",".xlsx");
    }
}

5.3 查看导出效果

运行工程,请求:http://127.0.0.1:9000/excel/dogList,效果如下:

发布了81 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zengdongwen/article/details/103933066