在我工作时遇到了导出ppt文件的需求,这种需求还是比较冷门的,网上的资料也比较零散,而且这只是一个工具,大部分人也不想花太多精力去学这玩意,所以我将这项工作的总结写成文章,基本能满足工作中自动导出ppt的需求,希望能帮上大家,话不多说,直接上代码。
依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.15.0</version>
</dependency>
工具类
在操作ppt之前,我们先写一个导出、读取ppt的一个工具类。当然,不写也行,主要作用是美化代码
public class FileUtil {
/**
* 将给定的 XMLSlideShow 对象导出为 PPT 文件。
*
* @param xmlSlideShow 要导出的 XMLSlideShow 对象
* @param outputPath 导出的 PPT 文件路径
*/
public static void exportPPT(XMLSlideShow xmlSlideShow, String outputPath) {
try (FileOutputStream out = new FileOutputStream(outputPath)) {
xmlSlideShow.write(out);
System.out.println("文件已导出");
} catch (IOException e) {
handleException(e);
}
}
/**
* 从指定文件路径读取 PPT 文件并返回对应的 XMLSlideShow 对象。
*
* @param filePath PPT 文件的路径
* @return 代表 PPT 的 XMLSlideShow 对象,如果读取失败则返回 null
*/
public static XMLSlideShow readPPT(String filePath) {
// 使用 ClassPathResource 获取指定路径的文件资源
ClassPathResource resource = new ClassPathResource(filePath);
try (InputStream inputStream = resource.getInputStream()) {
// 从输入流中创建 XMLSlideShow 对象并返回
return new XMLSlideShow(inputStream);
} catch (IOException e) {
// 处理异常情况
handleException(e);
}
return null;
}
/**
* 处理 IOException 异常的辅助方法,打印错误信息和异常堆栈。
*
* @param e IOException 异常对象
*/
private static void handleException(IOException e) {
System.err.println("导出文件时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
生成PPT
凭空生成一张ppt,用与导出的ppt比较简单的情况
创建ppt
//创建ppt
XMLSlideShow ppt = new XMLSlideShow();
//创建一张幻灯片
XSLFSlide slide = ppt.createSlide();
创建文本框
//创建一个文本框
XSLFTextBox textBox = slide.createTextBox();
//设置文本框位置已经宽高
textBox.setAnchor(new Rectangle2D.Double(30, 20, 400, 30));
//修改文本框内容
TextRun textRun = textBox.setText("PPT生成");
textRun.setBold(true);
textRun.setFontSize(30.0);
创建表格
//创建一个5*5的表格
XSLFTable table = slide.createTable(5, 5);
TextRun run;
//遍历表格的行
for (int i = 0; i < table.getNumberOfRows(); i++) {
//遍历列
for (int j = 0; j < i + 1; j++) {
int num1 = i + 1;
int num2 = j + 1;
//获取单元格
XSLFTableCell cell = table.getCell(i, j);
//修改单元格内容
run = cell.setText(num2 + "*" + num1 + "=" + num1 * num2);
run.setFontSize(16.0);
run.setFontColor(Color.black);
run.setFontFamily("微软雅黑");
//修改边框宽度
cell.setBorderWidth(TableCell.BorderEdge.top, 1);
cell.setBorderWidth(TableCell.BorderEdge.left, 1);
cell.setBorderWidth(TableCell.BorderEdge.right, 1);
cell.setBorderWidth(TableCell.BorderEdge.bottom, 1);
//修改边框颜色
cell.setBorderColor(TableCell.BorderEdge.top, Color.black);
cell.setBorderColor(TableCell.BorderEdge.left, Color.black);
cell.setBorderColor(TableCell.BorderEdge.right, Color.black);
cell.setBorderColor(TableCell.BorderEdge.bottom, Color.black);
}
}
for (int i = 0; i < table.getNumberOfColumns(); i++) {
//修改单元格的宽高
table.setColumnWidth(i, 80.0);
table.setRowHeight(i, 30);
}
//设置表格的位置和宽高
table.setAnchor(new Rectangle2D.Double(30, 60, 400, 150));
创建柱状、折线图
//创建图表,并设置图表标题
XSLFChart chart = ppt.createChart();
chart.setTitleText("图表生成");
//准备数据
String[] xs = new String[]{"类别1", "类别2", "类别3", "类别4"};
Integer[] ys = new Integer[]{1, 2, 3, 4};
Integer[] lineYs = new Integer[]{3, 1, 4, 2};
//建立x轴,于图表的下方
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
//建立左y轴
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT);
//设置数据和y轴之间的空隙
valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
//建立柱状图的数据集
XDDFChartData data = chart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
//转成柱状图
XDDFBarChartData bar = (XDDFBarChartData) data;
//设置柱状图方向,峰状
bar.setBarDirection(BarDirection.COL);
//设置柱状图分组,标准
bar.setBarGrouping(BarGrouping.STANDARD);
//建立x轴数据
XDDFCategoryDataSource xValue = XDDFDataSourcesFactory.fromArray(xs);
//建立y轴数据
XDDFNumericalDataSource<Integer> yValue = XDDFDataSourcesFactory.fromArray(ys);
//将x轴的数据和y轴的数据建立成系列数据集
XDDFChartData.Series series = data.addSeries(xValue, yValue);
//设置系列名
series.setTitle("柱状图数据", null);
//绘制数据
chart.plot(data);
//建立右y轴
XDDFValueAxis lineValueAxis = chart.createValueAxis(AxisPosition.RIGHT);
//设置轴距,max表示在右侧拉满
lineValueAxis.setCrosses(AxisCrosses.MAX);
//关联x轴
lineValueAxis.crossAxis(categoryAxis);
//建立折现图的数据集
XDDFChartData lineData = chart.createData(ChartTypes.LINE, categoryAxis, lineValueAxis);
//建立右y轴数据
XDDFNumericalDataSource<Integer> lineYValue = XDDFDataSourcesFactory.fromArray(lineYs);
//将x轴的数据和右y轴的数据建立成系列数据集,并转型为折线数据集
XDDFLineChartData.Series lineSeries = (XDDFLineChartData.Series) lineData.addSeries(xValue, lineYValue);
// 设置系列名
lineSeries.setTitle("条形图数据", null);
//折线是否圆滑
lineSeries.setSmooth(false);
//折线点大小
lineSeries.setMarkerSize((short) 2);
//折线点样式
lineSeries.setMarkerStyle(MarkerStyle.NONE);
//绘制数据
chart.plot(lineData);
//获取数据系列标签
XDDFChartLegend orAddLegend = chart.getOrAddLegend();
//将数据系列标签置于图表下方
orAddLegend.setPosition(LegendPosition.BOTTOM);
//设置图表的位置和宽高
slide.addChart(chart, new Rectangle(500000, 3000000, 4000000, 3000000));
创建饼状图
String[] xs = new String[]{"类别1", "类别2", "类别3", "类别4"};
Integer[] ys = new Integer[]{1, 2, 3, 4};
//创建图表,并设置图表标题
XSLFChart chart = ppt.createChart();
chart.setTitleText("饼状图生成");
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT);
//建立饼状图数据集
XDDFChartData data = chart.createData(ChartTypes.DOUGHNUT, categoryAxis, valueAxis);
XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromArray(xs);
//建立饼图数据
XDDFNumericalDataSource<Integer> value = XDDFDataSourcesFactory.fromArray(ys);
//将数据添加进数据集
data.addSeries(countries, value);
chart.plot(data);
//获取饼状图
CTDLbls dLbls = chart.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).addNewDLbls();
//饼状图上 显示数据
dLbls.addNewShowVal().setVal(true);
//饼状图上 显示数据名称
dLbls.addNewShowCatName().setVal(true);
//饼状图上 显示类别名称
dLbls.addNewShowSerName().setVal(false);
//饼状图上 显示百分比
dLbls.addNewShowPercent().setVal(true);
//饼状图上 数据用字符串隔开
dLbls.setSeparator("\n");
slide.addChart(chart, new Rectangle(5000000, 3000000, 4000000, 3000000));
读取、修改PPT
读取ppt原型,并修改原ppt中的内容,用于ppt比较复杂,要素过多的情况。
这是我存放ppt原型的位置,具体位置自行更改,这里仅做演示。
//读取ppt文件
XMLSlideShow xmlSlideShow = FileUtil.readPPT("template/template.pptx");
//获取到ppt集合
List<XSLFSlide> slides = xmlSlideShow.getSlides();
//假设学生表
String[][] students = new String[][]{{"张三", "13", "男"}, {"李四", "14", "女"}};
TextRun textRun;
//遍历文件中的每页ppt
for (XSLFSlide slide : slides) {
//遍历ppt中的每一种元素:文本框、图表、表格
for (XSLFShape shape : slide.getShapes()) {
//获取元素的简单名称,判断出不同的元素,做出不同的操作
switch (shape.getClass().getSimpleName()) {
case "XSLFTextBox":
//转型成文本框
XSLFTextBox textShape = (XSLFTextBox) shape;
textRun = textShape.setText(textShape.getText().replace("type", "学生"));
textRun.setFontColor(Color.black);
textRun.setBold(true);
textRun.setFontSize(20.0);
textRun.setFontFamily("微软雅黑");
break;
case "XSLFTable":
//转型成表格
XSLFTable tableShape = (XSLFTable) shape;
//遍历行
for (int i = 1; i < tableShape.getNumberOfRows(); i++) {
//遍历列
for (int j = 0; j < tableShape.getNumberOfColumns(); j++) {
textRun = tableShape.getCell(i, j).setText(students[i - 1][j]);
textRun.setFontSize(16.0);
textRun.setFontColor(Color.red);
textRun.setFontFamily("微软雅黑");
}
}
break;
case "XSLFGraphicFrame":
//转型成图表
XSLFGraphicFrame frame = (XSLFGraphicFrame) shape;
//获取chart图
XSLFChart chart = frame.getChart();
//准备新数据
String[] xs = new String[]{"类别1", "类别2", "类别3", "类别4"};
Integer[] ys = new Integer[]{1, 2, 3, 4};
//将新数据转换成x轴和y轴数据
XDDFCategoryDataSource xddfCategoryDataSource = XDDFDataSourcesFactory.fromArray(xs);
XDDFNumericalDataSource<Integer> count = XDDFDataSourcesFactory.fromArray(ys);
List<XDDFChartData> chartSeries = chart.getChartSeries();
for (XDDFChartData chartData : chartSeries) {
//遍历图表中的系列
for (XDDFChartData.Series series : chartData.getSeries()) {
//遍历系列里数据的长度
for (int i = 0; i < series.getValuesData().getPointCount(); i++) {
//根据下标获取相应数据
System.out.print(series.getValuesData().getPointAt(i) + " ");
}
System.out.println();
}
}
for (XDDFChartData chartData : chartSeries) {
for (XDDFChartData.Series series : chartData.getSeries()) {
//修改系列数据
series.replaceData(xddfCategoryDataSource, count);
}
//将新数据绘制到图表
chart.plot(chartData);
}
break;
}
}
}
FileUtil.exportPPT(xmlSlideShow, "src/main/resources/template/template2.pptx");