POI导出工具类,可导出模板,也可导出数据.

本文介绍了一个基于Apache POI库的Java工具类,该类支持根据模板导出Excel文件,同时也能够直接导出数据到Excel。通过这个工具,开发者可以方便地在项目中实现灵活的Excel数据导出功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.example.demo.exportExcel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * Copyright © 2018 Shanghai 
 *
 * @Description Excel 导入工具辅助类
 * @Author zhaoweijiang
 * @Date 2019/3/29 11:11
 *
 * Excel_2003 支持最大导出65536行
 * Excel_2007 支持最大导出1048576行
 * 详情查看SpreadsheetVersion.class
 *
 */
public class ExportExcelUtil {

    //注释换行符
    public static final String NEWLINE = "\r\n";
    //工作簿
    private Workbook wb;
    //工作表
    private Sheet sheet;
    //样式
    private CellStyle cellStyle;
    //工作簿类型 .xls/.xlsx
    private String extension;
    /**
     * 默认模板工作表名称
     */
    private String sheetName = "";

    /*
     * 默认模板名称字体大小为36
     */
    private int typeFontSize = 36;
    /*
     * 默认模板注释字体大小为11
     */
    private int annotationFontSize = 11;
    /*
     * 默认模板标题字体大小为11
     */
    private int titleFontSize = 11;
    /*
     * 默认模板示例字体大小为11
     */
    private int exampleFontSize = 11;

    /**
     * 对外提供set方法,可修改默认字体大小
     */
    public void setSize(int typeFontSize) {
        this.typeFontSize = typeFontSize;
    }

    public void setAnnotationFontSize(int annotationFontSize) {
        this.annotationFontSize = annotationFontSize;
    }

    public void setTitleFontSize(int titleFontSize) {
        this.titleFontSize = titleFontSize;
    }

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

    /**
     * 构造函数初始化
     * ExcelTypeTl 自定义的一个枚举类,该枚举类是工作簿格式 .xls/.xlsx
     */
    public ExportExcelUtil(ExcelTypeTl excelTypeTl){

        String type = excelTypeTl.getType();

        if (".xls".equals(type)){
            this.wb = new HSSFWorkbook();
        }else if (".xlsx".equals(type)){
            this.wb = new XSSFWorkbook();
        }else {
            throw new IllegalArgumentException("Illegal parameter type");
        }
        //传递给私有属性,下面的其他方法还需要
        this.extension = type;
    }

    /**
     * 创建工作表
     * 创建样式
     * 注:表名称不可用特殊符号
     */
    private void createSheet(){
        this.sheet = wb.createSheet(this.sheetName.length() > 0 ? sheetName : "sheet1");
        this.cellStyle = wb.createCellStyle();

    }

    /**
     * 说明: excel的字体大小 * 20 = 设置值  例; excel 字体是 13 * 20 = 260
     *  你需要设置字体大小为260.导出的excel才会是13的字体大小 ,,,同行高,具体源码里有
     *
     * row.setHeight( (short)( 20 * Math.round( (this.typeFontSize/0.69) ) )); //设置行高
     * 我设置的行高,根据字体大小自己调试的我认为最佳行高
     *
     * 创建Excel模板名称   / 第一行
     * @param titleLenght 标题长度
     * @param description 模板名称 同工作簿名称
     */
    private void createTlType(int titleLenght , String description){

        CellRangeAddress region = new CellRangeAddress(0, 0, 0, titleLenght - 1);
        sheet.addMergedRegion(region); //设置第一行合并单元格
        CellStyle style = wb.createCellStyle(); //创建单元格样式
        Font font = wb.createFont(); //创建字体
        font.setFontHeight( (short)(this.typeFontSize * 20) ); //字体大小

        style.setFont(font);
        style.setVerticalAlignment(VerticalAlignment.CENTER); //单元格内容居中
        style.setAlignment(HorizontalAlignment.CENTER); //单元格左右居中
        style.setFillForegroundColor(IndexedColors.ROSE.getIndex()); //LIGHT_GREEN色
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND); //全部填充


        Row row = sheet.createRow(0); //创建第一行
        row.setHeight( (short)( 20 * Math.round( (this.typeFontSize/0.69) ) )); //设置行高
        Cell cell = row.createCell(0); //创建第一个单元格
        cell.setCellValue(description); //给单元格加载数据
        cell.setCellStyle(style); //设置单元格样式
    }

    /**
     * 创建Excel模板注释   /  第二行
     * @param titleLenght 标题长度
     * @param list 注释文本
     */
    private void createTlAnnotation(int titleLenght , ArrayList<String> list){
        CellRangeAddress region = new CellRangeAddress(1, 1, 0, titleLenght - 1);
        sheet.addMergedRegion(region); //设置第二行合并单元格

        CellStyle style = wb.createCellStyle();
        Font font = wb.createFont();
        font.setFontHeight( (short)(this.annotationFontSize * 20) ); //字体大小

        style.setFont(font);
        style.setAlignment(HorizontalAlignment.LEFT);//文字居左
        style.setVerticalAlignment(VerticalAlignment.CENTER); //单元格内容居中
        style.setFillForegroundColor(IndexedColors.ORANGE.getIndex()); //ORANGE色
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND); //全部填充
        style.setWrapText(true);//自动换行

        Row row = sheet.createRow(1);
        Cell cell = row.createCell(0);

        int lenght = list.size(); //数据长度
        String data = null;

        if (lenght > 0){
            row.setHeight((short) ( 20 * Math.round((list.size() * this.annotationFontSize)/0.69))); //行高随着字体的行数和大小自动适配
             data = list.get(0);
            for (int i = 1 ; i < lenght ; i++){

                data += NEWLINE + list.get(i);
            }
        }else{
            row.setHeight((short) ( 20 * Math.round((3 * this.annotationFontSize)/0.69))); // 默认适配3行字体大小行高
        }
        cell.setCellValue(data);
        cell.setCellStyle(style);
    }

    /**
     * 创建Excel模板标题   /  第三行
     * @param title 标题数据
     */
    private void createTitle(String[] title ){
        /*
         *前三列样式
         */
        //设置字体
        Font font1 = wb.createFont();
        //加粗
        font1.setBold(true);
        //字体大小
        font1.setFontHeight((short) (this.titleFontSize * 20));
        //字体颜色
        font1.setColor(IndexedColors.RED.getIndex());
        //设置样式
        CellStyle style1 = wb.createCellStyle();
        //左右居中
        style1.setAlignment(HorizontalAlignment.CENTER);
        //单元格居中
        style1.setVerticalAlignment(VerticalAlignment.CENTER);
        style1.setFont(font1);

        /*
         * 后边的列 样式
         */
        //设置字体
        Font font = wb.createFont();
        //加粗
        font.setBold(true);
        //字体大小
        font.setFontHeight((short) (this.titleFontSize * 20));
        //设置样式
        CellStyle style = wb.createCellStyle();
        //居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //单元格居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFont(font);


        /*
         * 全局设置
         * 所有有数据的列单元格为文本格式
         */
        CellStyle contextStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        //文本格式
        contextStyle.setDataFormat(format.getFormat("@"));


        //创建唯一表头行,默认为第一行
        Row row = sheet.createRow(2);
        //行高
        row.setHeight((short) ( 20 * Math.round( this.titleFontSize / 0.69) ));
        for (int i = 0; i < title.length; i++) {

            //全局列宽
            sheet.setColumnWidth(i, 256 * 20 + 185);
            //加载全局列样式
            sheet.setDefaultColumnStyle(i, contextStyle);


            //创建单元格
            Cell cell = row.createCell(i);
            //单元格值
            cell.setCellValue(title[i]);

            //单元格加载样式
            cell.setCellStyle(i < 3 ? style1 : style);

        }
    }

    /**
     * 创建Excel模板示例数据   /  第四行
     * @param example  示例数据
     */
    private void createExample(String[] example ){

        //全局变量
        // 该行高未*20,因为源码已经帮我们做了这个动作
        sheet.setDefaultRowHeightInPoints((short)( this.exampleFontSize / 0.69 ));
        
        Row row = sheet.createRow(3);
        CellStyle style = wb.createCellStyle();
        //设置字体
        Font font = wb.createFont();
        //字体大小
        font.setFontHeight((short) (this.exampleFontSize  * 20));

        style.setFont(font);
        style.setDataFormat((short) 49 );

        //当前行高
        row.setHeight((short) ( 20 * Math.round( this.exampleFontSize /0.69 ) ));
        for (int i = 0; i < example.length; i++) {
            Cell cell = row.createCell(i);
            cell.setCellValue(example[i]);
            cell.setCellStyle(style);
        }
    }


    /**
     * 创建Excel模板导入数据   /  第五行
     * @param listData 数据
     */
    private void createData(List<Object> listData) {



        for (int i = 0; i < listData.size(); i++) {
            //从第四行开始插入数据
            Row row = this.sheet.createRow(i + 3);
            //获取集合对象
            Object o = listData.get(i);

            //反射获取字段
            Field[] fields = o.getClass().getDeclaredFields();

            for (int j = 0; j < fields.length; j++) {

                Field field = fields[j];
                //暴力访问/取消检查机制
                field.setAccessible(true);
                String data = null;
                try {
                    data = (String)field.get(o);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                Cell cell = row.createCell(j);
                cell.setCellValue(data);
                this.cellStyle.setDataFormat((short) 49);  //文本格式
                cell.setCellStyle(cellStyle);

            }
        }
    }

    /**
     * 导出excel模板
     * @param response  响应
     * @param bookName  工作簿名称
     * @param annotations 注释
     * @param title 标题
     * @param example 示例
     * @throws IOException
     */
    public void exportFileTemplate(HttpServletResponse response , String bookName , ArrayList<String> annotations,
                                   String[] title ,String[] example ) throws IOException {

        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment;fileName=" +
                new String(bookName.getBytes(StandardCharsets.UTF_8), "ISO8859-1") + extension);

        if (title == null || title.length == 0  || title.length != example.length){
            throw new IllegalArgumentException("the title&example of Unequal length");
        }

        //1,创建表
        createSheet();

        //2,创建第一行模板名称
        createTlType(title.length , bookName);

        //3,创建第二行模版注释
        createTlAnnotation(title.length , annotations);

        //4,创建第三行模板标题
        createTitle(title);

        //5,创建第四行模板示例数据
        createExample(example);


        ServletOutputStream out = response.getOutputStream();

        wb.write(out);

        out.flush();
        out.close();
        wb.close();

    }
    /**
     * 导出excel文本数据
     * @param response  响应
     * @param bookName  工作簿名称
     * @param annotations 注释
     * @param title 标题
     * @param arrayList 导出数据   可传空集合
     * @throws IOException
     */
    public void exportFile(HttpServletResponse response , String bookName , ArrayList<String> annotations,
                           String[] title ,ArrayList<Object> arrayList) throws IOException {

        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment;fileName=" +
                new String(bookName.getBytes(StandardCharsets.UTF_8), "ISO8859-1") + extension);

        if (title == null || title.length == 0 ){
            throw new IllegalArgumentException("the title & arrayList of Unequal length");

        }

        if ( extension == ExcelTypeTl.EXCEL_2003.getType() && arrayList.size() >= 65536){
            throw new IllegalArgumentException("Invalid row number (" + arrayList.size() + ") outside allowable range (0.." + 65536 + ")");
        }else if (extension == ExcelTypeTl.EXCEL_2007.getType() && arrayList.size() >= 1048576 ){
            throw new IllegalArgumentException("Invalid row number (" + arrayList.size() + ") outside allowable range (0.." + 1048576 + ")");
        }

        //1,创建表
        createSheet();

        //2,创建第一行模板名称
        createTlType(title.length , bookName);

        //3,创建第二行模版注释
        createTlAnnotation(title.length , annotations);

        //4,创建第三行模板标题
        createTitle(title);

        //5,创建第四行模板数据导入
        createData(arrayList);


        ServletOutputStream out = response.getOutputStream();

        wb.write(out);

        out.flush();
        out.close();
        wb.close();
    }

}



package com.example.demo.exportExcel;

/**
 * Copyright © 2018 Shanghai \
 *
 * @Description ExcelTemplateConstant  excel工作簿 模板名称/标题/标题示例/注释 模板
 * @Author zhaoweijiang
 * @Date 2019/3/2710:53
 *
 */
public final class ExcelTlCon{


    //工资单导入模板
    public static final String PAYROLL_TL= "工资单导入模板";

    // first bill 标题
    public static final String[] HFW_FIRST_BILL_TITLE = {"身份证号(必填)", "用户姓名(必填)", "发薪主体(必填)", "操作金额", "资金类型(发薪)", "发薪年份", "发薪月份", "描述"};

     // first bill 示例数据
    public static final String[] HFW_FIRST_BILL_DATA = {"342422199209272334","小黄鸭", "上海银行", "6666.00", "发薪", "2019", "07", "2019年07月工资"};

    //注释1
    public static final String ANNOTATION_ONE = "1.所有数据均为文本格式。";

    //注释2
    public static final String ANNOTATION_TWO = "2.请不要在未有标题的列存放数据。";

    //注释3
    public static final String ANNOTATION_THREE = "3.请你一定要爱我。";


}


package com.example.demo.exportExcel;

/**
 * Copyright © 2018 Shanghai 
 *
 * @Description  excel模板类型 / 枚举类
 * @Author zhaoweijiang
 * @Date 2019/3/2713:44
 */
public enum ExcelTypeTl {

    //2003版本后缀名
    EXCEL_2003(2003,".xls"),

    //2007版本后缀名
    EXCEL_2007(2007,".xlsx");

    private final int code;

    private final String type;

    ExcelTypeTl(int code, String type) {
        this.code = code;
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public int getCode() {
        return code;
    }


    public static String fromInt(int code) {
        if (code < 0){
            throw new IllegalArgumentException("Illegal ExcelTypeTl code: " + code);
        }

        String var0 = null;
        ExcelTypeTl[] values = values();
        for (ExcelTypeTl excelTypeTl : values){

            if (excelTypeTl.code == code){
                return excelTypeTl.getType();
            }
        }

        if (var0 == null){
            throw new IllegalArgumentException("Illegal ExcelTypeTl code: " + code);
        }

        return var0;
    }
}




这是我严格意义上第一次接触POI,当我第一次去做这个东西的时候,首先去http://POI.apache.org官网看了半天的demo,按照demo教程敲了一遍.第二天写了一个简单的工具类,应该说是第一个版本的,只有3个方法,创建工作簿和表,创建行,和创建行数据.极其的简漏.自己都觉得很不好看.随后对源码进行了多次的查看,写成现在的样子,可能你会觉得很low,没关系,做个借鉴.其中遇到几个小问题源码也没怎么看懂
1, row.setRowStyle(style); 把样式传进去并没有得到修改,问了一位大佬,建议我查看源码,最终没有去看.
2, 当我去设置所创建的列全局单元格为文本格式的时候.如果导出的是空工作簿,你在往里面填数据的时候就是文本格式,但是当你设置好之后,在没有导出工作簿前,往单元格里放数据他会修改单元格文本为常规.也就是说如果你要往单元格放数据的时候,最好放一个数据设置一个样式.提供的代码就是这样玩的.
3,背景颜色可能比较单一,可以参考https://blog.youkuaiyun.com/ruanhao1203/article/details/39553915
4,有疑问可以留言呗!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值