本帖最后由 zhouen 于 2025-4-7 14:42 编辑
Java替换PPT模板饼图或者柱状图数据解决方案
日常工作中遇到了一个很小众的问题,就是目前给定的PPT模板中存在饼状图和柱状图(测试用的是wps中的图表),
需要根据后台数据改变PPT中的饼状体和柱状图的数据。尝试和很多种方法,记录下最终的解决方案:
PPT中的图形如下(主要是替换数据,实现图形根据数据变化):
饼状图:
柱状图:
具体实现方式如下如下:
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 {
if (chart.getRelations().isEmpty()) {
return;
}
XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
XSSFSheet chartDataSheet = chartDataWorkbook.getSheetAt(0);
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) {
XDDFChartData chartData = chart.getChartSeries().get(0);
if (chartData.getSeriesCount() == 1) {
int rMin = 1;
int rMax = data.length - 1;
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]);
}
category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
c = 1;
XDDFNumericalDataSource<Double> values = null;
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])));
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);
String series1Title = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title);
series1.setTitle(series1Title, new CellReference("sheetName", 0, c, true, true));
series1.plot();
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();
}
}
}
public static void main(String[] args) throws Exception {
String filePath = "C:\\Users\\cuihq\\Downloads\\图形2.pptx";
String filePathNew = "C:\\Users\\cuihq\\Downloads\\New111.pptx";
Object[][] barData = new Object[][] {
{"User", "标题", ""},
{"黑龙江省11", 75, 42.05},
{"西藏自治区22", 66.7, 42.05},
{"天津市33", 56.4, 42.05},
};
Object[][] pieData = new Object[][] {
{"User", "标题"},
{"0-10%", 0.8502},
{"11-25%", 0.1048},
{"51-75%", 0.0084},
{"76-100%", 0.0366},
};
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();
}
}
|