freemarker生成復雜樣式圖片並無文件損壞的excel


參考Freemarker整合poi導出帶有圖片的Excel教程優化代碼實現和Excel版本兼容。

(因對代碼結構該動太大,沒有提交PR,代碼核心思路和代碼源於大腦補丁)

功能介紹:
1.支持Freemarker導出Excel的所有功能(完美導出復雜的合並單元格、合並行和列、顏色、字體等)
2.支持導出帶有圖片的Excel
3.支持多Sheet頁導出
4.支持導出單元格注釋
5.支持完美導出.xls、.xlsx格式,生成文件打開無報錯提醒
6.適用於生成復雜樣式的Excel,不適用於大數據量導出

需求背景

企業級需求中有較多復雜樣式的excel需求,包括各種單元格合並,插入圖片,而且變更頻繁,案例如下:

單純使用JAVA POI無法滿足此類開發需求。Freemarker導出的Excel為xml格式,此格式所有的富文本信息都會丟失,只留下文本內容,不能直接導出帶有圖片的Excel。通常使用Freemaker直接將.xml重命名為.xls的方法,對復雜樣式兼容不友好,會有彈框報錯。基於此種需求,開發此工具導出帶有圖片的Excel。

依賴包

<dependencies><!-- 僅僅需要基本的starter,不需要web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency><!-- 模板引擎 -->
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.28</version>
    </dependency><!-- java處理Excel文件,支持excel2003 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.17</version>
    </dependency><!--支持excel2007以上,性能特別好-->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
        <exclusions>
            <exclusion>
                <artifactId>poi</artifactId>
                <groupId>org.apache.poi</groupId>
            </exclusion>
        </exclusions>
    </dependency><!-- java解析XML文件 -->
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency><!-- 使用其中的FileUtils工具類 -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency><dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.9</version>
    </dependency>

使用步驟

1. 參考Freemaker語法設置占位符,將Excel文件另存為XML;

2. 將模板XML放到項目的模板目錄中

3. 導出效果

@Test
public void writeExcel() throws IOException {
    Map<String, Object> dataMap = getDemoDataMap();
    String templateName = "圖片-顏色-單元格合並-樣例.xml";
    /*
        若改變圖片位置,修改后4個參數
        dx1 dy1 起始單元格中的x,y坐標.
        dx2 dy2 結束單元格中的x,y坐標
        col1,row1 指定起始的單元格,下標從0開始
        col2,row2 指定結束的單元格 ,下標從0開始
     */
    HSSFClientAnchor hssfClientAnchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 5, 1, (short) 13, 21);
    // 讀取resource下的文件
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    // 獲取單個文件
    Resource resource = resolver.getResource("template/功能簡介.png");
    File img = resource.getFile();

    ExcelImage hssfImage = new ExcelImage(img, 0, hssfClientAnchor);
    List<ExcelImage> hssfImgs = new ArrayList<>();
    hssfImgs.add(hssfImage);
    ExcelWriter.writeExcel2003(dataMap, templateName, "圖片-顏色-單元格合並-樣例-2003", hssfImgs);

    XSSFClientAnchor xssfClientAnchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 5, 1, (short) 13, 21);
    ExcelImage xssfImage = new ExcelImage(img, 0, xssfClientAnchor);
    List<ExcelImage> xssfImgs = new ArrayList<>();
    xssfImgs.add(xssfImage);
    ExcelWriter.writeExcel2007(dataMap, templateName, "圖片-顏色-單元格合並-樣例-2007", xssfImgs);
}

代碼邏輯

1. 使用Freemaker給占位符賦值,生成XML文件,該XML文件中包含Excel原始樣式和所有數據;

2. 解析XML中的Excel樣式,轉化為CellStyle;

3. 遍歷XML的數據格式,按照讀取的CellStyle重新生成Excel;

4. 將圖片插入到給定的單元格中;

結論:此方法的邏輯是通過Freemaker模板引擎,給預置的Excel模板動態賦值,生成中間態的XML文件,再解析該XML文件生成新的Excel文件。將復雜的樣式和數據的編輯放在模板中,通過兩次IO生成文件,不適合大數據量的導出,適合結構復雜和多樣定制的Excel生成。

項目地址:

1. Github: 541211190/freemarker-excel (原作者的項目)
2. Github: Hlingoes/freemaker-poi-excel (按原作者思路重新實現的項目),Gitee:hlingoes/freemaker-poi-excel


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM