easyexcel導(dǎo)出合并單元格

吐槽:網(wǎng)絡(luò)上有很多人在貢獻(xiàn)自己的代碼昔穴,但是極其相似可以作為參考。如下:
https://cloud.tencent.com/developer/article/1671316椭住,https://www.it610.com/article/1296421123914801152.htm 等等)

前言:網(wǎng)絡(luò)上easyexcel合并的文章都使用的是“CellWriteHandler”,其實(shí)還有“RowWriteHandler”。此片文章將為大家提供一個(gè)按照行來(lái)合并單元格的做法

1.按行合并的策略ExcelMergeRowByRowUtil

public class ExcelMergeRowByRowUtil implements RowWriteHandler {
    private int mergeRowIndex;//從哪一行開(kāi)始合并
    private int[] mergeColumnIndex;//excel合并的列
    private int signNum;//合并的唯一標(biāo)識(shí)
    private int total;//總行數(shù)

    private int lastRow;
    private int firstCol;
    private int lastCol;
    private int firstRow;

    private int mergeCount =1;

    public ExcelMergeRowByRowUtil(int mergeRowIndex, int[] mergeColumnIndex, int signNum, int total) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
        this.signNum = signNum;
        this.total = total;
    }

    @Override
    public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
        //當(dāng)前行
        int curRowIndex = row.getRowNum();
        //每一行的最大列數(shù)
        short lastCellNum = row.getLastCellNum();

        if(curRowIndex == 1){
            //賦初值 第一行
            firstRow = curRowIndex;
        }
        //開(kāi)始合并位置
        if(curRowIndex > mergeRowIndex && !row.getCell(0).getStringCellValue().equals("")){
            for (int i = 0; i < lastCellNum; i++) {
                if(i == mergeColumnIndex[i]){
                    //當(dāng)前行號(hào) 當(dāng)前行對(duì)象 合并的標(biāo)識(shí)位
                    mergeWithPrevAnyRow(writeSheetHolder.getSheet(),curRowIndex,row,signNum);
                    break;//已經(jīng)進(jìn)入到合并單元格操作里面了字逗,執(zhí)行一次就行
                }

            }
        }
    }

    public void mergeWithPrevAnyRow(Sheet sheet,int curRowIndex,Row row,int signNum){
        Object currentData = row.getCell(signNum).getCellTypeEnum() == CellType.STRING ? row.getCell(signNum).getStringCellValue() : row.getCell(signNum).getNumericCellValue();
        Row preRow = row.getSheet().getRow(curRowIndex - 1);
        Object preData = preRow.getCell(signNum).getCellTypeEnum() == CellType.STRING ? preRow.getCell(signNum).getStringCellValue() : preRow.getCell(signNum).getNumericCellValue();
        //判斷是否合并單元格
        boolean curEqualsPre = currentData.equals(preData);
        //判斷前一個(gè)和后一個(gè)相同 并且 標(biāo)識(shí)位相同
        if (curEqualsPre){
            lastRow = curRowIndex;
            mergeCount++;
        }
        //excel過(guò)程中合并
        if(!curEqualsPre && mergeCount>1){
            mergeSheet(firstRow,lastRow,mergeColumnIndex,sheet);
            mergeCount = 1;
        }

        //excel結(jié)尾處合并
        if (mergeCount>1 && total==curRowIndex){
            mergeSheet(firstRow,lastRow,mergeColumnIndex,sheet);
            mergeCount = 1;
        }

        if (!curEqualsPre){
            firstRow = curRowIndex;
        }

    }

    private void mergeSheet(int firstRow,int lastRow,int[] mergeColumnIndex,Sheet sheet){
        for (int colNum : mergeColumnIndex){
            firstCol = colNum;
            lastCol = colNum;
            CellRangeAddress cellRangeAddress = new CellRangeAddress(firstRow,lastRow,firstCol,lastCol);
            sheet.addMergedRegion(cellRangeAddress);
        }
    }
}

2.easyexcel組裝的model

@Getter
@Setter
@ContentRowHeight(15) //內(nèi)容行高
@HeadRowHeight(20)//表頭行高
public class ExcelModel {
    /**oss模板名稱*/
    public static final String RESEXCELNAME = "document.xlsx";
    public static final String TEMPLATEEXCELNAME = "文章管理";
    public static final String SUFFIX = ".xlsx";

    /**
     * notice
     * 當(dāng)采用模板上傳Excel且.needHead(false)設(shè)置了不生成標(biāo)題頭  @ColumnWidth(10)標(biāo)簽將無(wú)效京郑,根據(jù)模板頭的長(zhǎng)度來(lái)走
     */
    @ColumnWidth(10)//單元格長(zhǎng)度
    @ExcelProperty(value = "序號(hào)", index = 0)
    private String order;

    @ColumnWidth(20)//單元格長(zhǎng)度
    @ExcelProperty(value = "文章標(biāo)題", index = 1)
    private String title;

    @ColumnWidth(15)//單元格長(zhǎng)度
    @ExcelProperty(value = "單位", index = 2)
    private String company;

    @ColumnWidth(15)//單元格長(zhǎng)度
    @ExcelProperty(value = "編號(hào)", index = 3)
    private String documentCode;

    @ColumnWidth(12)//單元格長(zhǎng)度
    @ExcelProperty(value = "發(fā)文日期", index = 4)
    private String publishDate;

    @ColumnWidth(25)//單元格長(zhǎng)度
    @ExcelProperty(value = "意見(jiàn)", index = 5)
    private String idea;

    @ColumnWidth(15)//單元格長(zhǎng)度
    @ExcelProperty(value = "事件詳情事項(xiàng)", index = 6)
    private String workDetails;

    @ColumnWidth(15)//單元格長(zhǎng)度
    @ExcelProperty(value = "截止時(shí)間", index = 7)
    private String dueTime;

    @ColumnWidth(20)//單元格長(zhǎng)度
    @ExcelProperty(value = "負(fù)責(zé)人", index = 8)
    private String name;

    @ColumnWidth(15)//單元格長(zhǎng)度
    @ExcelProperty(value = "備注", index = 9)
    private String remarks;

3.list組裝excel并合并單元格

public void getEasyExcel(List<ExcelModel> list){
        int[] mergeColumeIndex = {0,1,2,3,4,5};//需要合并的列
        int mergeRowIndex = 1;// 從那一行開(kāi)始合并
        //合并單元格
//      ExcelMergeUtil excelFillCellMergeStrategy = new ExcelMergeUtil(mergeRowIndex,mergeColumeIndex);
        ExcelMergeRowByRowUtil excelMergeRowByRowStrategy = new ExcelMergeRowByRowUtil(mergeRowIndex,mergeColumeIndex,mergeColumeIndex[0],documentExcelList.size());
        //設(shè)置頭樣式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        
        //設(shè)置內(nèi)容格式
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle,contentWriteCellStyle);
        
        //2.excel轉(zhuǎn)outputStream
        //拼裝excel字節(jié)數(shù)組outputStream
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        EasyExcel.write(out, DocumentExcelModel.class)
//              .withTemplate(in)
//              .needHead(false)//是否需要excel自定義模板的標(biāo)題頭
                .registerWriteHandler(horizontalCellStyleStrategy)
                .registerWriteHandler(excelMergeRowByRowStrategy)
//              .registerWriteHandler(excelFillCellMergeStrategy)//此處為網(wǎng)絡(luò)上按照每個(gè)單元格進(jìn)行合并
                .sheet("sheet")
                .doWrite(list);
    
}

ExcelMergeRowByRowUtil合并單元格的思路:
1.讀取每一行,如果上一行和當(dāng)前行唯一標(biāo)識(shí)位相同葫掉,mergeCount累加些举。當(dāng)上一行和當(dāng)前行唯一標(biāo)識(shí)位不相同的時(shí)候進(jìn)行合并單元格。
2.當(dāng)讀取到最后一行符合合并條件的時(shí)候進(jìn)行合并單元格俭厚。

ExcelMergeRowByRowUtil implements RowWriteHandler 與網(wǎng)上 ExcelMergeUtil implements CellWriteHandler的區(qū)別
CellWriteHandler實(shí)現(xiàn)的方法是按照cell為單元進(jìn)行處理的户魏,假如每一行有十列,則需要比對(duì)十次挪挤。
RowWriteHandler實(shí)現(xiàn)的方法是按照row為單位盡心處理的叼丑,粒度更粗一寫】该牛控制好操作excel速度會(huì)更快鸠信。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尖飞,隨后出現(xiàn)的幾起案子症副,更是在濱河造成了極大的恐慌店雅,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贞铣,死亡現(xiàn)場(chǎng)離奇詭異闹啦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辕坝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門窍奋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人酱畅,你說(shuō)我怎么就攤上這事琳袄。” “怎么了纺酸?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵窖逗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我餐蔬,道長(zhǎng)碎紊,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任樊诺,我火速辦了婚禮仗考,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘词爬。我一直安慰自己秃嗜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布顿膨。 她就那樣靜靜地躺著锅锨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恋沃。 梳的紋絲不亂的頭發(fā)上橡类,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音芽唇,去河邊找鬼顾画。 笑死,一個(gè)胖子當(dāng)著我的面吹牛匆笤,可吹牛的內(nèi)容都是我干的研侣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼炮捧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼庶诡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咆课,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤末誓,失蹤者是張志新(化名)和其女友劉穎扯俱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體喇澡,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迅栅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晴玖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片读存。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呕屎,靈堂內(nèi)的尸體忽然破棺而出让簿,到底是詐尸還是另有隱情,我是刑警寧澤秀睛,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布尔当,位于F島的核電站,受9級(jí)特大地震影響蹂安,放射性物質(zhì)發(fā)生泄漏居凶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一藤抡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抹估,春花似錦缠黍、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至语泽,卻和暖如春贸典,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踱卵。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工廊驼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惋砂。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓妒挎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親西饵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酝掩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容