Spring通过poi简单封装excel导出的工具类

Spring通过poi简单封装excel导出的工具类

  • 前言
  • 分析
    • excel组成
      • 文件组成
      • sheet的通常使用格式
  • 工具类的设计与实现
    • 数据单元
    • sheet
    • excel文件载体
    • 通用工具类
    • 处理器
  • 功能分配汇总
  • 需要的依赖
  • 总结
  • 代码
    • ExcelColumn
    • Sheet
    • ExcelProcessor
    • StandardExcelProcessor
    • ExcelUtil
    • ExcelWorkBookCreator
  • 测试
  • 码云

前言

  首先,当准备看这个博客的时候,就默认大家已经会使用spring进行javaweb开发以及使用poi导出excel。相信大家在进行excel导出的时候都会发现,代码冗余较多,如果每导出一个excel文件就写一段代码的话,代码重复量巨大,出了问题也难以定位问题的所在。那么自己封装一个导出excel的工具类就显得十分有意义了。
  那么我们可以通过什么方式来构建这个工具类呢?
  相信大家在使用spring开发项目的时候都使用过hibernate、mybatis来查询处理数据库中的数据,而这类框架的名称叫做ORM(Object Relational Mapping)框架,即对象关系映射框架。ORM的思想是将数据库中的每一个关系(即表)映射到一个实体类上,用类代表表、对象代表一条条记录、类的属性代表表中的字段。
  大家也都知道,数据库通常分为关系型数据库和非关系型数据库,而关系型数据库中数据的存储展示方式与excel表格十分相似,那我们为什么不能模仿ORM来进行excel导出辅助工具类的设计呢?

分析

excel组成

  在生成excel之前我们首先要知道一个excel文件的结构以及一个excel文件通常是什么样的。

文件组成

  首先我们来看一个简单的例子,这是关于学生信息统计的excel表格。
Spring通过poi简单封装excel导出的工具类_第1张图片

  在图中我们可以发现一个excel文件结构是:一个excel文件(A对应的xxx.xls)包含多个sheet(C对应的部分),而一个sheet包含多个单元格(cell)(B对应的部分)。

sheet的通常使用格式

  通常我们将一个sheet分成四个模块:标题、表头、数据和标尾。
Spring通过poi简单封装excel导出的工具类_第2张图片
  但是我们知道,一个excel表格中,只有表头和数据部分是必须出现的,少了任何一个便不能成为一个完整的数据呈现载体。而标题和标尾不能强求,说不定别人一个文件想要,另一个就不想要了,所以表头和数据部分是必须的,而标题和标尾应该可以供用户选择,留出扩展实现的接口。

工具类的设计与实现

  我们使用自底向上的思路,从cell开始,直到excel文件。

数据单元

  我们知道,在spring-data-jpa中是使用@Entity来标明这个类这是一个实体,需要映射到某张表;而用@Column标明这个属性需要映射到表中的一个字段。那我们是不是也可以通过注解的方式来标注实体的映射信息呢?
  我们可以分别用两个注解,一个类注解来表明这个实体类对应一个sheet,一个属性注解来表明这个属性对应一个表头。(由于时间原因这里只实现了后者
  话不多说,直接贴一下代码:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
     
    /**
     * 该字段出现在 excel 表格的顺序
     *
     * @return
     */
    int order();

    /**
     * 该字段在表头的名称
     *
     * @return
     */
    String description();

    /**
     * 标题字体大小
     *
     * @return
     */
    short titleFontSize() default (short) 10;

    /**
     * 标题字体粗细
     *
     * @return
     */
    short titleFontWeight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 标题字体颜色
     *
     * @return
     */
    short titleFontColor() default Font.COLOR_NORMAL;

    /**
     * 正文字体大小
     *
     * @return
     */
    short contentFontSize() default (short) 10;

    /**
     * 正文字体粗细
     *
     * @return
     */
    short contentFontWeight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 正文字体颜色
     *
     * @return
     */
    short contentFontColor() default Font.COLOR_NORMAL;

    /**
     * 是否对这一列上锁
     *
     * @return
     */
    boolean columnLocked() default true;
}

  这里除了字体格式、颜色、大小以及是否对该列上锁等基本信息,需要注意的两个属性是order和description,这两个属性不能为空,也是格式构造必不可少的两个部分:
  order:order是这个属性对应的权重,越小,该属性对应的列就越靠前,就像最开始学生信息表,order:学号 < 姓名 < 性别 < 住址。
  description:description是该属性对应的列的表头,如最开始学生信息表的学号、姓名、性别和住址。
  使用方式如下:

class Student{
     
        @ExcelColumn(order = 1, description = "学号")
        private String id;
        @ExcelColumn(order = 2, description = "姓名")
        private String name;
        @ExcelColumn(order = 4, description = "住址")
        private String address;
        @ExcelColumn(order = 3, description = "性别")
        private String sex;

		// 构造方法和getter、setter方法省略
    }

sheet

  现在单元格的载体已经设计好,可以设计单元格的载体sheet了,其实大家也都熟悉sheet,所以这里直接放上代码:

public class Sheet {
     
    private String sheetName; // sheet的名称
    private List<String> orderedTitles; // 排好序的每一列的表头
    private List<?> data; // 具体的数据
    private Class targetClass; // 承载数据的类,如:Student
    private List<Field> orderedFields; // 排好序的属性
    private List<HSSFCellStyle> titleStyle; // 表头的格式
    private List<HSSFCellStyle> contentStyle; // 正文数据的格式
    private HSSFWorkbook hssfWorkbook; // 所属的excel文件
    private ExcelProcessor excelProcessor = new StandardExcelProcessor(); // 处理器(这里默认是标准处理器)
    private boolean customMode = false; // 是否为自定义模式

    // 构造方法和getter、setter方法省略
}

  这里将要利用反射机制对属性进行排序,具体代码如下:

private void initExcelAssistBean() {
     
        Field[] fields = targetClass.getDeclaredFields();
        orderedFields = new ArrayList<>();
        for (Field temp : fields) {
     
            if (temp.getAnnotation(ExcelColumn.class) != null) {
     
                orderedFields.add(temp);
            }
        }
        orderedFields.sort(Comparator.comparingInt(field -> field.getAnnotation(ExcelColumn.class).order()));
        orderedTitles = new ArrayList<>();
        for (Field temp : orderedFields) {
     
            orderedTitles.add(temp.getAnnotation(ExcelColumn.class).description());
        }
        //如果开启自定义模式
        if (customMode) {
     
            titleStyle = new ArrayList<>();
            contentStyle = new ArrayList<>();
            HSSFCellStyle currentCellStyle;
            Font font;
            for (Field temp : orderedFields) {
     
                currentCellStyle = hssfWorkbook.createCellStyle();
                font = hssfWorkbook.createFont();
                font.setFontHeightInPoints(temp.getAnnotation(ExcelColumn.class).titleFontSize());
                font.setBoldweight(temp.getAnnotation(ExcelColumn.class).titleFontWeight());
                font.setColor(temp.getAnnotation(ExcelColumn.class).titleFontColor());
                currentCellStyle.setLocked(false);  // 表头均不能修改
                currentCellStyle.setFont(font);
                titleStyle.add(currentCellStyle);
                currentCellStyle = hssfWorkbook.createCellStyle();
                font = hssfWorkbook.createFont();
                font.setFontHeightInPoints(temp.getAnnotation(ExcelColumn.class).contentFontSize());
                font.setBoldweight(temp.getAnnotation(ExcelColumn.class).contentFontWeight());
                font.setColor(temp.getAnnotation(ExcelColumn.class).contentFontColor());
                currentCellStyle.setLocked(temp.getAnnotation(ExcelColumn.class).columnLocked());
                currentCellStyle.setFont(font);
                contentStyle.add(currentCellStyle);
            }
        }
    }

  该类的每个构造方法都会调用这个初始化方法,而这个方法主要是对属性进行排序(通过order),以及设置表头和正文各种格式样式。

excel文件载体

  虽说可以专门抽象出一个类来描述一个excel文件,可转念一想,一个excel文件其实包含的属性比较少,所以就和工厂类抽象成同一个就好了,下面是代码:

public class ExcelWorkBookCreator {
     
    private String excelFileName; // 文件名称
    private List<Sheet> sheets; // 文件包含的sheets
    private HSSFWorkbook hssfWorkbook; // 文件载体
    private final String EXCEL_SHEET_PASSWORD = "123321"; // 文件密码

    // 构造方法和getter、setter方法省略
}

通用工具类

  在这个类中可以获取ExcelWorkBookCreator,以及一些简单的通用操作:

public class ExcelUtil {
     
    /**
     * 获取 excel 文件创造器
     *
     * @param excelFileName -> excel 文件的名字
     * @return
     */
    public static ExcelWorkBookCreator getExcelWorkBookCreator(String excelFileName) {
     
        return new ExcelWorkBookCreator(excelFileName);
    }
}

处理器

  大家是否还记着之前说的:通常我们将一个sheet分成四个模块:标题、表头、数据和标尾。而标题和标尾不是必须不可的,而在上面我们也没有给这两个模块留有相应的余地。不光如此,一个封装工具无论怎样设计都难做到满足所有需求,所以我们必须留给自己足够的余地。这个时候就很需要处理器了。这里我们模仿spring中ioc容器的PostProcessor,在绘制表头和正文之前(自定义标题)和之后(自定义标尾以及处理一些特殊数据)让用户进行自定义的处理。

public interface ExcelProcessor {
     
    /**
     * 在正式注入数据之前的自定义操作,可以自己设计标题等
     *
     * @param sheet -> 当前 sheet 信息
     * @param currentSheet -> 当前 sheet
     * @return 想要正式注入表头及数据的行数
     */
    Integer customOperationBeforeInvokeData(Sheet sheet, HSSFSheet currentSheet);

    /**
     * 在注入完数据后的自定义操作,如:在表格最后落上日期、对某些数据进行修改等
     * 可以通过 currentSheet..getLastRowNum() 获取最后一行的行标,从 0 开始
     *
     * @param sheet -> 当前 sheet 信息
     * @param currentSheet -> 当前 sheet
     */
    void customOperationAfterInvokeData(Sheet sheet, HSSFSheet currentSheet, int firstRowNum);
}

  通过实现这个接口,我们便可以进行一些扩展的操作。

功能分配汇总

ExcelWorkBookCreator(层级:文件):保存所有sheet,可以导出文件。
Sheet(层次:sheet):保存sheet信息,可以注入数据。
ExcelUtil:进行一些通用操作。
ExcelProcessor:在文件构造前后进行自定义处理。

需要的依赖

<dependency>
	<groupId>org.apache.poigroupId>
	<artifactId>poiartifactId>
	<version>3.12version>
dependency>

总结

  由于从想到要创建这个工具类到实现只用了一两天的时间,所以有许多设计其实并不是特别合理。而且这个工具类也没有使用过,所以可能会出现很多bug。但这里其实我只是提供一种思路,实现还是自己来的好,毕竟用自己实现的才安心。另外这些代码仅供学习,如果在实际环境中使用出现问题,请自负责任。

代码

  **这里是所有内容的代码,仅供学习!真实环境中使用出现问题,这里不负责!**如果嫌麻烦,可以去空间下载。

ExcelColumn

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
     
    /**
     * 该字段出现在 excel 表格的顺序
     *
     * @return
     */
    int order();

    /**
     * 该字段在表头的名称
     *
     * @return
     */
    String description();

    /**
     * 标题字体大小
     *
     * @return
     */
    short titleFontSize() default (short) 10;

    /**
     * 标题字体粗细
     *
     * @return
     */
    short titleFontWeight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 标题字体颜色
     *
     * @return
     */
    short titleFontColor() default Font.COLOR_NORMAL;

    /**
     * 正文字体大小
     *
     * @return
     */
    short contentFontSize() default (short) 10;

    /**
     * 正文字体粗细
     *
     * @return
     */
    short contentFontWeight() default HSSFFont.BOLDWEIGHT_NORMAL;

    /**
     * 正文字体颜色
     *
     * @return
     */
    short contentFontColor() default Font.COLOR_NORMAL;

    /**
     * 是否对这一列上锁
     *
     * @return
     */
    boolean columnLocked() default true;
}

Sheet

public class Sheet {
     
    private String sheetName;
    private List<String> orderedTitles;
    private List<?> data;
    private Class targetClass;
    private List<Field> orderedFields;
    private List<HSSFCellStyle> titleStyle;
    private List<HSSFCellStyle> contentStyle;
    private HSSFWorkbook hssfWorkbook;
    private ExcelProcessor excelProcessor = new StandardExcelProcessor();
    private boolean customMode = false;

    public Sheet() {
     
    }

    public Sheet(HSSFWorkbook hssfWorkbook, String sheetName, List<?> data, Class targetClass) {
     
        this.hssfWorkbook = hssfWorkbook;
        this.sheetName = sheetName;
        this.data = data;
        this.targetClass = targetClass;
        initExcelAssistBean();
    }

    public Sheet(HSSFWorkbook hssfWorkbook, String sheetName, List<?> data, Class targetClass, ExcelProcessor excelProcessor) {
     
        this.hssfWorkbook = hssfWorkbook;
        this.sheetName = sheetName;
        this.data = data;
        this.targetClass = targetClass;
        this.excelProcessor = excelProcessor;
        initExcelAssistBean();
    }

    public Sheet(HSSFWorkbook hssfWorkbook, String sheetName, List<?> data, Class targetClass, boolean customMode) {
     
        this.hssfWorkbook = hssfWorkbook;
        this.sheetName = sheetName;
        this.data = data;
        this.targetClass = targetClass;
        this.customMode = customMode;
        initExcelAssistBean();
    }

    public Sheet(HSSFWorkbook hssfWorkbook, String sheetName, List<?> data, Class targetClass, ExcelProcessor excelProcessor, boolean customMode) {
     
        this.hssfWorkbook = hssfWorkbook;
        this.sheetName = sheetName;
        this.data = data;
        this.targetClass = targetClass;
        this.excelProcessor = excelProcessor;
        this.customMode = customMode;
        initExcelAssistBean();
    }

    private void initExcelAssistBean() {
     
        Field[] fields = targetClass.getDeclaredFields();
        orderedFields = new ArrayList<>();
        for (Field temp : fields) {
     
            if (temp.getAnnotation(ExcelColumn.class) != null) {
     
                orderedFields.add(temp);
            }
        }
        orderedFields.sort(Comparator.comparingInt(field -> field.getAnnotation(ExcelColumn.class).order()));
        orderedTitles = new ArrayList<>();
        for (Field temp : orderedFields) {
     
            orderedTitles.add(temp.getAnnotation(ExcelColumn.class).description());
        }
        //如果开启自定义模式
        if (customMode) {
     
            titleStyle = new ArrayList<>();
            contentStyle = new ArrayList<>();
            HSSFCellStyle currentCellStyle;
            Font font;
            for (Field temp : orderedFields) {
     
                currentCellStyle = hssfWorkbook.createCellStyle();
                font = hssfWorkbook.createFont();
                font.setFontHeightInPoints(temp.getAnnotation(ExcelColumn.class).titleFontSize());
                font.setBoldweight(temp.getAnnotation(ExcelColumn.class).titleFontWeight());
                font.setColor(temp.getAnnotation(ExcelColumn.class).titleFontColor());
                currentCellStyle.setLocked(false);  // 表头均不能修改
                currentCellStyle.setFont(font);
                titleStyle.add(currentCellStyle);
                currentCellStyle = hssfWorkbook.createCellStyle();
                font = hssfWorkbook.createFont();
                font.setFontHeightInPoints(temp.getAnnotation(ExcelColumn.class).contentFontSize());
                font.setBoldweight(temp.getAnnotation(ExcelColumn.class).contentFontWeight());
                font.setColor(temp.getAnnotation(ExcelColumn.class).contentFontColor());
                currentCellStyle.setLocked(temp.getAnnotation(ExcelColumn.class).columnLocked());
                currentCellStyle.setFont(font);
                contentStyle.add(currentCellStyle);
            }
        }
    }

    public void titleCellStyleInvoke(HSSFRow row) {
     
        HSSFCell titleCell;
        for (int titleIndex = 0; titleIndex < orderedTitles.size(); titleIndex++) {
     
            titleCell = row.createCell(titleIndex);
            titleCell.setCellStyle(titleStyle.get(titleIndex));
            titleCell.setCellValue(orderedTitles.get(titleIndex));
        }
    }

    public void contentCellStyleInvoke(HSSFSheet hssfSheet, int firstRowNum) throws Exception {
     
        HSSFRow currentRow;
        for (int rowIndex = firstRowNum + 1; rowIndex < data.size(); rowIndex++) {
     
            currentRow = hssfSheet.createRow(rowIndex);
            HSSFCell currentCell;
            Object obj = data.get(rowIndex);
            for (int cellIndex = 0; cellIndex < orderedFields.size(); cellIndex++) {
     
                currentCell = currentRow.createCell(cellIndex);
                currentCell.setCellStyle(contentStyle.get(cellIndex));
                if (!orderedFields.get(cellIndex).isAccessible()) {
     
                    orderedFields.get(cellIndex).setAccessible(true);
                    if (orderedFields.get(cellIndex).get(obj) != null) {
     
                        currentCell.setCellValue(orderedFields.get(cellIndex).get(obj).toString());
                    }
                    orderedFields.get(cellIndex).setAccessible(false);
                } else {
     
                    if (orderedFields.get(cellIndex).get(obj) != null) {
     
                        currentCell.setCellValue(orderedFields.get(cellIndex).get(obj).toString());
                    }
                }
            }
        }
    }

    public String getSheetName() {
     
        return sheetName;
    }

    public void setSheetName(String sheetName) {
     
        this.sheetName = sheetName;
    }

    public List<String> getOrderedTitles() {
     
        return orderedTitles;
    }

    public void setOrderedTitles(List<String> orderedTitles) {
     
        this.orderedTitles = orderedTitles;
    }

    public List<?> getData() {
     
        return data;
    }

    public void setData(List<?> data) {
     
        this.data = data;
    }

    public Class getTargetClass() {
     
        return targetClass;
    }

    public void setTargetClass(Class targetClass) {
     
        this.targetClass = targetClass;
    }

    public List<Field> getOrderedFields() {
     
        return orderedFields;
    }

    public void setOrderedFields(List<Field> orderedFields) {
     
        this.orderedFields = orderedFields;
    }

    public ExcelProcessor getExcelProcessor() {
     
        return excelProcessor;
    }

    public void setExcelProcessor(ExcelProcessor excelProcessor) {
     
        this.excelProcessor = excelProcessor;
    }

    public boolean isCustomMode() {
     
        return customMode;
    }

    public void setCustomMode(boolean customMode) {
     
        this.customMode = customMode;
    }

    public List<HSSFCellStyle> getTitleStyle() {
     
        return titleStyle;
    }

    public void setTitleStyle(List<HSSFCellStyle> titleStyle) {
     
        this.titleStyle = titleStyle;
    }

    public List<HSSFCellStyle> getContentStyle() {
     
        return contentStyle;
    }

    public void setContentStyle(List<HSSFCellStyle> contentStyle) {
     
        this.contentStyle = contentStyle;
    }

    public HSSFWorkbook getHssfWorkbook() {
     
        return hssfWorkbook;
    }

    public void setHssfWorkbook(HSSFWorkbook hssfWorkbook) {
     
        this.hssfWorkbook = hssfWorkbook;
    }
}

ExcelProcessor

public interface ExcelProcessor {
     
    /**
     * 在正式注入数据之前的自定义操作,可以自己设计标题等
     *
     * @param sheet -> 当前 sheet 信息
     * @param currentSheet -> 当前 sheet
     * @return 想要正式注入表头及数据的行数
     */
    Integer customOperationBeforeInvokeData(Sheet sheet, HSSFSheet currentSheet);

    /**
     * 在注入完数据后的自定义操作,如:在表格最后落上日期、对某些数据进行修改等
     * 可以通过 currentSheet..getLastRowNum() 获取最后一行的行标,从 0 开始
     *
     * @param sheet -> 当前 sheet 信息
     * @param currentSheet -> 当前 sheet
     */
    void customOperationAfterInvokeData(Sheet sheet, HSSFSheet currentSheet, int firstRowNum);
}

StandardExcelProcessor

public class StandardExcelProcessor implements ExcelProcessor {
     
    @Override
    public Integer customOperationBeforeInvokeData(Sheet sheet, HSSFSheet currentSheet) {
     
        return 0;
    }

    @Override
    public void customOperationAfterInvokeData(Sheet sheet, HSSFSheet currentSheet, int firstRowNum) {
     
        ExcelUtil.RowWidthAutoFix(sheet, currentSheet, firstRowNum);
    }
}

ExcelUtil

public class ExcelUtil {
     

    /**
     * 获取 excel 文件创造器
     *
     * @param excelFileName -> excel 文件的名字
     * @return
     */
    public static ExcelWorkBookCreator getExcelWorkBookCreator(String excelFileName) {
     
        return new ExcelWorkBookCreator(excelFileName);
    }

    /**
     * 列宽自适应,可以在 ExcelProcessor 的实现类的后置处理中使用
     *
     * @param sheet
     * @param currentSheet
     * @param firstRowNum
     */
    public static void RowWidthAutoFix(Sheet sheet, HSSFSheet currentSheet, int firstRowNum) {
     
        int columnNum = sheet.getOrderedTitles().size();
        int columnLength = currentSheet.getLastRowNum() + 1;
        System.out.println(columnLength);
        int[] columnWidth = new int[columnNum];
        for (int index = 0; index < columnNum; index++) {
     
            columnWidth[index] = 0;
        }
        HSSFRow currentRow;
        for (int currentRowNum = firstRowNum; currentRowNum < columnLength; currentRowNum++) {
     
            currentRow = currentSheet.getRow(currentRowNum);
            HSSFCell currentCell;
            if (currentRow != null) {
     
                for (int currentColumnNum = 0; currentColumnNum < columnNum; currentColumnNum++) {
     
                    currentCell = currentRow.getCell(currentColumnNum);
                    if (currentCell != null && currentCell.getStringCellValue().getBytes().length > columnWidth[currentColumnNum]) {
     
                        columnWidth[currentColumnNum] = currentCell.getStringCellValue().getBytes().length;
                    }
                }
            }
        }
        for (int index = 0; index < columnNum; index++) {
     
            currentSheet.setColumnWidth(index, columnWidth[index] * 300);
        }
    }
}

ExcelWorkBookCreator

public class ExcelWorkBookCreator {
     
    private String excelFileName;
    private List<Sheet> sheets;
    private HSSFWorkbook hssfWorkbook;
    private final String EXCEL_SHEET_PASSWORD = "123321";

    public ExcelWorkBookCreator(String excelFileName) {
     
        this.excelFileName = excelFileName;
        hssfWorkbook = new HSSFWorkbook();
        sheets = new ArrayList<>();
    }

    public void addOneSheet(String sheetName, List<?> data, Class targetClass) {
     
        sheets.add(new Sheet(hssfWorkbook, sheetName, data, targetClass));
    }

    public void addOneSheet(String sheetName, List<?> data, Class targetClass, boolean customMode) {
     
        sheets.add(new Sheet(hssfWorkbook, sheetName, data, targetClass, customMode));
    }

    public void addOneSheet(String sheetName, List<?> data, Class targetClass, ExcelProcessor excelProcessor) {
     
        sheets.add(new Sheet(hssfWorkbook, sheetName, data, targetClass, excelProcessor));
    }

    public void addOneSheet(String sheetName, List<?> data, Class targetClass, ExcelProcessor excelProcessor, boolean customMode) {
     
        sheets.add(new Sheet(hssfWorkbook, sheetName, data, targetClass, excelProcessor, customMode));
    }


    /**
     * 导出 excel
     *
     * @param response
     * @return
     * @throws Exception
     */
    public void excelExport(HttpServletResponse response) throws Exception {
     
        //设置文件名
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode((excelFileName + ".xls"), "UTF-8"));
        OutputStream os = response.getOutputStream();
        //开始注入数据
        for (int sheetIndex = 0; sheetIndex < sheets.size(); sheetIndex++) {
     
            Sheet currentSheetMsg = sheets.get(sheetIndex);
            HSSFSheet currentSheet = hssfWorkbook.createSheet(currentSheetMsg.getSheetName());
            currentSheet.protectSheet(EXCEL_SHEET_PASSWORD);
            ExcelProcessor excelProcessor = currentSheetMsg.getExcelProcessor();
            int firstRowNum = excelProcessor.customOperationBeforeInvokeData(currentSheetMsg, currentSheet);
            if (currentSheetMsg.isCustomMode()) {
     
                invokeDataUnderCustomModel(currentSheetMsg, currentSheet, firstRowNum);
            } else {
     
                invokeData(currentSheetMsg, currentSheet, firstRowNum);
            }
            excelProcessor.customOperationAfterInvokeData(currentSheetMsg, currentSheet, firstRowNum);
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        hssfWorkbook.write(outputStream);
        outputStream.flush();
        hssfWorkbook.close();
        outputStream.close();
        InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

        int b = 0;
        byte[] buffer = new byte[512];
        while (b != -1) {
     
            b = inputStream.read(buffer);
            if (b != -1) {
     
                os.write(buffer, 0, b);
            }
        }

        if (os != null) {
     
            os.close();
            os.flush();
        }
    }

    /**
     * 不开启自定义文本模式下注入正文
     *
     * @param currentSheet
     * @param hssfSheet
     * @param firstRowNum
     * @throws Exception
     */
    private void invokeData(Sheet currentSheet, HSSFSheet hssfSheet, int firstRowNum) throws Exception {
     
        //设置表头
        HSSFRow firstRow = hssfSheet.createRow(firstRowNum);
        HSSFCellStyle cellStyle = hssfWorkbook.createCellStyle();
        Font titleFont = hssfWorkbook.createFont();
        //加粗标题字体
        titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        cellStyle.setFont(titleFont);
        cellStyle.setLocked(true);
        HSSFCell titleCell;
        for (int titleIndex = 0; titleIndex < currentSheet.getOrderedTitles().size(); titleIndex++) {
     
            titleCell = firstRow.createCell(titleIndex);
            titleCell.setCellValue(currentSheet.getOrderedTitles().get(titleIndex));
            titleCell.setCellStyle(cellStyle);
        }
        //注入数据
        List<?> currentData = currentSheet.getData();
        List<Field> fields = currentSheet.getOrderedFields();
        cellStyle = hssfWorkbook.createCellStyle();
        cellStyle.setLocked(true);
        HSSFRow currentRow;
        for (int rowIndex = 0; rowIndex < currentData.size(); rowIndex++) {
     
            currentRow = hssfSheet.createRow(rowIndex + firstRowNum + 1);
            HSSFCell currentCell;
            Object obj = currentData.get(rowIndex);
            for (int cellIndex = 0; cellIndex < fields.size(); cellIndex++) {
     
                currentCell = currentRow.createCell(cellIndex);
                currentCell.setCellStyle(cellStyle);
                if (!fields.get(cellIndex).isAccessible()) {
     
                    fields.get(cellIndex).setAccessible(true);
                    if (fields.get(cellIndex).get(obj) != null) {
     
                        currentCell.setCellValue(fields.get(cellIndex).get(obj).toString());
                    }
                    fields.get(cellIndex).setAccessible(false);
                } else {
     
                    if (fields.get(cellIndex).get(obj) != null) {
     
                        currentCell.setCellValue(fields.get(cellIndex).get(obj).toString());
                    }
                }
            }
        }
    }

    /**
     * 开启自定义文本模式下注入正文
     *
     * @param currentSheet
     * @param hssfSheet
     * @param firstRowNum
     * @throws Exception
     */
    private void invokeDataUnderCustomModel(Sheet currentSheet, HSSFSheet hssfSheet, int firstRowNum) throws Exception {
     
        //设置表头
        HSSFRow firstRow = hssfSheet.createRow(firstRowNum);
        currentSheet.titleCellStyleInvoke(firstRow);
        //注入数据
        currentSheet.contentCellStyleInvoke(hssfSheet, firstRowNum);
    }

    public String getExcelFileName() {
     
        return excelFileName;
    }

    public void setExcelFileName(String excelFileName) {
     
        this.excelFileName = excelFileName;
    }

    public List<Sheet> getSheets() {
     
        return sheets;
    }

    public void setSheets(List<Sheet> sheets) {
     
        this.sheets = sheets;
    }
}

测试

@Controller
@RequestMapping("/test")
public class TestController {
     

    @ResponseBody
    @RequestMapping(value = "/getExcel", method = RequestMethod.GET)
    public String getExcel(HttpServletResponse response){
     
        try {
     
            List<Student> students = new ArrayList<>();
            this.injectData(students);
            ExcelWorkBookCreator creator = ExcelUtil.getExcelWorkBookCreator("学生信息汇总");
            creator.addOneSheet("学生信息", students, Student.class);
            creator.excelExport(response);
            return "success";
        } catch (Exception e) {
     
            e.printStackTrace();
            return "error";
        }
    }

    private void injectData(List<Student> students){
     
        students.add(new Student("1", "张三", "xx1小区", "男"));
        students.add(new Student("2", "李四", "xx2小区", "男"));
        students.add(new Student("3", "王五", "xx3小区", "女"));
        students.add(new Student("4", "小明", "xx4小区", "男"));
        students.add(new Student("5", "小红", "xx5小区", "女"));
    }

    class Student{
     
        @ExcelColumn(order = 1, description = "学号")
        private String id;
        @ExcelColumn(order = 2, description = "姓名")
        private String name;
        @ExcelColumn(order = 4, description = "住址")
        private String address;
        @ExcelColumn(order = 3, description = "性别")
        private String sex;

        public Student() {
     
        }

        public Student(String id, String name, String address, String sex) {
     
            this.id = id;
            this.name = name;
            this.address = address;
            this.sex = sex;
        }

        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 String getAddress() {
     
            return address;
        }

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

        public String getSex() {
     
            return sex;
        }

        public void setSex(String sex) {
     
            this.sex = sex;
        }
    }
}

Spring通过poi简单封装excel导出的工具类_第3张图片

码云

poi简单封装excel导出的工具类

你可能感兴趣的:(java,excel,poi,spring,spring,boot)