吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 482|回复: 2
收起左侧

[学习记录] Java替换PPT模板饼图或者柱状图数据解决方案

  [复制链接]
zhouen 发表于 2025-4-7 14:27
本帖最后由 zhouen 于 2025-4-7 14:42 编辑

Java替换PPT模板饼图或者柱状图数据解决方案

日常工作中遇到了一个很小众的问题,就是目前给定的PPT模板中存在饼状图和柱状图(测试用的是wps中的图表),
需要根据后台数据改变PPT中的饼状体和柱状图的数据。尝试和很多种方法,记录下最终的解决方案:

PPT中的图形如下(主要是替换数据,实现图形根据数据变化):


               饼状图:
                pie.png
               柱状图:
                bar.png

具体实现方式如下如下:

package com.eaq.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFChart;
import org.apache.poi.xssf.usermodel.*;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.*;

public class PPTBarPieUtil  {

    public static void updateChart(XSLFChart chart, Map<String, Object[][]> dataMap) throws Exception {
        //判断是否有引用文件(Excel文件),若没有不处理
        if (chart.getRelations().isEmpty()) {
            return;
        }
        // get chart's data source which is a Excel sheet
        XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
//        String sheetName = chartDataWorkbook.getSheetAt(0);
        XSSFSheet chartDataSheet = chartDataWorkbook.getSheetAt(0);
        // current Office uses a table as data source
        // so get that table if present
        XSSFRow row1 = chartDataSheet.getRow(0);
        XSSFTable chartDataTable = null;
        if (chartDataSheet.getTables().size() > 0) {
            chartDataTable = chartDataSheet.getTables().get(0);
            row1 = ((XSSFSheet) chartDataTable.getParent()).getRow(0);
        }
        if(row1 == null){
            return;
        }
        String rawValue = row1.getCell(0).getStringCellValue();
        if (StringUtils.isBlank(rawValue)) {
            return;
        }
        Object[][] data = dataMap.get(rawValue.trim());
        if (null == data || data.length == 0) {
            return;
        }
        if (chart.getChartSeries().size() >= 1) { // we will process only one chart data
            XDDFChartData chartData = chart.getChartSeries().get(0);
            if (chartData.getSeriesCount() == 1) { // we will process only templates having one series

                int rMin = 1; // first row (0) is headers row
                int rMax = data.length - 1;

                // set new category data
                XDDFCategoryDataSource category = null;
                int c = 0;
                for (int r = rMin; r <= rMax; r++) {
                    XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
                    XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
                    cell.setCellValue((String)data[r][c]); // in sheet
                }
                category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart

                // series 1, is present already and a pie chart only has one series
                c = 1;

                // set new values in sheet and in chart
                XDDFNumericalDataSource<Double> values = null;
                // to remain possible cell styles
                XSSFCellStyle cellStyle = null;
                for (int r = rMin; r < rMax+1; r++) {
                    XSSFRow row = chartDataSheet.getRow(r); if (row == null) row = chartDataSheet.createRow(r);
                    XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
                    cell.setCellValue(Double.parseDouble(String.valueOf(data[r][c]))); // in sheet
                    // remain possible cell styles
                    if (cellStyle == null) cellStyle = cell.getCellStyle();
                    cell.setCellStyle(cellStyle);
                }
                values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
                XDDFChartData.Series series1 = chartData.getSeries(0);
                series1.replaceData(category, values); // in chart

                // set new title in sheet and in chart
                String series1Title = (String)data[0][c];
                chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
                series1.setTitle(series1Title, new CellReference("sheetName", 0, c, true, true)); // in chart

                series1.plot();

                //no further series as a pie chart only has one series

                // update the table if present
                CellReference topLeft = new CellReference(chartDataSheet.getRow(0).getCell(0));
                CellReference bottomRight = new CellReference(chartDataSheet.getRow(rMax).getCell(c));
                AreaReference tableArea = chartDataWorkbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
                if (chartDataTable != null) {
                    chartDataTable.setArea(tableArea);
                }else {
                    chartDataTable = chartDataSheet.createTable(tableArea);
                }
                chartDataTable.updateHeaders();

            }
        }
    }

    /**
     * @Param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        String filePath = "C:\\Users\\cuihq\\Downloads\\图形2.pptx"; // has template pie chart
        String filePathNew = "C:\\Users\\cuihq\\Downloads\\New111.pptx";

        //柱状图数据
        Object[][] barData = new Object[][] { // new data 1 series, 6 categories
                {"User", "标题", ""}, // series title
                {"黑龙江省11", 75, 42.05}, // category 1
                {"西藏自治区22", 66.7, 42.05}, // category 1
                {"天津市33", 56.4, 42.05}, // category 2
        };

        //饼状图数据
        Object[][] pieData = new Object[][] { // new data 1 series, 6 categories
                {"User", "标题"}, // series title
                {"0-10%", 0.8502}, // category 1
                {"11-25%", 0.1048}, // category 1
                {"51-75%", 0.0084}, // category 2
                {"76-100%", 0.0366}, // category 2
        };

        //填充key为数据表格第一行第一列的值
        Map<String, Object[][]> dataMap = new HashMap<String, Object[][]>();
        dataMap.put("aa", barData);
        dataMap.put("bb", pieData);

        XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream(filePath));
        List<XSLFChart> charts = slideShow.getCharts();
        for (XSLFChart chart : charts) {
            updateChart(chart, dataMap);
        }

        FileOutputStream out = new FileOutputStream(filePathNew);
        slideShow.write(out);
        out.close();
        slideShow.close();
    }

}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

netdna518 发表于 2025-4-7 16:00
楼主这个其实很实用!很多时候确实有这个困扰。楼主能给个成品吗?还有使用说明来一个呗
liujian7769 发表于 2025-4-7 16:07
楼主能出个详细点的教程吗?想学习研究一下。谢谢。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-23 12:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表