利用easyexcel生成excel文件-复杂表头/多表头/自定义表头设计

摘要: 在上一篇文章( http://www.yihaomen.com/article/1850.html ) 测试了easyexcel生成简单的EXCEL文件,继续测试利用easyexcel生成复杂表头,或者自定义表头的设计。既然是多表头,复杂的自定义表头设计,原来利用注解来实现单元格的宽度,样式等都不能用了,这个时候需要自定义指定参数,测试还是用上一篇文章提到的订单来做

在上一篇文章( http://www.yihaomen.com/article/1850.html ) 测试了easyexcel生成简单的EXCEL文件,继续测试利用easyexcel生成复杂表头,或者自定义表头的设计。

既然是多表头,复杂的自定义表头设计,原来利用注解来实现单元格的宽度,样式等都不能用了,这个时候需要自定义指定参数,测试还是用上一篇文章提到的订单来做,最终实现的效果如下:

先上代码,然后在稍稍解释一下:

package com.yihaomen.myexcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.yihaomen.myexcel.domain.Detail;
import com.yihaomen.myexcel.domain.Master;
import org.apache.poi.ss.usermodel.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import sun.security.x509.CertAttrSet;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@SpringBootTest
public class WriteExcel_1 {
    private Master master;
    private List<Detail> details = new ArrayList<>();

    /**
     * 初始化测试数据
     */
    @Before
    public void initData() {
        master = new Master();
        master.setCustomer("特朗普集团");
        master.setSheetNo("SO2020000011111");
        master.setCreatedDate(new Date());

        for(int i=0; i<100; i++) {
            Detail d = new Detail();
            d.setProductId("product:" + i);
            d.setProductName("产品:" + i);
            d.setPrice(new BigDecimal("26.80"));
            d.setNumber(new BigDecimal("20.5"));
            d.setAmount(d.getPrice().multiply(d.getNumber()));
            d.setMemo("备注产品:" + i);
            details.add(d);
        }
    }

    /**
     * 仅仅输出明细数据到excel文件
     */
    @Test
    public void writeSimpleExcelForDetail() {
        String path = this.getClass().getResource("/").getPath();
        System.out.println(path);
        String fileName = path + File.separator + "writeSimpleExcel.xlsx";
        // 这里 需要指定写用哪个class去写,指定模板名称及数据
        EasyExcel.write(fileName, Detail.class).sheet("sheet名称").doWrite(details);
    }

    /**
     * 仅仅输出明细数据到excel文件, 排除部分字段
     */
    @Test
    public void writeSimpleExcelExculdeColumns() {
        String path = this.getClass().getResource("/").getPath();
        List<String> excludeColumns = new ArrayList<>();
        excludeColumns.add("memo");
        String fileName = path + File.separator + "writeSimpleExcel.xlsx";
        // 这里 需要指定写用哪个class去写,指定模板名称及数据
        EasyExcel.write(fileName, Detail.class).excludeColumnFiledNames(excludeColumns).sheet("sheet名称").doWrite(details);
    }

    /**
     * 仅仅输出明细数据到excel文件, 增加自定义的头部
     */
    @Test
    public void writeSimpleExcelWithHeader() {
        String path = this.getClass().getResource("/").getPath();
        String fileName = path + File.separator + "writeSimpleExcel.xlsx";
        // 准备 HEADER
        List<List<String>> list = getHeader();
        // 这里 需要指定写用哪个class去写,指定模板名称及数据
        EasyExcel.write(fileName).head(list).registerWriteHandler(new CustomizeColumnWidth())
                .registerWriteHandler(getStyleStrategy()).sheet("sheet名称").doWrite(details);
    }

    private List<List<String>> getHeader() {
        /**
         * 打算展示成如下样子
         * |客户:xxx 公司 (这一行需要合并单元格)
         * |单号: SO22222222222222|  日期: 2020-01-01 (分别需要合并单元格)
         * |产品ID|产品名称|价格|数量|总金额|备注|
         */
        String customer = "客户: " + master.getCustomer();
        String sheetNo = "单号: " + master.getSheetNo();
        String dateStr = "日期: " + master.getCreatedDate();
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        head0.add(customer);
        head0.add(sheetNo);
        head0.add("产品ID");
        List<String> head1 = new ArrayList<String>();
        head1.add(customer);
        head1.add(sheetNo);
        head1.add("产品名称");
        List<String> head2 = new ArrayList<String>();
        head2.add(customer);
        head2.add(sheetNo);
        head2.add("价格");

        List<String> head3 = new ArrayList<String>();
        head3.add(customer);
        head3.add(sheetNo);
        head3.add("数量");

        List<String> head4 = new ArrayList<String>();
        head4.add(customer);
        head4.add(dateStr);
        head4.add("总金额");

        List<String> head5 = new ArrayList<String>();
        head5.add(customer);
        head5.add(dateStr);
        head5.add("备注");

        list.add(head0);
        list.add(head1);
        list.add(head2);
        list.add(head3);
        list.add(head4);
        list.add(head5);
        return list;
    }

    private HorizontalCellStyleStrategy getStyleStrategy() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 设置对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        // 背景色, 设置为白色,也是默认颜色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        // 字体
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 12);
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        // contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);

        // 背景绿色
        //contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 12);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //设置 自动换行
        contentWriteCellStyle.setWrapped(true);
        //设置 垂直居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置 水平居中
        // contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //设置边框样式
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        return horizontalCellStyleStrategy;
    }

    /**
     * 自定义头部的 列的宽度设置 策略. .
     */
    class CustomizeColumnWidth extends AbstractColumnWidthStyleStrategy {
        @Override
        protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean isHead) {
            // 测试为 COLUMN 宽度定制.
            if (isHead && cell.getRowIndex() == 2) {
                int columnWidth = cell.getStringCellValue().getBytes().length;
                int cellIndex = cell.getColumnIndex();
                switch (cellIndex) {
                    case 0:
                    case 2:
                    case 3:
                        columnWidth = 10;
                        break;
                    case 1:
                        columnWidth = 25;
                        break;
                    case 4:
                        columnWidth = 15;
                        break;
                    case 5:
                        columnWidth = 50;
                        break;
                    default:
                        break;
                }

                if (columnWidth > 255) {
                    columnWidth = 255;
                }
                writeSheetHolder.getSheet().setColumnWidth(cellIndex, columnWidth * 256);
            }
        }

        @Override
        public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
            // 设置行高测试
            int rowIndex = row.getRowNum();
            System.out.println("当前行: " + rowIndex);
            short height = 600;
            row.setHeight(height);
        }
    }
}

测试方式是 writeSimpleExcelWithHeader, 其中通过 getHeader() 方法去得到自定义表头, 注意自定义表头合并部分的写法, 另外,自定义表头样式是通过 getStyleStrategy()方法得到的,头部样式与内容样式是分开设置的。另外对于行高,列框是通过实现了easyexcel 里面提供的方法实现的, 也就是自定义类 CustomizeColumnWidth .

最终生成excel的部分代码,只有少许差别:

EasyExcel.write(fileName).head(list).registerWriteHandler(new CustomizeColumnWidth())
        .registerWriteHandler(getStyleStrategy()).sheet("sheet名称").doWrite(details);

其实里面还是用的POI的方法,通过实现 WriteHandler可以实现很多自己想要的功能。



上一篇: 利用easyexcel生成excel文件测试小记之一(easyexcel入门)
下一篇: 利用easyexcel生成excel文件-自定义单元格格式及样式
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号