亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

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

一、需求背景

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

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

二、方案分析

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

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

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

3.1 Maven 依賴

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

<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)容。對于圖片,需要在占位符前加 @,例如:

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

3.3 實(shí)現(xiàn)代碼

以下是核心實(shí)現(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í)", "數(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); // 每個(gè)類別寬度為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è)置第一條折線的粗細(xì)
        plot.getRenderer().setSeriesStroke(0, new BasicStroke(5.0f));
         // 根據(jù)樣式設(shè)置折線顏色
        plot.getRenderer().setSeriesPaint(0, Color.RED);
    }

效果

在這里插入圖片描述

踩坑

  • 插入圖片如何占位
    與常規(guī)文本替換不同,圖片插入需要在占位符前加 @,例如 ${@dailyOnlinePic}{{@pic}}
  • 統(tǒng)計(jì)圖中文亂碼
    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)計(jì)圖橫坐標(biāo)…
    如果生成的圖片寬度不夠,橫坐標(biāo)可能會(huì)顯示不全??梢酝ㄟ^增加圖片寬度解決,插入時(shí)等比例縮放:
ChartUtils.saveChartAsPNG(new File(picFile), chart, 1200, 400);
dataMap.put("dailyOnlinePic", 
Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());

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

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

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

相關(guān)文章

  • Reactor3 Map與FlatMap的區(qū)別示例詳解

    Reactor3 Map與FlatMap的區(qū)別示例詳解

    這篇文章主要為大家介紹了Reactor3 Map與FlatMap的區(qū)別示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • springboot 排除redis的自動(dòng)配置操作

    springboot 排除redis的自動(dòng)配置操作

    這篇文章主要介紹了springboot 排除redis的自動(dòng)配置操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java直接插入排序示例

    java直接插入排序示例

    這篇文章主要介紹了java直接插入排序示例,插入排序的比較次數(shù)仍然是n的平方,但在一般情況下,它要比冒泡排序快一倍,比選擇排序還要快一點(diǎn)。它常常被用在復(fù)雜排序算法的最后階段,比如快速排序。
    2014-05-05
  • Java 中執(zhí)行動(dòng)態(tài)表達(dá)式語句前中后綴Ognl、SpEL、Groovy、Jexl3

    Java 中執(zhí)行動(dòng)態(tài)表達(dá)式語句前中后綴Ognl、SpEL、Groovy、Jexl3

    這篇文章主要介紹了Java 中執(zhí)行動(dòng)態(tài)表達(dá)式語時(shí)的句前中后綴Ognl、SpEL、Groovy、Jexl3的相關(guān)資料,需要的朋友可以參考下面文章的詳細(xì)介紹
    2021-09-09
  • Java結(jié)構(gòu)型模式之門面模式詳解

    Java結(jié)構(gòu)型模式之門面模式詳解

    門面模式又叫外觀模式(Facade Pattern),主要用于隱藏系統(tǒng)的復(fù)雜性,并向客戶端提供了一個(gè)客戶端可以訪問系統(tǒng)的接口,本文通過實(shí)例代碼給大家介紹下java門面模式的相關(guān)知識,感興趣的朋友一起看看吧
    2023-02-02
  • Java中&和&&的區(qū)別簡單介紹

    Java中&和&&的區(qū)別簡單介紹

    這篇文章主要介紹了Java中&和&&的區(qū)別,&&邏輯與||邏輯或  它們都是邏輯運(yùn)算符,& 按位與|按位或它們都是位運(yùn)算符,更多詳細(xì)內(nèi)容請需要的小伙伴了解下面文章內(nèi)容
    2022-01-01
  • Java中的FutureTask實(shí)現(xiàn)代碼實(shí)例

    Java中的FutureTask實(shí)現(xiàn)代碼實(shí)例

    這篇文章主要介紹了Java中的FutureTask手寫代碼實(shí)例,FutureTask是Future的實(shí)現(xiàn),用來異步任務(wù)的獲取結(jié)果,可以啟動(dòng)和取消異步任務(wù),查詢異步任務(wù)是否計(jì)算結(jié)束以及獲取最終的異步任務(wù)的結(jié)果,需要的朋友可以參考下
    2023-12-12
  • SpringBoot?@Scheduled?Cron表達(dá)式使用方式

    SpringBoot?@Scheduled?Cron表達(dá)式使用方式

    這篇文章主要介紹了SpringBoot?@Scheduled?Cron表達(dá)式使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • SpringBoot集成Druid配置(yaml版本配置文件)詳解

    SpringBoot集成Druid配置(yaml版本配置文件)詳解

    這篇文章主要介紹了SpringBoot集成Druid配置(yaml版本配置文件),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • java http連接池的實(shí)現(xiàn)方式(帶有失敗重試等高級功能)

    java http連接池的實(shí)現(xiàn)方式(帶有失敗重試等高級功能)

    這篇文章主要介紹了java http連接池的實(shí)現(xiàn)方式(帶有失敗重試等高級功能),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04

最新評論