最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

EasyExcel如何導(dǎo)出多級且動(dòng)態(tài)的表頭

 更新時(shí)間:2026年01月14日 09:15:57   作者:小憨憨的牛  
文章介紹了使用EasyExcel庫實(shí)現(xiàn)Excel多級表頭導(dǎo)出的步驟,包括創(chuàng)建表頭集合、導(dǎo)出數(shù)據(jù)集合、設(shè)置樣式和列寬,以及自動(dòng)合并表頭和測試導(dǎo)出

實(shí)現(xiàn)步驟

  1. 創(chuàng)建表頭集合List<List<String>> headList,為每個(gè)單元格設(shè)置完整的表頭路徑(一級,二級....)
  2. 創(chuàng)建導(dǎo)出數(shù)據(jù)集合List<List<String>> dataList,每行列數(shù)要與最末及表頭的列數(shù)一致
  3. 定義表頭或單元格的樣式,列寬等
  4. 導(dǎo)出時(shí)應(yīng)用樣式

分析

EasyExcel 會(huì)根據(jù)你的Head結(jié)構(gòu)自動(dòng)判斷是否需要合并表頭。如果你的表頭是多層級的(比如有分組表頭),EasyExcel 會(huì)自動(dòng)合并相同的一級表頭。

動(dòng)態(tài)表頭可以根據(jù)實(shí)際的業(yè)務(wù)需求組裝成List<List<String>>格式,導(dǎo)出數(shù)據(jù)也是。

一 .業(yè)務(wù)代碼

@Test
    void excelTest(){
        // 1. 動(dòng)態(tài)構(gòu)建表頭(一級和二級)
        List<List<String>> headList = new ArrayList<>();

        // 為每個(gè)單元格設(shè)置完整的表頭路徑
        headList.add(new ArrayList<>(Arrays.asList("id")));
        headList.add(new ArrayList<>(Arrays.asList("學(xué)院", "學(xué)院名稱")));
        headList.add(new ArrayList<>(Arrays.asList("學(xué)院", "學(xué)院代碼")));
        headList.add(new ArrayList<>(Arrays.asList("學(xué)生信息", "姓名")));
        headList.add(new ArrayList<>(Arrays.asList("學(xué)生信息", "學(xué)號")));
        headList.add(new ArrayList<>(Arrays.asList("成績", "數(shù)學(xué)")));
        headList.add(new ArrayList<>(Arrays.asList("成績", "語文")));

        // 2. 準(zhǔn)備內(nèi)容數(shù)據(jù)(每行列數(shù)與二級表頭一致)
        List<List<Object>> dataList = new ArrayList<>();
        dataList.add(new ArrayList<>(Arrays.asList("123","計(jì)算機(jī)學(xué)院", "CS001", "張三", "S1001", 90, 85)));
        dataList.add(new ArrayList<>(Arrays.asList("324","計(jì)算機(jī)學(xué)院", "CS001", "李四", "S1002", 88, 92)));
        dataList.add(new ArrayList<>(Arrays.asList("966","文學(xué)院", "LA002", "王五", "S2001", 78, 95)));

        // 3. 自定義表頭字體格式樣式
        WriteCellStyle headWriteCellStyle = ExcelHeadStyle.writExcelHeadStyle();
        
        // 4. 應(yīng)用樣式策略
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, new WriteCellStyle());

        // 5. 導(dǎo)出 Excel 并應(yīng)用樣式
        String fileName = "dynamic_header_with_style.xlsx";
        EasyExcel.write(fileName)
                .head(headList)
                .registerWriteHandler(horizontalCellStyleStrategy)  // 注冊樣式處理器
                .registerWriteHandler(new ExcelCellWriteHandler()) // 注冊自適應(yīng)列寬
                .sheet("學(xué)生成績表")
                .doWrite(dataList);
    }

二. 表頭樣式實(shí)現(xiàn)

/**
 * @Description Excel表頭樣式
 * @Author dhp
 * @create 2025-06-09 15:13
 */
public class ExcelHeadStyle {

    /**
     * 設(shè)置表頭字體格式樣式
     * @return
     */
    public static WriteCellStyle writExcelHeadStyle(){
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 設(shè)置表頭居中對齊
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

        // 創(chuàng)建字體樣式
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontName("宋體");  // 設(shè)置字體
        headWriteFont.setFontHeightInPoints((short) 12);  // 設(shè)置字號
        headWriteFont.setBold(true);  // 加粗
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 設(shè)置背景顏色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        return headWriteCellStyle;
    }

}

三.表頭和單元格列寬調(diào)整策略

自動(dòng)適應(yīng)合適的列寬

**
 * 單元格列寬調(diào)整策略
 * @Description
 * @Author dhp
 * @create 2025-06-09 14:55
 */
public class ExcelCellWriteHandler extends AbstractColumnWidthStyleStrategy {
    private static final int MAX_COLUMN_WIDTH = 255;
    private static final int MIN_COLUMN_WIDTH = 8;

    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        int columnIndex = cell.getColumnIndex();
        Sheet sheet = writeSheetHolder.getSheet();

        // 如果是表頭,直接設(shè)置寬度
        if (isHead) {
            String text = cell.getStringCellValue();
            int width = text.length() * 2 + 2;
            width = Math.min(width, MAX_COLUMN_WIDTH);
            width = Math.max(width, MIN_COLUMN_WIDTH);
            sheet.setColumnWidth(columnIndex, width * 256);
        }
        // 如果是內(nèi)容單元格,計(jì)算并比較是否需要更新寬度
        else {
            // 獲取當(dāng)前列寬
            int currentWidth = sheet.getColumnWidth(columnIndex) / 256;

            // 計(jì)算內(nèi)容所需寬度
            int contentWidth = calculateCellWidth(cell);
            contentWidth = Math.min(contentWidth, MAX_COLUMN_WIDTH);
            contentWidth = Math.max(contentWidth, MIN_COLUMN_WIDTH);

            // 如果內(nèi)容比當(dāng)前列寬更寬,則更新列寬
            if (contentWidth > currentWidth) {
                sheet.setColumnWidth(columnIndex, contentWidth * 256);
            }
        }
    }

    /**
     * 根據(jù)單元格內(nèi)容計(jì)算合適的寬度
     * @param cell
     * @return
     */
    private int calculateCellWidth(Cell cell) {
        String text;
        switch (cell.getCellType()) {
            case STRING:
                text = cell.getStringCellValue();
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    text = cell.getDateCellValue().toString();
                } else {
                    text = String.valueOf(cell.getNumericCellValue());
                }
                break;
            case BOOLEAN:
                text = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                text = cell.getCellFormula();
                break;
            default:
                text = "";
        }

        // 簡單計(jì)算:中文字符算2個(gè)寬度,其他算1個(gè)
        int width = 0;
        for (char c : text.toCharArray()) {
            //0x4E00 到 0x9FA5 是 Unicode 中 CJK 統(tǒng)一表意文字的范圍(即中文字符)
            width += (c >= 0x4E00 && c <= 0x9FA5) ? 2 : 1;
        }

        return width + 2; // 加2作為邊距
    }
}

四.測試導(dǎo)出

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中NIO的三大核心組件詳細(xì)解析

    Java中NIO的三大核心組件詳細(xì)解析

    這篇文章主要介紹了Java中NIO的三大核心組件詳細(xì)解析,NIO的Buffer類是一個(gè)抽象類,位于java.nio包中,提供了一組更加有效的方法,用來進(jìn)行寫入和讀取的交替訪問,本質(zhì)上是一個(gè)內(nèi)存塊,既可以寫入數(shù)據(jù),也可以從中讀取數(shù)據(jù),需要的朋友可以參考下
    2023-12-12
  • java實(shí)現(xiàn)解析二進(jìn)制文件的方法(字符串、圖片)

    java實(shí)現(xiàn)解析二進(jìn)制文件的方法(字符串、圖片)

    本篇文章主要介紹了java實(shí)現(xiàn)解析二進(jìn)制文件的方法(字符串、圖片),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • 教你使用IDEA搭建spring源碼閱讀環(huán)境的詳細(xì)步驟

    教你使用IDEA搭建spring源碼閱讀環(huán)境的詳細(xì)步驟

    這篇文章主要介紹了使用IDEA搭建spring源碼閱讀環(huán)境的詳細(xì)步驟,本文分兩步通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-08-08
  • Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹

    Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹

    這篇文章主要介紹了Java設(shè)計(jì)模式之橋模式(Bridge模式)介紹,本文講解了為什么使用橋模式、如何實(shí)現(xiàn)橋模式、Bridge模式在EJB中的應(yīng)用等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • Spring boot將配置屬性注入到bean類中

    Spring boot將配置屬性注入到bean類中

    本篇文章主要介紹了Spring boot將配置屬性注入到bean類中,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • SpringBoot中restTemplate請求存在亂碼問題的解決方法

    SpringBoot中restTemplate請求存在亂碼問題的解決方法

    這篇文章主要介紹了SpringBoot中restTemplate請求存在亂碼問題的解決方法,文中有相關(guān)的圖文和代碼示例供大家參考,對大家的解決問題有一定的幫助,需要的朋友可以參考下
    2024-11-11
  • 解讀maven項(xiàng)目中Tomcat10與JSTL的問題匯總(Debug親身經(jīng)歷)

    解讀maven項(xiàng)目中Tomcat10與JSTL的問題匯總(Debug親身經(jīng)歷)

    這篇文章主要介紹了解讀maven項(xiàng)目中Tomcat10與JSTL的問題匯總(Debug親身經(jīng)歷),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • MyBatis中${}?和?#{}?有什么區(qū)別小結(jié)

    MyBatis中${}?和?#{}?有什么區(qū)別小結(jié)

    ${}?和?#{}?都是?MyBatis?中用來替換參數(shù)的,它們都可以將用戶傳遞過來的參數(shù),替換到?MyBatis?最終生成的?SQL?中,但它們區(qū)別卻是很大的,今天通過本文介紹下MyBatis中${}?和?#{}?有什么區(qū)別,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • 優(yōu)惠券優(yōu)惠的思路以及實(shí)踐

    優(yōu)惠券優(yōu)惠的思路以及實(shí)踐

    本文主要介紹了優(yōu)惠券優(yōu)惠的思路以及實(shí)踐。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • SpringBoot定時(shí)任務(wù)參數(shù)運(yùn)行代碼實(shí)例解析

    SpringBoot定時(shí)任務(wù)參數(shù)運(yùn)行代碼實(shí)例解析

    這篇文章主要介紹了SpringBoot定時(shí)任務(wù)運(yùn)行代碼實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06

最新評論

景德镇市| 嵊泗县| 房山区| 错那县| 奈曼旗| 河北省| 汽车| 河西区| 灯塔市| 宿迁市| 扶沟县| 涟水县| 巢湖市| 张家港市| 方山县| 深水埗区| 休宁县| 霍州市| 旺苍县| 宁晋县| 龙门县| 沁水县| 延安市| 南岸区| 余干县| 藁城市| 平和县| 永和县| 兴安县| 西乌| 射洪县| 印江| 丽水市| 东安县| 南郑县| 马山县| 大关县| 嵊泗县| 鹤壁市| 渝中区| 涟水县|