吐槽:像这种需求半年碰不到一个 O.o
可以多去poi官网翻一下官方文档虽然很难理解但有用
所有代码基于个人习惯编写,懒得贴图了相信兄弟们的理解能力,有问题可以留言我尽量解决。
本文所有代码生成都基于pptx文件编写,可根据具体业务修改代码
1.打开模板文件
String modelPath = "classpath:static/模板.pptx";
String fileName = "生成路径/test1.pptx";
// 打开PPTX文件
InputStream fis = ResourceUtils.getURL(modelPath).openStream();
XMLSlideShow ppt = new XMLSlideShow(fis);
fis.close();
2.创建数据映射集合
// 文本数据映射表
Map<String, String> textDataMap = new HashMap<>();
textDataMap.put("${title}", "测试数据标题");
textDataMap.put("${context}", "测试数据文本");
textDataMap.put("${table_title}", "表格数据测试标题");
textDataMap.put("${table_context}", "表格数据测试文本");
textDataMap.put("textPic", "图片地址");
String[] ary = new String[3];
ary[0] = "文本框1";
ary[1] = "文本框2";
ary[2] = "文本框3";
textDataMap.put("testTextBox", "ary")
注:ppt每页内容及业务不一样,需要每页单独处理,但可以封装通用方法
private void makePPT(Integer page, XMLSlideShow ppt, Map<String, Object> textDataMap) {
//获取幻灯片对象
XSLFSlide slide = getShapes(page - 1, ppt);
switch (page) {
case 1:
slideShow1(slide, textDataMap);
break;
case 2:
slideShow2(slide, textDataMap);
break;
case 3:
slideShow3(XSLFSlide slide, XMLSlideShow ppt, Map<String, Object> textDataMap);
break;
case 4:
slideShow4(slide);
break;
case 5:
slideShow5(slide, textDataMap);
break;
case 6:
slideShow6(slide);
break;
}
}
正式调用:
//填充普通文本框
public void sideShow1(XSLFSlide slide, Map<String, Object> textDataMap) {
fillDateToPPT(slide, textDataMap);
}
//填充表格数据
public void sideShow2(XSLFSlide slide, Map<String, Object> textDataMap) {
fillTableDataToPPT(slide, textDataMap);
}
//填充图片
public void sideShow3(XSLFSlide slide, XMLSlideShow ppt, Map<String, Object> textDataMap) {
fillImageToPPT(ppt, slide, StringIsEmpty(textDataMap.get("textPic")), 0, 0, 200, 200);
}
//动态生成表格
public void sideShow4(XSLFSlide slide) {
//设置表格数据数组
String[][] ary = new String[3][3];
//给数组添加数据(根据需求可以自定义数组长度并填充数据)
ary[0][0] = "0";
ary[0][1] = "1";
ary[0][2] = "2";
ary[1][0] = "0";
ary[1][1] = "1";
ary[1][2] = "2";
ary[2][0] = "0";
ary[2][1] = "1";
ary[2][2] = "2";
createTable(ary , slide, 0, 0, 400.00, 200.00);
}
//填充文本框内容
public void sideShow5(XSLFSlide slide, Map<String, Object> textDataMap) {
PPTFontStyle pptFontStyle = new PPTFontStyle();
pptFontStyle.setFontSize(12.00);
pptFontStyle.setFontFamily("Hiragino Sans GB W6");
fillTextBoxDataToPPT(textDataMap, "testTextBox", "\n", slide, pptFontStyle);
}
//填充图表数据
public void sideShow6(XSLFSlide slide) {
List<Integer> list = new ArrayList<>();
list.add(0);
list.add(1);
list.add(2);
fillChartToPPT(list, slide);
}
封装的方法:
注:根据需求可以组合使用
1.创建XSLFSlide(幻灯片)对象
//生成ppt幻灯片对象
private XSLFSlide getShapes(Integer page, XMLSlideShow ppt) {
return ppt.getSlides().get(page);
}
2.循环获取幻灯片当页所有文本框对象找到与textDataMap集合中符合的数据填充替换
注:不能使用实例化后的textShape直接setText会失去所有样式信息
/**
* 替换文本数据到ppt
*
* @param textDataMap 文本数据
* @param slide 幻灯片对象
*/
private void fillDateToPPT(XSLFSlide slide, Map<String, Object> textDataMap) {
for (XSLFShape shape : slide.getShapes()) {
if (shape instanceof XSLFTextShape) {
XSLFTextShape textShape = (XSLFTextShape) shape;
for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
String text = textRun.getRawText();
String resultText = textDatMap.get(text);
textRun.setText(resultText);
}
}
}
}
}
3.和上一个方法类似,获取页面表格并循环每个 单元格拿到匹配数据替换
/**
* 根据集合循环填充表格数据
*
* @param textDataMap 文本数据地图
* @param slide 幻灯片对象
*/
private void fillTableDataToPPT(Map<String, Object> textDataMap, XSLFSlide slide) {
for (XSLFShape shape : slide.getShapes()) {
if (shape instanceof XSLFTable) {
XSLFTable table = (XSLFTable) shape;
for (int row = 0; row < table.getNumberOfRows(); row++) {
for (int colum = 0; colum < table.getNumberOfColumns(); colum++) {
// 遍历单元格匹配修改内容
XSLFTableCell cell = table.getCell(row, colum);
for (XSLFTextParagraph textParagraph : cell.getTextParagraphs()) {
for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
String text = textRun.getRawText();
String resultText = textDataMap.get(text)
textRun.setText(resultText);
}
}
}
}
}
}
}
4.获取当前幻灯片页中为空的文本框
注:此方法为填充文本框需用appendText不会破坏原本样式
/**
* 填充文本框带编号
*
* @param textDataMap - 文本数据
* @param key - 集合对象
* @param split - 分隔符
* @param slide - 幻灯片对象
* @param pptFontStyle - ppt字体样式
*/
private void fillTextBoxDataToPPT(Map<String, Object> textDataMap, String key, String split, XSLFSlide slide, PPTFontStyle pptFontStyle) {
// 根据换行符拆分字符串
String[] lines = StringIsEmpty(textDataMap.get(key)).split(split);
// 将拆分的字符串保存到集合中
List<String> list = new ArrayList<>();
Collections.addAll(list, lines);
for (XSLFShape shape : slide.getShapes()) {
if (shape instanceof XSLFTextBox) {
XSLFTextBox textBox = (XSLFTextBox) shape;
String text = textBox.getText();
if ("".equals(text)) {
XSLFTextRun xslfTextRun = null;
for (int i = 0; i < list.size(); i++) {
boolean isFirstItem = true;
if (i == 0) {
isFirstItem = false;
}
xslfTextRun = textBox.appendText(list.get(i), isFirstItem);
xslfTextRun.setFontSize();
xslfTextRun.setFontFamily();
}
}
}
}
}
5.设置字体样式,这里处理的是基本的几种属性
/**
* 设置字体样式
*
* @param pptFontStyle
*/
private void setFontStyle(PPTFontStyle pptFontStyle) {
if (ObjectUtils.isEmpty(pptFontStyle)) {
return;
}
XSLFTextRun textRun = null;
if (!ObjectUtils.isEmpty(pptFontStyle.getCell())) {
XSLFTextParagraph paragraph = pptFontStyle.getCell().addNewTextParagraph();
textRun = paragraph.addNewTextRun();
} else {
textRun = pptFontStyle.getTextRun();
}
if (!StringUtils.isEmpty(pptFontStyle.getText())) {
textRun.setText(pptFontStyle.getText());
}
if (!StringUtils.isEmpty(pptFontStyle.getFontSize())) {
textRun.setFontSize(pptFontStyle.getFontSize());
}
if (!StringUtils.isEmpty(pptFontStyle.getFontFamily())) {
textRun.setFontFamily(pptFontStyle.getFontFamily());
}
if (!StringUtils.isEmpty(pptFontStyle.getFontColor())) {
textRun.setFontColor(pptFontStyle.getFontColor());
}
}
实体类
public class PPTFontStyle {
private XSLFTableCell cell;
private String text;
private Double fontSize;
private String fontFamily;
private Color fontColor;
private XSLFTextRun textRun;
}
6.根据x轴、y轴将图片填充到幻灯片中
/**
* @param ppt ppt对象
* @param slide 幻灯片对象
* @param fileName 图片地址
* @param x x轴
* @param y y轴
* @param width 宽
* @param height 高
*///填充图片
private void fillImage(XMLSlideShow ppt, XSLFSlide slide, String fileName, Integer x, Integer y, Integer width, Integer height) {
if (StringUtils.isEmpty(fileName)) {
return;
}
// 填充展位图片
try {
XSLFPictureData pictureData = ppt.addPicture(Files.newInputStream(Paths.get(fileName)), PictureData.PictureType.JPEG);
XSLFPictureShape pictureShape = slide.createPicture(pictureData);
pictureShape.setAnchor(new Rectangle(x, y, width, height));
} catch (IOException e) {
e.printStackTrace();
}
}
7.填充图表数据
此方法是以折线图为基础填充,两条数据线。
注:填充完数据必须刷新图表信息,否则生成后图表关联Excel中有数据但必须编辑数据后图表才会显示数据文章来源:https://www.toymoban.com/news/detail-832737.html
/**
* 填充图表数据
*
* @param slide 幻灯片
* @param list 列表
*/
private void fillChartToPPT(List<Ineger> list, XSLFSlide slide) {
// 遍历幻灯片上的所有形状
for (XSLFShape shape : slide.getShapes()) {
if (shape instanceof XSLFGraphicFrame) {
XSLFGraphicFrame graphicFrame = (XSLFGraphicFrame) shape;
XSLFChart chart = graphicFrame.getChart();
XDDFChartData xddfChartData = chart.getChartSeries().get(0);
XDDFLineChartData xddfLineChartData = (XDDFLineChartData) xddfChartData;
if (chart != null) {
try {
//获取图表中的Excel工作簿
XSSFWorkbook workbook = chart.getWorkbook();
XSSFSheet sheet = workbook.getSheetAt(0);
for (int i = 0; i < list.size(); i++) {
//获取图表中excel对象之后根据自己需求填充数据即可
}
//对象中的数据以具体业务填充
//设置图表中的数据,从内嵌的表格sheet0中获取
XDDFDataSource<String> cat0 = XDDFDataSourcesFactory.fromStringCellRange(sheet,
new CellRangeAddress(0, 0, 0, 0));
XDDFNumericalDataSource val0 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(0, 0, 0, 0));
XDDFNumericalDataSource val1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(0, 0, 0, 0));
XDDFChartData.Series series = xddfLineChartData.getSeries(0);
series.replaceData(cat0, val0);
XDDFChartData.Series series1 = xddfLineChartData.getSeries(1);
series1.replaceData(cat0, val1);
//设置最小限值
xddfChartData.getValueAxes().get(0).setMinimum(0);
//设置单位
xddfChartData.getValueAxes().get(0).setMajorUnit(4);
//重新绘图
chart.plot(xddfLineChartData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
8.动态生成表格并赋值
注:因为表格是动态生成的所有表格是没有样式的包括字体,需手动添加字体样式或表格样式文章来源地址https://www.toymoban.com/news/detail-832737.html
/**
* 生成表格
*
* @param ary 数据
* @param slide 幻灯片对象
* @param x 表格左上角的 x 坐标
* @param y 表格左上角的 y 坐标
* @param maxHeight 总行高
* @param maxWidth 最大宽度
*/
private void createTable(String[][] ary, XSLFSlide slide, int x, int y, Double maxHeight, Double maxWidth) {
// 设置表格的行数和列数
int numRows = ary.length; // 行数
int numCols = ary[0].length; // 列数
// 设置表格位置和大小
XSLFTable table = slide.createTable(numRows, numCols);
table.setAnchor(new Rectangle(new Point(x, y)));
//设置单元格宽
double width = maxWidth / numCols; //列宽
//设置行高
double height = maxHeight / numRows ; // 行高
//根据数组生成单元格并设置样式
for (int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
// 获取单元格对象
XSLFTableCell cell = table.getCell(row, col);
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
//填充文本
XSLFTextRun xslfTextRun = cell.setText(ary[row][col]);
TableCell.BorderEdge left = TableCell.BorderEdge.left;
TableCell.BorderEdge right = TableCell.BorderEdge.right;
TableCell.BorderEdge top = TableCell.BorderEdge.top;
TableCell.BorderEdge bottom = TableCell.BorderEdge.bottom;
//设置单元格边框颜色
cell.setBorderColor(left, new Color(241, 241, 241, 255));
cell.setBorderColor(right, new Color(241, 241, 241, 255));
cell.setBorderColor(top, new Color(241, 241, 241, 255));
cell.setBorderColor(bottom, new Color(241, 241, 241, 255));
}
}
}
到了这里,关于java调用poi根据模板生成ppt的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!