EasyExcel使用、合并

2023-10-28

写入EXCEL 有两种方法,其一是通过 直接代码控制,缺点是不好掌握整个的页面设计。

合并策略。根据  行开始和结束 进行控制,


合并列, 参数 mergeRowIndex 开始行,endmergeRowIndex截至行  mergeColumnIndex[]哪几列 垂直合并

 Boolean bool = cell.getRow().getCell(0).getStringCellValue()
                .equals(cell.getSheet()
                        .getRow(curRowIndex - 1).getCell(0).getStringCellValue()); 

根据第一列的数据进行 合并, 可以按自己需求增加

package demo3;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

public class ExcelFillCellMergeStrategyTest implements CellWriteHandler {
    private int[] mergeColumnIndex;
    private int mergeRowIndex;
    private int endmergeRowIndex;

    public ExcelFillCellMergeStrategyTest() {
    }

    public ExcelFillCellMergeStrategyTest(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    public ExcelFillCellMergeStrategyTest(int mergeRowIndex, int endmergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
        this.endmergeRowIndex = endmergeRowIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curRowIndex > mergeRowIndex && curRowIndex < endmergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }


    /**
     * 当前单元格向上合并
     *
     * @param writeSheetHolder
     * @param cell             当前单元格
     * @param curRowIndex      当前行
     * @param curColIndex      当前列
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
        // 将当前单元格数据与上一个单元格数据比较
        Boolean dataBool = preData.equals(curData);
        //此处需要注意:因为我是按照工程名称确定是否需要合并的,所以获取每一行第二列数据和上一行第一列数据进行比较,如果相等合并,getCell里面的值,是工程名称所在列的下标
        Boolean bool = cell.getRow().getCell(0).getStringCellValue()
                .equals(cell.getSheet()
                        .getRow(curRowIndex - 1).getCell(0).getStringCellValue());
        if (dataBool && bool) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }
}


合并列 ,mergeRowIndex[] 合并的列号    mergeColumnIndex 从第几列开始合并行 ,

 Boolean bool = cell.getSheet().getRow(13).getCell(curColIndex).getStringCellValue()
                .equals(cell.getSheet()
                        .getRow(13).getCell(curColIndex-1).getStringCellValue());

根据14行 的数据进行合并,可以自行增加或减少

package demo3;
//合并单元格

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 单元格合并
 *
 * @author Jamin
 * @date 2020/11/9 11:35
 */
@Data
public class ExcelMergeRowByRowUtil2 implements CellWriteHandler {
    /**
     * 合并字段的下标
     */
    private int[] mergeRowIndex;
    /**
     * 合并几行
     */
    private int mergeColumnIndex;

    public ExcelMergeRowByRowUtil2() {
    }

    public ExcelMergeRowByRowUtil2(int mergeColumnIndex, int[] mergeRowIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                 Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                       CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curColIndex > mergeColumnIndex) {
            for (int i = 0; i < mergeRowIndex.length; i++) {
                if (curRowIndex == mergeRowIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex).getCell(curColIndex-1);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();
        // 将当前单元格数据与上一个单元格数据比较
        Boolean dataBool = preData.equals(curData);
        //此处需要注意:因为我是按照工程名称确定是否需要合并的,所以获取每一行第二列数据和上一行第一列数据进行比较,如果相等合并,getCell里面的值,是工程名称所在列的下标
        Boolean bool = cell.getSheet().getRow(13).getCell(curColIndex).getStringCellValue()
                .equals(cell.getSheet()
                        .getRow(13).getCell(curColIndex-1).getStringCellValue());
        if (dataBool && bool) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex , curColIndex-1)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastColumn(curColIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex, curRowIndex, curColIndex-1,
                        curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }
}

样式调整 ,可以调整头和 内容的样式,通过行号可以控制

package demo3;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @Author wendy
 * @Date 2020/8/14 5:10 下午
 * @Desc 拦截处理单元格创建
 */
    public class HeadStyleWriteHandler extends AbstractCellStyleStrategy implements CellWriteHandler {

        Workbook workbook;

        @Override
        public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
            super.beforeCellCreate(writeSheetHolder, writeTableHolder, row, head, columnIndex, relativeRowIndex, isHead);
        }

        @Override
        public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            super.afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead);
        }

        @Override
        public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            this.initCellStyle(writeSheetHolder.getSheet().getWorkbook());
            this.setHeadCellStyle(cell,head,relativeRowIndex);
        }

        @Override
        protected void initCellStyle(Workbook workbook) {
            this.workbook = workbook;
        }

        @Override
        protected void setHeadCellStyle(Cell cell, Head head, Integer integer) {
            if (cell.getRowIndex() == 0) {
                cell.setCellStyle(EasyExcelUtils.getColumnTopStyle(workbook, 18));
            } else if (cell.getRowIndex() == 1) {
                cell.setCellStyle(EasyExcelUtils.getColumnTopStyle(workbook,11));
            }else if (cell.getRowIndex()==2){
                cell.setCellStyle(EasyExcelUtils.getColumnSecondLineStyle(workbook,20));
            }
            if(cell.getRowIndex() > 2){
                cell.setCellStyle(EasyExcelUtils.getColumnStyle(workbook));
            }
        }

        @Override
        protected void setContentCellStyle(Cell cell, Head head, Integer integer) {

        }
    }







package demo3;

import org.apache.poi.ss.usermodel.*;

public class EasyExcelUtils {

    /**
     * 首行单元格
     * @param workbook
     * @param fontSize
     * @return
     */
    public static CellStyle getColumnTopStyle(Workbook workbook, int fontSize) {
        if (fontSize == 0) {
            fontSize = 10;
        }
        // 设置字体
        Font font = workbook.createFont();
        //设置字体大小
        font.setFontHeightInPoints((short) fontSize);
        //字体加粗
        font.setBold(true);
        //设置字体名字
        font.setFontName("宋体");
        //设置样式;
        CellStyle style = workbook.createCellStyle();
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
//        style.setBorderBottom(BorderStyle.THIN);
//        style.setBorderLeft(BorderStyle.THIN);
//        style.setBorderRight(BorderStyle.THIN);
//        style.setBorderTop(BorderStyle.THIN);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);
        return style;
    }

    /**
     *
     * @param workbook
     * @param fontSize
     * @return
     */
    public static CellStyle getColumnSecondLineStyle(Workbook workbook, int fontSize) {
        if (fontSize == 0) {
            fontSize = 10;
        }
        Font font = workbook.createFont();
        //设置字体大小
        font.setFontHeightInPoints((short) fontSize);
        //字体加粗
        font.setBold(true);
        //设置字体名字
        font.setFontName("宋体");
        //设置样式;
        CellStyle style = workbook.createCellStyle();
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(false);

        //边框
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);


        return style;
    }
    /*
     * 字段样式
     */
    public static CellStyle getColumnStyle(Workbook workbook) {
        // 设置字体
        Font font = workbook.createFont();
        //设置字体大小
        font.setFontHeightInPoints((short) 12);
        //设置字体名字
        font.setFontName("Arial");
        //设置样式;
        CellStyle style = workbook.createCellStyle();
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //垂直居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
//        style.setBorderBottom(BorderStyle.THIN);
//        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
//        style.setBorderTop(BorderStyle.THIN);
        //在样式用应用设置的字体;
        style.setFont(font);
        //设置自动换行;
        style.setWrapText(true);
        return style;

    }
}

测试 输出

package demo3;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
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 demo3.entity.ComplexHeadStyles;
import org.apache.poi.ss.usermodel.*;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

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

    SimpleDateFormat simple = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
    Date date=new Date();
    String format = simple.format(date);

    /**
     * 初始化测试数据
     */
    @Before
    public void initData() {
        master = new Master();
        master.setBigTitle("设备购置需求 " + "(" +format + ")");
        master.setSmallTitle("()" + format);
        master.setCreatedDate(format);
        master.setTitle("购置需求");

        Detail d0 = new Detail();
        d0.setRow1("采购类别");
        d0.setRow2("设备");
        d0.setRow3("项目");
        d0.setRow4("");
        d0.setRow5("填表日期");
        d0.setRow6("填表日期");
        d0.setRow7("");
        d0.setRow8("");
        details.add(d0);



        Detail d1 = new Detail();
        d1.setRow1("申请");
        d1.setRow2("采中");
        d1.setRow3("联系人");
        d1.setRow4("");
        d1.setRow5("名称");
        d1.setRow6("");
        d1.setRow7("数量");
        d1.setRow8("12");
        details.add(d1);

        Detail d2 = new Detail();
        d2.setRow1("科");
        d2.setRow2("采");
        d2.setRow3("联系方式");
        d2.setRow4("11122223122");
        d2.setRow5("名称");
        d2.setRow6("");
        d2.setRow7("数量");
        d2.setRow8("12");
        details.add(d2);

        Detail d3= new Detail();
        d3.setRow1("项目总预算)");
        d3.setRow2("11");
        d3.setRow3("年份");
        d3.setRow4("c");
        d3.setRow5("区");
        d3.setRow6("1");
        d3.setRow7(" ");
        d3.setRow8(" ");

        details.add(d3);

        Detail d4= new Detail();
        d4.setRow1("aaa");
        d4.setRow2("ww");
        d4.setRow3("品行名号");
        d4.setRow4("w");

        details.add(d4);

        Detail d5= new Detail();
        d5.setRow1("推荐");
        d5.setRow2("序号");
        d5.setRow3("供应商");
        d5.setRow4("型号");
        d5.setRow5("品牌");
        d5.setRow6("联系人");
        d5.setRow7("电话");
        d5.setRow8("电话");
        details.add(d5);
        Detail d6= new Detail();
        d6.setRow1("狗东型号极其名称");

        details.add(d6);
        Detail d7= new Detail();
        d7.setRow1("狗东型号极其名称");
        d7.setRow2("插入项");
        details.add(d7);
        Detail d8= new Detail();
        d8.setRow1("狗东型号极其名称");
        details.add(d8);
        details.add(d8);

        Detail d9=new Detail();
        d9.setRow1("此写");
        d9.setRow2("采");
        d9.setRow3("采购概况");
        d9.setRow4("采购概况");
        d9.setRow5("预算");
        d9.setRow6("预算");
        d9.setRow7("备注");
        d9.setRow8("备注");
        details.add(d9);
        Detail d10 =new Detail();
        d10.setRow1("此写");
        details.add(d10);
        details.add(d10);
        details.add(d10);

        Detail d11=new Detail();
        d11.setRow1("会议");
        details.add(d11);
        details.add(d11);
        Detail d12=new Detail();
        d12.setRow1("会议");
        d12.setRow2("详细描述");
        details.add(d12);

        Detail d13=new Detail();
        d13.setRow1("设备");
        details.add(d13);
        details.add(d13);
        Detail d14=new Detail();
        d14.setRow1("设备");
        d14.setRow2("参数");
        details.add(d14);

        Detail d15=new Detail();
        d15.setRow1("意见");
        details.add(d15);
        details.add(d15);
        details.add(d15);

        Detail d16=new Detail();
        d16.setRow1("意见");
        details.add(d16);
        details.add(d16);
        Detail d17=new Detail();
        d17.setRow1("意见");
        d17.setRow2("修改附件");
        details.add(d17);

        Detail d18=new Detail();
        d18.setRow1("分管领导意见");
        details.add(d18);
        details.add(d18);
        details.add(d18);


    }

    /**
     * 仅仅输出明细数据到excel文件
     */
//    @Test
//    public void writeSimpleExcelForDetail() {
//        String path = this.getClass().getResource("/").getPath();
//        System.out.println(path);
//        String fileName = "D:\\bf\\simpleWrite" + System.currentTimeMillis() + ".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 =  "D:\\bf\\simpleWrite" + System.currentTimeMillis() + ".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 = "D:\\bf\\simpleWrite" + ".xlsx";
        File file = new File(fileName);
        if (file.exists()) {
            file.delete();
        }

        // 准备 HEADER
        List<List<String>> list = getHeader();
        // 这里 需要指定写用哪个class去写,指定模板名称及数据
        int rowArray[] =new int[]{0,1,2,3,4,5,6,7};
        int rowArray2[] =new int[]{0};

        int columnArray[] =new int[]{3,6,8,10,19,22};
        int columnArray2[]=new int[]{9,11,12,13,14,15,14,17,18,20,21,23,24,25,26,28,29,31};
//        int columnArray3[]=new int[]{};

        //需要从第一行开始,列头第一行
        EasyExcel.write(fileName).head(list)
                .registerWriteHandler(new CustomizeColumnWidth()) //设置行宽
                //设置标题和正文的内容
                //合并单元格策略
                //合并行,
                .registerWriteHandler(new ExcelMergeRowByRowUtil(2,columnArray))
                .registerWriteHandler(new ExcelMergeRowByRowUtil(1,columnArray2))
//                .registerWriteHandler(new ExcelMergeRowByRowUtil2(1,columnArray3))
                //合并列,开始,截至
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(3,9,rowArray))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(11,19,rowArray))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(19,22,rowArray))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(22,28,rowArray))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(29,32,rowArray))
                //合并列,开始,截至
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(8,13,rowArray2))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(17,20,rowArray2))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(19,23,rowArray2))
                .registerWriteHandler(new ExcelFillCellMergeStrategyTest(22,29,rowArray2))
                .registerWriteHandler(new HeadStyleWriteHandler())
                .sheet("sheet名称")
                .doWrite(details);
    }

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

        List<String> head0 = new ArrayList<String>();
        head0.add(customer);
        head0.add(sheetNo);
        head0.add(" ");
        list.add(head0);

        for (int i = 0; i < 7; i++) {
            List<String> head = new ArrayList<String>();
            head.add(customer);
            head.add(sheetNo);
            head.add(title);
            list.add(head);
        }


        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) 18);
//        headWriteCellStyle.setWriteFont(headWriteFont);
//        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
//        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//
//        // 内容的策略
//        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:
                        columnWidth = 12;
                        break;
                    case 2:
                    case 3:
                    case 1:
                        columnWidth = 15;
                        break;
                    case 4:
                    case 5:
                        columnWidth = 15;
                        break;
                    default:
                        columnWidth = 12;
                        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();
            short height = 600;
            System.out.println("当前行: " + rowIndex);
            if (rowIndex==2)
                height=1000;
            row.setHeight(height);
        }
    }
}

输出参考

参考文章

【easyexcel根据数据相同导出动态合并单元格】_ekkcole的博客-CSDN博客_easyexcel导出合并单元格


easyexcel导出合并单元格 - 简书

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EasyExcel使用、合并 的相关文章

  • 按键时关闭 ModalWindow

    我希望能够在用户按下某个键 在我的例子中是 ESC 时关闭 ModalWindow 我有一个用于按键的 Javascript 侦听器 它调用取消按钮 ID 的单击事件 jQuery modalWindowInfo closeButtonId
  • 在 Java 中克隆对象 [3 个问题]

    这样做会调用Asub的clone方法吗 或者Asub深度克隆是否正确 如果没有的话 有没有办法通过这种方法对Asub进行深度克隆呢 abstract class Top extends TopMost protected Object cl
  • Junit:如何测试从属性文件读取属性的方法

    嗨 我有课ReadProperty其中有一个方法ReadPropertyFile返回类型的Myclass从属性文件读取参数值并返回Myclass目的 我需要帮助来测试ReadPropertyFile方法与JUnit 如果可能的话使用模拟文件
  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • org.apache.hadoop.security.AccessControlException:客户端无法通过以下方式进行身份验证:[TOKEN,KERBEROS] 问题

    我正在使用 java 客户端通过 Kerberos 身份验证安全访问 HDFS 我尝试打字klist在服务器上 它显示已经存在的有效票证 我收到的异常是客户端无法通过以下方式进行身份验证 TOKEN KERBEROS 帮助将不胜感激 这是一
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • 在 junit 测试中获取 javax.lang.model.element.Element 类

    我想测试我的实用程序类 ElementUtils 但我不知道如何将类作为元素获取 在 AnnotationProcessors 中 我使用以下代码获取元素 Set
  • Eclipse Maven Spring 项目 - 错误

    I need help with an error which make me crazy I started to study Java EE and I am going through tutorial on youtube Ever
  • Hibernate 的 PersistentSet 不使用 hashCode/equals 的自定义实现

    所以我有一本实体书 public class Book private String id private String name private String description private Image coverImage pr
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 如何在用户输入数据后重新运行java代码

    嘿 我有一个基本的java 应用程序 显示人们是成年人还是青少年等 我从java开始 在用户输入年龄和字符串后我找不到如何制作它它们被归类为 我希望它重新运行整个过程 以便其他人可以尝试 的节目 我一直在考虑做一个循环 但这对我来说没有用
  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla

随机推荐

  • 制作一个简单的网页(入门篇)

    使用HTML和CSS来制作一个简单的网页 前言 一 HTML 1 1常见元素介绍 1 2借助工具 浏览器开发者工具 二 实现个人名片 1 基本框架 2 使用CSS美化 1 CSS书写位置 1 以元素的style 属性来指定 内联样式 2 以
  • 快速排序递归实现和非递归实现(详解)

    内容 快速排序的递归 非递归实现代码及注解 思路详解 以及快速排序的优化 目录 快速排序的递归实现 基本思想 步骤 让基准值排序到最终位置 使得左右区间自然分割开的方法有如下三种 1 hoare版本 基本思想 编辑动图演示 一些细节 代码实
  • dvwa靶场Brute Force(暴力破解)全难度教程(附代码分析)

    建议使用owaspbwa靶场可以不用搭建dvwa以及其他常用靶场 省去搭建靶场的困扰 但是此靶机靶场较老 并不建议使用 owaspbwa下载地址 OWASP Broken Web Applications Project download
  • 【C++奇遇记】函数模板

    博客主页 博主链接 本文由 M malloc 原创 首发于 CSDN 学习专栏推荐 LeetCode刷题集 数据库专栏 初阶数据结构 欢迎点赞 收藏 留言 如有错误敬请指正 未来很长 值得我们全力奔赴更美好的生活 文章目录 本章详情 函数模
  • XML的生成和解析

    一 什么是XML XML就是可扩展标记语言 HTML是超文本标记语言 标记语言就是通过一个一个的标记来组织数据的一种语法格式 与HTMl超文本语言比较的话XML这种可扩展语言它的标记是自己定义的 XML中自己定义的标记表示 例如 lt 标记
  • 复杂网络博弈:WS、NW小世界网络模型

    用Matlab程序分别绘制含有至少100个节点的WS NW小世界网络模型 并给出具体程序代码 带每行注释 Matlab版本 matlab R2022b 代码1 自己不用去创建函数体 设置节点数量为100 N 100 设置平均度数为4 K 4
  • 如何编写jstl自定义标签(示例:自定义jstl Long型时间转为date型)

    原文地址 http www cnblogs com icoding archive 2012 07 08 2581164 html 写jsp不可避免的会用到jstl 因为这个公司也没怎么用过velocity等模板 所以jstl就相对来说是比
  • 幼儿园分班问题 【Java】

    幼儿园分班问题 Java 题目描述 幼儿园两个班的小朋友在排队时混在了一起 每位小朋友都知道自己是否与前面一位小朋友是否同班 请你帮忙把同班的小朋友找出来 小朋友的编号是整数 与前一位小朋友同班用Y表示 不同班用N表示 输入描述 输入由空格
  • LaTeX 宏包(\usepackage)

    LaTeX 宏包引用及常用宏包简介 LaTeX 宏包 宏包介绍 常用宏包简介 如何安装宏包 MiKTeX Console 宏包调用 LaTeX 宏包 宏包介绍 宏包是用来扩展 增强LaTeX的功能 宏包与LaTeX的关系和浏览器插件与浏览器
  • hbuilderX自定义主题仿vscode暗黑主题

    目录 hbuilderX自定义主题仿vscode暗黑主题 效果图 设置方式 把主题代码复制进来即可 是基于雅蓝主题自定义的 设置好后需要切换到雅蓝主题 hbuilderx保存时自动整理代码 1 首先在顶部栏 找到工具 打开设置 2 点击旁边
  • net::ERR_CONNECTION_RESET 报错原因

    1 gt 向tomcat 服务器上上传视频 谷歌浏览器控制台报出 打开信地址栏后 发现 net ERR CONNECTION RESET 错误 但是此视频以经过mp4转码 注 浏览器支持的播放mp4视频编码格式为 AVC编码的H264 后发
  • Unity 打包至Android 平台 编译不通过 所遇到过的坑

    Now we are here to learn how to build a android app by unity game engine but Build 不出来咋办 你都遇到了那些情况的问题呢 1 入门 忘记设置包名 2 安装A
  • Intellj idea 中创建测试 test

    在idea中创建测试类有两种方法 1 鼠标点中类名 使用 Alt Enter 会弹出intention action gt create tests 2 鼠标点中类名 使用 Ctrl Shift T 默认 会弹出 create new te
  • 在uniapp微信小程序中实现无限级评论(vue递归组件+Java构建所有评论树状结构)

    1 前言 这是本人毕业设计中其中一个功能点 就是用户在微信小程序 使用uniapp框架 中的首页模块中可以对健身资讯进行评论或者社区模块对别人发布的动态进行评论 2 实现效果 最后放个演示视频吧 实现思路 1 首先 在前端页面中编写好一个递
  • 制作PCB的基本设计流程;

    基本流程 1 在电脑中建立一个自定义的文件夹 例如D AD project Project1 以备存储设计文件用 双击打开Altium Designer 进入软件工作界面 2 创建工程文件 单击 File 菜单 选择 New 选项中的 Pr
  • [知识/工具/安全渗透测试]简洁明了的Google Hacking教程,效率UPUP

    Google Hacking 简介 Google Hacking 是指利用谷歌搜索引擎中的高级操作符 在搜索结果中定位特定的文本字符串 依托于谷歌强大的后台爬虫数据库 灵活使用可大大提高效率 前排提醒 请遵守法律法规 科学上网 不要用于非法
  • 语音合成技术

    转自 https zhuanlan zhihu com p 27395458 语音合成又称文语转换 Text To Speech 简称TTS 指通过机械的 电子的方法生成语音的技术 随着科技的发展 合成语音的自然度和音质均得到了明显的改善
  • 在 MVC 4 中使用RDLC 报表

    前期知识点 RDLC 报表 Visual Studio NET进入2005版本以后 Crystal Report与IDE的结合更 紧密 了 至少我们看不到那个讨厌的注册窗口了 但是 Microsoft似乎并不容忍在自己的超级工具中竟然没有报
  • 如何完全卸载HbuilderX

    今天本来想发行打包安卓端 结果发现突然就不行了 前天还行 报错 然后我找了各种原因 排查了很久才发现是HbuilderX编辑器的问题 机智如我 所以我们需要重新去下载一个HbuilderX 但是问题来了 很多人不知道怎么卸载 我自己网上也百
  • EasyExcel使用、合并

    写入EXCEL 有两种方法 其一是通过 直接代码控制 缺点是不好掌握整个的页面设计 合并策略 根据 行开始和结束 进行控制 合并列 参数 mergeRowIndex 开始行 endmergeRowIndex截至行 mergeColumnIn