【每日一点】1. Java如何实现导出Excel单表头或多表头

栏目: Java · 发布时间: 6年前

内容简介:在后台项目中,经常会遇到将呈现的内容导出到Excel的需求,通过都是导出单个表头的Excel文件,如果存在级联关系的情况下,也就需要导出多表头的场景。今天这篇文章就是分享导出Excel单表头或多表头的实现,目前实现方案仅支持2行表头场景。如有更复杂的3行表头、4行表头复杂需求可以自行实现。1. 借助POI包实现表头的写入。每个表头其实就是一行,如果是多个表头,无非就是将写多行表头,然后将需要合并的表头进行合并,借助POI的函数为addMergedRegion。2. 将导出数据进行转化为一个集合,循环写入每

一、背景

在后台项目中,经常会遇到将呈现的内容导出到Excel的需求,通过都是导出单个表头的Excel文件,如果存在级联关系的情况下,也就需要导出多表头的场景。今天这篇文章就是分享导出Excel单表头或多表头的实现,目前实现方案仅支持2行表头场景。如有更复杂的3行表头、4行表头复杂需求可以自行实现。

二、实现思路

1. 借助POI包实现表头的写入。每个表头其实就是一行,如果是多个表头,无非就是将写多行表头,然后将需要合并的表头进行合并,借助POI的函数为addMergedRegion。

2. 将导出数据进行转化为一个集合,循环写入每行数据。

三、实现代码

3.1 pom引入


<properties>
        <java.version>1.8</java.version>
        <poi.version>3.17</poi.version>
        <mybatis.version>1.3.2</mybatis.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
    </dependencies>

View Code

3.2 Java代码实现

@Getter
@Setter
public class ExcelHelper<T> {
    /**
     * 表格标题
     */
    private String title;

    /**
     * 单元格宽度
     */
    private int colWidth = 20;

    /**
     * 行高度
     */
    private int rowHeight = 20;

    private HSSFWorkbook workbook;

    /**
     * 表头样式
     */
    private HSSFCellStyle headStyle;

    /**
     * 主体样式
     */
    private HSSFCellStyle bodyStyle;

    /**
     * 日期格式化,默认yyyy-MM-dd HH:mm:ss
     */
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * Constructor
     * @param title
     */
    public ExcelHelper(String title){
        this.title = title;
        workbook = new HSSFWorkbook();
        init();
    }
    /**
     * Constructor
     * @param title
     * @param colWidth
     * @param rowHeight
     */
    public ExcelHelper(String title, int colWidth, int rowHeight){
        this.colWidth = colWidth;
        this.rowHeight = rowHeight;
        this.title = title;
        workbook = new HSSFWorkbook();
        init();
    }

    /**
     * Constructor
     * @param title
     * @param colWidth
     * @param rowHeight
     * @param dateFormat
     */
    public ExcelHelper(String title, int colWidth, int rowHeight, String dateFormat) {
        this.title = title;
        this.colWidth = colWidth;
        this.rowHeight = rowHeight;
        workbook = new HSSFWorkbook();
        sdf = new SimpleDateFormat(dateFormat);
        init();
    }

    /**
     * 导出Excel,适用于web导出excel
     *
     * @param sheet
     * @param data
     */
    private void writeSheet(HSSFSheet sheet, List<T> data,List<Column> headerList) {
        try {
            sheet.setDefaultColumnWidth(colWidth);
            sheet.setDefaultRowHeightInPoints(rowHeight);
            createHead(headerList, sheet);
            writeSheetContent(headerList, data, sheet);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 导出表格
     * @param listColumn
     * @param datas
     * @return
     * @throws Exception
     */
    public InputStream exportExcel(List<Column> listColumn,List<T> datas) throws Exception {
        splitDataToSheets(datas,listColumn);
        return save(workbook);
    }

    /**
     * 导出表格 支持2级表头或单表头的Excel导出
     * @param headers
     * @param datas
     * @param filePath
     * @throws FileNotFoundException
     * @throws IOException
     * void
     */
    public void exportExcel(List<Column> headers,List<T> datas,String filePath) throws IOException {
        splitDataToSheets(datas, headers);
        save(workbook, filePath);
    }

    /**
     * 把数据写入到单元格
     * @param listColumn
     * @param datas
     * @param sheet
     * @throws Exception
     * void
     */
    private void writeSheetContent(List<Column> listColumn,List<T> datas,HSSFSheet sheet) throws Exception {
        HSSFRow row;
        List<Column> listCol = getColumnList(listColumn);
        for (int i = 0, index = 2; i < datas.size(); i++, index++) {
            // 创建行
            row = sheet.createRow(index);
            for (int j = 0; j < listCol.size(); j++) {
                Column c = listCol.get(j);
                createCol(row, c, datas.get(i), j);
            }
        }
    }

    /**
     * 创建表头
     * @param listColumn 表头数组
     * @return 返回表头总行数
     */
    public void createHead(List<Column> listColumn, HSSFSheet sheetCo){
        HSSFRow row = sheetCo.createRow(0);
        HSSFRow row2 = sheetCo.createRow(1);
        for(short i = 0, n = 0; i < listColumn.size(); i++){
            HSSFCell cell1 = row.createCell(n);
            cell1.setCellStyle(headStyle);
            HSSFRichTextString text;
            List<Column> columns = listColumn.get(i).getListColumn();
            //双标题
            if(CollectionUtils.isEmpty(columns)){
                // 单标题
                HSSFCell cell2 = row2.createCell(n);
                cell2.setCellStyle(headStyle);
                text = new HSSFRichTextString(listColumn.get(i).getContent());
                sheetCo.addMergedRegion(new CellRangeAddress(0, n, 1, n));
                n++;
                cell1.setCellValue(text);
                continue;
            }

            text = new HSSFRichTextString(listColumn.get(i).getContent());
            cell1.setCellValue(text);

            // 创建第一行大标题
            sheetCo.addMergedRegion(new CellRangeAddress(0, 0, n, (short) (n + columns.size() -1)));
            // 给标题赋值
            for(int j = 0; j < columns.size(); j++){
                HSSFCell cell2 = row2.createCell(n++);
                cell2.setCellStyle(headStyle);
                cell2.setCellValue(new HSSFRichTextString(columns.get(j).getContent()));
            }
        }
    }

    /**
     * 创建行
     * @param row
     * @param column
     * @param v
     * @param rowIndex
     * @return
     * @throws Exception
     */
    public int createRowVal(HSSFRow row, Column column,T v,int rowIndex) throws Exception{
        // 遍历标题
        if(column.getListColumn() != null && column.getListColumn().size() > 0){
            for(int i = 0; i < column.getListColumn().size(); i++){
                createRowVal(row,column.getListColumn().get(i),v,rowIndex);
            }
        }else{
            createCol(row,column,v,rowIndex++);
        }

        return rowIndex;
    }

    /**
     * 创建单元格
     * @param row
     * @param column
     * @param v
     * @param columnIndex
     * @throws Exception
     */
    public void createCol(HSSFRow row,Column column,T v,int columnIndex) throws Exception{
        // 创建单元格
        HSSFCell cell = row.createCell(columnIndex);
        // 设置单元格样式
        cell.setCellStyle(bodyStyle);
        Class cls = v.getClass();
        Field field = cls.getDeclaredField(column.getFieldName());
        // 设置些属性是可以访问的
        field.setAccessible(true);
        if(field.get(v) != null){
            Object value = field.get(v);
            if(value instanceof Date){
                value = parseDate((Date)value);
            }

            HSSFRichTextString richString = new HSSFRichTextString(value.toString());
            cell.setCellValue(richString);
        }
    }

    /**
     * init
     */
    private void init(){
        // 生成表头样式
        headStyle = workbook.createCellStyle();
        headStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.AQUA.getIndex());
        headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        headStyle.setBorderBottom(BorderStyle.THIN);
        headStyle.setBorderLeft(BorderStyle.THIN);
        headStyle.setBorderRight(BorderStyle.THIN);
        headStyle.setBorderTop(BorderStyle.THIN);
        headStyle.setAlignment(HorizontalAlignment.CENTER);
        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 生成一个字体
        HSSFFont headFont = workbook.createFont();
        headFont.setColor(HSSFColor.HSSFColorPredefined.VIOLET.getIndex());
        headFont.setFontHeightInPoints((short) 12);
        headFont.setBold(true);
        // 把字体应用到当前的样式
        headStyle.setFont(headFont);

        // 生成并设置另一个样式
        bodyStyle = workbook.createCellStyle();
        bodyStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        bodyStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        bodyStyle.setBorderBottom(BorderStyle.THIN);
        bodyStyle.setBorderLeft(BorderStyle.THIN);
        bodyStyle.setBorderRight(BorderStyle.THIN);
        bodyStyle.setBorderTop(BorderStyle.THIN);
        bodyStyle.setAlignment(HorizontalAlignment.CENTER);
        bodyStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        // 生成另一个字体
        HSSFFont bodyFont = workbook.createFont();
        bodyFont.setBold(false);
        // 把字体应用到当前的样式
        bodyStyle.setFont(bodyFont);
    }

    /**
     * 时间转换
     * @param date
     * @return
     * String
     */
    private  String parseDate(Date date){
        String dateStr = "";
        try{
            dateStr = sdf.format(date);
        } catch (Exception e){
            e.printStackTrace();
        }

        return dateStr;
    }

    /**
     * 拆分sheet,因为每个sheet不能超过6526,否则会报异常
     * @param data
     * @param listColumn
     * void
     */
    private void splitDataToSheets(List<T> data,List<Column> listColumn) {
        int dataCount = data.size();
        int maxColumn = 65535;
        int pieces = dataCount / maxColumn;
        for (int i = 1; i <= pieces; i++) {
            HSSFSheet sheet = workbook.createSheet(this.title + i);
            List<T> subList = data.subList((i - 1) * maxColumn, i * maxColumn);
            writeSheet(sheet, subList, listColumn);
        }

        HSSFSheet sheet = workbook.createSheet(this.title + (pieces + 1));
        writeSheet(sheet, data.subList(pieces * maxColumn, dataCount), listColumn);
    }

    /**
     * 把column的columnList整理成一个list<column>
     * @param listColumn
     * @return
     * List<Column>
     */
    private List<Column> getColumnList(List<Column> listColumn){
        List<Column> listCol = new ArrayList<>();
        for(int i = 0; i < listColumn.size(); i++){
            List<Column> list = listColumn.get(i).getListColumn();
            if(list.size() > 0){
                for(Column c : list){
                    if(c.getFieldName() != null){
                        listCol.add(c);
                    }
                }
            }else{
                if(listColumn.get(i).getFieldName() != null){
                    listCol.add(listColumn.get(i));
                }
            }
        }

        return listCol;
    }

    /**
     * 保存Excel到InputStream,此方法适合web导出excel
     *
     * @param workbook
     * @return
     */
    private InputStream save(HSSFWorkbook workbook) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            workbook.write(bos);
            InputStream bis = new ByteArrayInputStream(bos.toByteArray());
            return bis;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 保存文件
     * @param workbook
     * @param filePath
     * @throws IOException
     */
    private void save(HSSFWorkbook workbook,String filePath) throws IOException {
        workbook.write(new FileOutputStream(filePath));
    }

四、测试类


public class ExportTest {
    @Data
    @AllArgsConstructor
    public class ValueObj {
        private String value1;

        private String value2;
    }
    public static void main(String[] args) throws Exception {

        //用于存放第一行单元格
        List<Column> listColumn = new ArrayList<>();
        // 用于存放第一列第二行的单元格
        List<Column> list2 = new ArrayList<>();
        // 创建一列,value1 表示这一列需要导出字段的值
        list2.add(new Column("标题1","value1"));
        list2.add(new Column("标题2","value1"));
        list2.add(new Column("标题3","value1"));

        // 用于存放第二列第二行的单元格
        List<Column> list3  = new ArrayList<>();
        list3.add(new Column("标题6","value2"));
        list3.add(new Column("标题7","value2"));


        //创建第一行大标题,大标题的fieldName 为 null
        Column c1 = new Column("标题1",null);
        c1.setListColumn(list2);
        Column c2 = new Column("标题2",null);
        c2.setListColumn(list3);
        listColumn.add(c1);
        listColumn.add(c2);

        //需要导出的数据
        List<ValueObj> valueList = new ArrayList<>();
        valueList.add(new ValueObj("1","11"));
        valueList.add(new ValueObj("2","22"));
        valueList.add(new ValueObj("3","33"));
        valueList.add(new ValueObj("4","44"));

        ExcelHelper<ValueObj> ta = new ExcelHelper<ValueObj>("表格",15,20);
        ta.exportExcel(listColumn, valueList,"D:\\outExcel.xls");
    }
}

View Code

五、实现效果

【每日一点】1. Java如何实现导出Excel单表头或多表头


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

CSS3 Solutions

CSS3 Solutions

Marco Casario / Apress / 2012-8-13 / GBP 35.50

CSS3 brings a mass of changes, additions, and improvements to CSS across a range of new modules. Web designers and developers now have a whole host of new techniques up their sleeves, from working wit......一起来看看 《CSS3 Solutions》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具