package com.artfess.dataShare.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
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.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
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 javax.servlet.ServletOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;


@Data
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
    /**
     * 合并字段的下标，如第一到五列new int[]{0,1,2,3,4}
     */
    private int[] mergeColumnIndex;
    /**
     * 从第几行开始合并，如果表头占两行，这个数字就是2
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategy() {
    }

    public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
        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 (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[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 - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同，相同合并当前单元格与上一行
        if (curData.equals(preData)) {
            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);
            }
        }
    }

    public static void main(String[] args) {
        // 设置模拟表头（此处为多表头，也可以传入单表头）
        List<List<String>> headList = new ArrayList<>();
        List<String> heads1 = new ArrayList<>();
        heads1.add("总表头");
        heads1.add("表头1");
        headList.add(heads1);

        List<String> heads2 = new ArrayList<>();
        heads2.add("总表头");
        heads2.add("表头2");
        headList.add(heads2);

        List<String> heads3 = new ArrayList<>();
        heads3.add("总表头");
        heads3.add("表头3");
        headList.add(heads3);

        List<String> heads4 = new ArrayList<>();
        heads4.add("总表头");
        heads4.add("表头4");
        headList.add(heads4);
        // 设置模拟内容
        List<List<String>> data = new ArrayList<>();
        List<String> data1 = new ArrayList<>(); // 第1行的内容
        data1.add("内容1");
        data1.add("内容1-2");
        data1.add("内容3");
        data1.add("内容4");
        List<String> data2 = new ArrayList<>();// 第2行的内容
        data2.add("内容1");
        data2.add("内容2-2");
        data2.add("内容3");
        data2.add("内容4");
        data.add(data1);
        data.add(data2);
        try {
            //response.setContentType("application/vnd.ms-excel");
            //response.setCharacterEncoding("utf-8");
            // 防止中文乱码
            //String fileName = URLEncoder.encode("导入模板名称", "UTF-8");
            //response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //ServletOutputStream outputStream = response.getOutputStream();
            String file="D:\\out2.xlsx";
            FileOutputStream outputStream = new FileOutputStream(new File(file));
            ExcelWriter writer = EasyExcel.write(outputStream).build();

            WriteSheet sheet = EasyExcel.writerSheet(0).needHead(Boolean.FALSE).sheetName("sheet页名称").build();
            WriteTable table = EasyExcel.writerTable(1).head(headList)
                    // 设置只合并第1、2、3列，其余不合并
                    .registerWriteHandler(new ExcelFillCellMergeStrategy(1,new int[]{0,1,2}))
                    .needHead(Boolean.TRUE).build();
            writer.write(data, sheet, table); // data

            List<String> data3 = new ArrayList<>();// 第2行的内容
            data3.add("内容11");
            data3.add("内容21-2");
            data3.add("内容31");
            data3.add("内容41");
            data.add(data3);

            WriteSheet sheet1 = EasyExcel.writerSheet(1).needHead(Boolean.FALSE).sheetName("sheet页名称2").build();
            WriteTable table1 = EasyExcel.writerTable(2).head(headList)
                    // 设置只合并第1、2、3列，其余不合并
                    .registerWriteHandler(new ExcelFillCellMergeStrategy(1,new int[]{0,1,2}))
                    .needHead(Boolean.TRUE).build();
            writer.write(data, sheet1, table1); // data

            writer.finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}