欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用POI-TL和JFreeChart動態(tài)生成Word報告

 更新時間:2025年02月09日 09:53:51   作者:Mr-Wanter  
本文介紹了使用POI-TL和JFreeChart生成包含動態(tài)數(shù)據(jù)和圖表的Word報告的方法,并分享了實際開發(fā)中的踩坑經(jīng)驗,通過代碼示例講解的非常詳細,具有一定的參考價值,需要的朋友可以參考下

前言

在開發(fā)過程中,我們經(jīng)常需要生成包含動態(tài)數(shù)據(jù)和圖表的 Word 報告。本文將介紹如何結(jié)合 POI-TL 和 JFreeChart,實現(xiàn)動態(tài)生成 Word 報告的功能,并分享一些實際開發(fā)中的踩坑經(jīng)驗。
word生成方案:

  • freemarker+ftl
  • pot-tl模板替換
  • poi硬編碼

一、需求背景

在之前的文章中,我們已經(jīng)介紹了如何使用模板替換、復(fù)雜表格和圖片插入等功能。此次的需求是生成一個包含統(tǒng)計圖的 Word 報告,統(tǒng)計圖需要根據(jù)動態(tài)數(shù)據(jù)生成。面臨的主要問題包括:

  • 選擇 Word 生成方案:如何在 Word 中動態(tài)插入數(shù)據(jù)和圖表?
  • 圖片插入方案:如何將生成的統(tǒng)計圖插入到 Word 中?
  • 生成統(tǒng)計圖表方案:如何根據(jù)數(shù)據(jù)動態(tài)生成統(tǒng)計圖?

二、方案分析

  • POI 硬編碼
    直接使用 Apache POI 硬編碼生成 Word 文檔,雖然可行,但代碼復(fù)雜且難以維護,因此不推薦。
  • FreeMarker + FTL
    FreeMarker 可以實現(xiàn)文本替換和圖片插入,理論上符合需求。但 FTL 模板的維護較為繁瑣,尤其是在處理復(fù)雜表格和圖片時。
  • POI-TL + JFreeChart
    POI-TL 是一個基于 Apache POI 的模板引擎,支持文本替換、圖片插入等功能。結(jié)合 JFreeChart 生成統(tǒng)計圖,可以很好地滿足需求。

三、 POI-TL + JFreeChart 實現(xiàn)

關(guān)于JFreeChart請移步Java使用JFreeChart創(chuàng)建動態(tài)圖表的代碼示例_java_腳本之家

3.1 Maven 依賴

首先,需要在項目中引入 POI-TL 和 JFreeChart 的依賴。注意 POI 和 POI-TL 的版本需要對應(yīng),否則可能會出現(xiàn) NoSuchMethod 等錯誤。

<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-scratchpad</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-excelant</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml-schemas</artifactId>
		    <version>4.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.jfree</groupId>
			<artifactId>jfreechart</artifactId>
			<version>1.5.3</version>
		</dependency>
		<dependency>
			<groupId>com.deepoove</groupId>
			<artifactId>poi-tl</artifactId>
			<version>1.10.0</version>
		</dependency>

3.2 word模板設(shè)置

在 Word 模板中,使用占位符標(biāo)記需要替換的內(nèi)容。對于圖片,需要在占位符前加 @,例如:

  • 替換文本:時間 -> ${date}
  • 插入圖片:${@dailyOnlinePic}

3.3 實現(xiàn)代碼

以下是核心實現(xiàn)代碼:

    private static final String TEMPLATE_PATH = "classpath:template/report.docx";
    private static final String OUTPUT_DIR = "D:/data/upload/analysis/";
    private static final String PIC_DIR = OUTPUT_DIR + "pic/";

    public void getWord(String curDistCode) {
        try {
            // 獲取模板文件
            File file = ResourceUtils.getFile(TEMPLATE_PATH);

            // 構(gòu)建模板替換的數(shù)據(jù)
            Map<String, Object> dataMap = buildTemplateData(curDistCode);

            // 生成最終文件路徑
            String fileName = UUIDUtil.genUUID32() + ".docx";
            String filePath = OUTPUT_DIR + fileName;

            // 使用 POI-TL 渲染模板并保存
            try (XWPFTemplate template = XWPFTemplate.compile(file, Configure.newBuilder().buildGramer("${", "}").build())
                    .render(dataMap)) {
                template.writeToFile(filePath);
            }
            //上傳文件返回附件id
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Map<String, Object> buildTemplateData(String curDistCode) throws IOException {
        Map<String, Object> dataMap = new HashMap<>();

        // 設(shè)置日期和在線總數(shù)
        dataMap.put("date", LocalDate.now());
        // 查詢設(shè)備數(shù)據(jù)
        dataMap.put("onlineTotal", 100);
        // 生成每日在線圖表
        DefaultCategoryDataset dailyData = buildDailyDataset(stationByTime);
        String dailyPicFile = generateChart(dailyData, "監(jiān)測站總在線數(shù)", "小時", "數(shù)量", dailyOnlineTxtEnum);
        dataMap.put("dailyOnlinePic", Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());
        return dataMap;
    }
    // 構(gòu)建每日在線圖表的數(shù)據(jù)集
    private DefaultCategoryDataset buildDailyDataset(List<FireStationByTimeDTO> stationByTime) {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        stationByTime.forEach(t -> dataset.addValue(t.getOnlineNum(), "", t.getTime()));
        return dataset;
    }
    // 生成圖表并保存為圖片
    private String generateChart(DefaultCategoryDataset dataset, String title, String xAxisLabel, String yAxisLabel, DailyOnlineTxtEnum style) throws IOException {
        // 設(shè)置全局字體(支持中文)
        StandardChartTheme chartTheme = new StandardChartTheme("CN");
        chartTheme.setExtraLargeFont(new Font("宋體", Font.PLAIN, 14)); // 標(biāo)題字體
        chartTheme.setLargeFont(new Font("宋體", Font.PLAIN, 14));     // 圖例字體
        chartTheme.setRegularFont(new Font("宋體", Font.PLAIN, 12));   // 軸標(biāo)簽字體
        ChartFactory.setChartTheme(chartTheme);

        // 創(chuàng)建圖表
        JFreeChart chart = ChartFactory.createLineChart(title, xAxisLabel, yAxisLabel, dataset);
        setChartStyle(chart, style);

        // 保存圖表為圖片
        String picFile = PIC_DIR + UUIDUtil.genUUID32() + ".png";
        //int numberOfCategories = dataset.getColumnCount();
        //int width = Math.max(800, numberOfCategories * 50); // 每個類別寬度為50,最小寬度為800
        ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);
        return picFile;
    }

    // 設(shè)置圖表樣式
    private void setChartStyle(JFreeChart chart) {
        CategoryPlot plot = chart.getCategoryPlot();
        chart.setBackgroundPaint(Color.WHITE);
        plot.setBackgroundPaint(Color.WHITE);
        plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
        plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
        // 設(shè)置第一條折線的粗細
        plot.getRenderer().setSeriesStroke(0, new BasicStroke(5.0f));
         // 根據(jù)樣式設(shè)置折線顏色
        plot.getRenderer().setSeriesPaint(0, Color.RED);
    }

效果

在這里插入圖片描述

踩坑

  • 插入圖片如何占位
    與常規(guī)文本替換不同,圖片插入需要在占位符前加 @,例如 ${@dailyOnlinePic}{{@pic}}
  • 統(tǒng)計圖中文亂碼
    JFreeChart 默認(rèn)不支持中文,需要通過設(shè)置全局字體解決:
       // 設(shè)置全局字體(支持中文)
        StandardChartTheme chartTheme = new StandardChartTheme("CN");
        chartTheme.setExtraLargeFont(new Font("宋體", Font.PLAIN, 14)); // 標(biāo)題字體
        chartTheme.setLargeFont(new Font("宋體", Font.PLAIN, 14));     // 圖例字體
        chartTheme.setRegularFont(new Font("宋體", Font.PLAIN, 12));   // 軸標(biāo)簽字體
        ChartFactory.setChartTheme(chartTheme);
  • 統(tǒng)計圖橫坐標(biāo)…
    如果生成的圖片寬度不夠,橫坐標(biāo)可能會顯示不全??梢酝ㄟ^增加圖片寬度解決,插入時等比例縮放:
ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);
dataMap.put("dailyOnlinePic", 
Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());

或動態(tài)計算需要生成的圖片寬度:

int numberOfCategories = dataset.getColumnCount();
int width = Math.max(800, numberOfCategories * 50); // 每個類別寬度為50,最小寬度為800

到此這篇關(guān)于Java使用POI-TL和JFreeChart動態(tài)生成Word報告的文章就介紹到這了,更多相關(guān)Java POI-TL JFreeChart生成Word報告t內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • idea git未提交代碼文件名字變色(圖解)

    idea git未提交代碼文件名字變色(圖解)

    這篇文章主要介紹了idea git未提交代碼文件名字變色,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • Java輸入輸出流方式(文件的復(fù)制)

    Java輸入輸出流方式(文件的復(fù)制)

    Java中的輸入輸出流主要用于數(shù)據(jù)的讀取和寫入,在文件復(fù)制中,我們首先創(chuàng)建輸入流和輸出流對象,然后打開源文件和目標(biāo)文件,接著,通過循環(huán)讀取源文件中的數(shù)據(jù),并將其寫入目標(biāo)文件中,最后,關(guān)閉輸入輸出流以釋放資源
    2025-02-02
  • Springboot讀取外部配置文件,項目部署時配置讀取不到問題及解決

    Springboot讀取外部配置文件,項目部署時配置讀取不到問題及解決

    這篇文章主要介紹了Springboot讀取外部配置文件,項目部署時配置讀取不到問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • idea 使用Maven Helper idea的解決方法

    idea 使用Maven Helper idea的解決方法

    這篇文章主要介紹了idea 使用Maven Helper idea的解決方法,本文給大家介紹的非常詳細對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • SpringBoot中使用?ThreadLocal?進行多線程上下文管理及注意事項小結(jié)

    SpringBoot中使用?ThreadLocal?進行多線程上下文管理及注意事項小結(jié)

    本文詳細介紹了ThreadLocal的原理、使用場景和示例代碼,并在SpringBoot中使用ThreadLocal保存請求中攜帶的用戶信息,ThreadLocal通過為每個線程維護獨立的變量副本,解決了線程安全問題,感興趣的朋友一起看看吧
    2025-02-02
  • Spring?this調(diào)用當(dāng)前類方法無法攔截的示例代碼

    Spring?this調(diào)用當(dāng)前類方法無法攔截的示例代碼

    這篇文章主要介紹了Spring?this調(diào)用當(dāng)前類方法無法攔截,通過debug 查看這個proxyService1 和this的區(qū)別,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • Java框架Quartz中API、Jobs和Trigger詳解

    Java框架Quartz中API、Jobs和Trigger詳解

    這篇文章主要介紹了Java框架Quartz中API、Jobs和Trigger詳解,JobDetail?對象是在將?job?加入?scheduler?時,由客戶端程序(你的程序)創(chuàng)建的,它包含?job?的各種屬性設(shè)置,以及用于存儲?job?實例狀態(tài)信息的?JobDataMap,需要的朋友可以參考下
    2023-11-11
  • Spring框架事務(wù)屬性中事務(wù)隔離級別與傳播行為全面講解

    Spring框架事務(wù)屬性中事務(wù)隔離級別與傳播行為全面講解

    這篇文章主要介紹了Spring框架聲明式事務(wù)的事務(wù)隔離級別和事務(wù)傳播行為,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • Java根據(jù)模板實現(xiàn)excel導(dǎo)出標(biāo)準(zhǔn)化

    Java根據(jù)模板實現(xiàn)excel導(dǎo)出標(biāo)準(zhǔn)化

    這篇文章主要為大家詳細介紹了Java如何根據(jù)模板實現(xiàn)excel導(dǎo)出標(biāo)準(zhǔn)化,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-03-03
  • java實現(xiàn)單鏈表中是否有環(huán)的方法詳解

    java實現(xiàn)單鏈表中是否有環(huán)的方法詳解

    本篇文章介紹了,用java實現(xiàn)單鏈表中是否有環(huán)的方法詳解。需要的朋友參考下
    2013-05-05

最新評論