首页 分享 POI生成动态模板PPT报告

POI生成动态模板PPT报告

来源:花匠小妙招 时间:2025-01-12 00:06

最新推荐文章于 2024-11-12 22:23:20 发布

java劝退师 于 2018-10-24 20:23:08 发布

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

Note

最新更新了github,有问题欢迎评论。感谢评论+讨论的同在奋斗的人

需求:(项目又一反人类需求)不同的样式模板,替换数据生成新的PPT

花了我4天时间,转载请注明作者感谢~

Github

地址:https://github.com/ithuhui/hui-core-autoreport
分支:master
位置:com.hui.core.report.ReportApp

Core

效果图:

在这里插入图片描述

在这里插入图片描述

读取模板,样式不变只替换其中数据POI操作数据封装

Code

接口设计

流程: 读取模板 -》 构建每一页的PPT(图表,表格,文本框) -》把传入的数据参数进行替换 -》保存生成新的PPT

在这里插入图片描述

接口实现

/** * <b><code>PowerPointGenerator</code></b> * <p/> * Description: * <p/> * <b>Creation Time:</b> 2018/10/23 21:15. * * @author Hu Weihui */ public class PowerPointGenerator { private PowerPointGenerator() { } /** * PPT构造方法 * * @param templateFilePath * @param destFilePath * @param slideDataMap * @throws IOException */ public static void generatorPowerPoint(String templateFilePath, String destFilePath, Map<Integer, SlideData> slideDataMap) throws IOException, NoSuchChartTypeException { XMLSlideShow ppt = readPowerPoint(templateFilePath); List<XSLFSlide> slideList = ppt.getSlides(); for (XSLFSlide slide : slideList) { int slidePage = slide.getSlideNumber(); SlideData slideData = slideDataMap.get(slidePage); generatorSlide(slide, slideData); } savePowerPoint(ppt, destFilePath); } /** * 保存ppt到指定路径 * * @param ppt * @param outputFilePath * @throws IOException */ private static void savePowerPoint(XMLSlideShow ppt, String outputFilePath) throws IOException { try ( FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath); ) { ppt.write(fileOutputStream); ppt.close(); } } /** * 读取模板库PPT * * @param inputFilePath * @return * @throws IOException */ private static XMLSlideShow readPowerPoint(String inputFilePath) throws IOException { FileInputStream fileInputStream = new FileInputStream(inputFilePath); XMLSlideShow ppt = new XMLSlideShow(fileInputStream); return ppt; } /** * 替换每一页数据 * * @param slide * @param slideData * @throws IOException */ private static void generatorSlide(XSLFSlide slide, SlideData slideData) throws IOException, NoSuchChartTypeException { List<POIXMLDocumentPart> partList = slide.getRelations(); int chartNum = 0; for (POIXMLDocumentPart part : partList) { if (part instanceof XSLFChart) { List<SeriesData> seriesDataList = slideData.getChartDataList().get(chartNum).getSeriesDataList(); generatorChart((XSLFChart) part, seriesDataList); chartNum++; } } List<XSLFShape> shapeList = slide.getShapes(); for (XSLFShape shape : shapeList) { Map<String, String> textMap = slideData.getTextMap(); List<TableData> tableDataList = slideData.getTableDataList(); int tableNum = 0; //判断文本框 if (shape instanceof XSLFTextShape) { generatorTextBox((XSLFTextShape) shape, textMap); } //判断表格 if (shape instanceof XSLFTable) { List<TableRowData> tableRowDataList = tableDataList.get(tableNum).getTableRowDataList(); generatorTable((XSLFTable) shape, tableRowDataList); } } } /** * 构造图表 * * @param chart * @param seriesDataList * @throws IOException */ private static void generatorChart(XSLFChart chart, List<SeriesData> seriesDataList) throws IOException, NoSuchChartTypeException { if (seriesDataList.size() < 1) { return; } GraphUtils.refreshGraph(chart, seriesDataList); } /** * 构造文本 * * @param textShape * @param textMap */ private static void generatorTextBox(XSLFTextShape textShape, Map<String, String> textMap) { List<XSLFTextParagraph> textParagraphList = textShape.getTextParagraphs(); for (XSLFTextParagraph textParagraph : textParagraphList) { String text = textParagraph.getText(); String regex = "${.*?}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(text); List<String> keys = new ArrayList<>(); while (matcher.find()) { keys.add(matcher.group()); } for (String key : keys) { String textKey = key.substring(2, key.length() - 1); text = text.replace(key, textMap.get(textKey) == null ? " " : textMap.get(textKey)); } List<XSLFTextRun> textRuns = textParagraph.getTextRuns(); for (XSLFTextRun textRun : textRuns) { String textStr = textRun.getRawText() == null ? "" : textRun.getRawText(); textRun.setText(""); } if (textRuns.size() > 0) { textRuns.get(0).setText(text); } } } /** * 构造表格 * * @param table * @param tableDataList */ private static void generatorTable(XSLFTable table, List<TableRowData> tableDataList) { List<XSLFTableRow> rows = table.getRows(); int rowSize = rows.size() - 1; for (int i = 0; i < tableDataList.size(); i++) { if (i < rowSize) { List<XSLFTableCell> cells = rows.get(i + 1).getCells(); for (int j = 0; j < tableDataList.get(i).getDataList().size(); j++) { String s = tableDataList.get(i).getDataList().get(j); cells.get(j).setText(s); } } else { table.addRow(); XSLFTableRow row = rows.get(i + 1); for (int j = 0; j < tableDataList.get(i).getDataList().size(); j++) { String s = tableDataList.get(i).getDataList().get(j); row.addCell().setText(s); } } } table.getCell(0, 0).setText(""); }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179

图表的构造工具

图表构造工具没时间重构,只有个demo,这里只挑core代码进行记录。

判断图表类型

参考别人,判断图表的类型真的是反人类,但是暂时还没找到其他的方法。

String chartType = ""; CTPlotArea plotArea = part.getCTChart().getPlotArea(); if (plotArea.getLineChartList().size() != 0) { chartType = "lie"; } if (plotArea.getBarChartList().size() != 0) { chartType = "bar"; } if (plotArea.getLineChartList().size() != 0 && plotArea.getBarChartList().size() != 0) { chartType = "barAndlie"; } if (plotArea.getPieChartList().size() != 0) { chartType = "pie"; } if (chartType == null) { throw new NoSuchChartTypeException("no Such Chart Type be found"); } else { return chartType; }

12345678910111213141516171819202122 刷新图表

// 创建一个excel Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet(); // 先生成excel表格,在刷新函数中往excel表格中添加数据 for (int i = 0; i <= seriesDataList.get(0).getCategoryDataList() .size(); i++) { sheet.createRow(i); for (int j = 0; j <= seriesDataList.size(); j++) { sheet.getRow(i).createCell(j); } } CTChart ctChart = chart.getCTChart(); // 获取图表区域 CTPlotArea plotArea = ctChart.getPlotArea(); // 获取柱状图表 CTBarChart barChart = plotArea.getBarChartArray(0); // 获取图表的系列 for (int i = 0; i < barChart.getSerList().size(); i++) { CTSerTx barTx = barChart.getSerArray(i).getTx(); barTx.getStrRef().getStrCache().getPtArray(0) .setV(seriesDataList.get(i).getSeriesName()); sheet.getRow(0).getCell(i + 1) .setCellValue(seriesDataList.get(0).getSeriesName()); String barTitleRef = new CellReference(sheet.getSheetName(), 0, i + 1, true, true).formatAsString(); barTx.getStrRef().setF(barTitleRef); CTAxDataSource barCat = barChart.getSerArray(i).getCat(); CTNumDataSource barVal = barChart.getSerArray(i).getVal(); refreshGraphContent(sheet, barCat, barVal, seriesDataList.get(i), i + 1); } } // 更新嵌入的workbook POIXMLDocumentPart xlsPart = chart.getRelations().get(0); OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); wb.write(xlsOut);刷新图表数据

1234567891011121314151617181920212223242526272829303132333435363738394041 刷新图表Excel内容

/** * 刷新图表内容. * * @param sheet * @param cat * @param val * @param seriesData * @param cellNum * @author Hu Weihui */ private static void refreshGraphContent(final Sheet sheet, final CTAxDataSource cat, final CTNumDataSource val, final SeriesData seriesData, final int cellNum) { // 获取类别 CTStrData strData = cat.getStrRef().getStrCache(); // 获取系列对应的值 CTNumData numData = val.getNumRef().getNumCache(); // strData.set strData.setPtArray((CTStrVal[]) null); // unset old axis text numData.setPtArray((CTNumVal[]) null); // unset old values // set model long idx = 0; int rownum = 1; for (CategoryData categoryData : seriesData.getCategoryDataList()) { CTNumVal numVal = numData.addNewPt(); numVal.setIdx(idx); numVal.setV(categoryData.getVal() + ""); CTStrVal sVal = strData.addNewPt(); sVal.setIdx(idx); sVal.setV(categoryData.getCategoryName()); idx++; rownum++; } // 设置excel的值 sheet.getRow(0).getCell(cellNum).setCellValue(seriesData.getSeriesName()); for (int i = 1; i < sheet.getLastRowNum() + 1; i++) { sheet.getRow(i).getCell(cellNum).setCellValue( seriesData.getCategoryDataList().get(i - 1).getVal()); } // 设置excel的标题 for (int i = 0; i < seriesData.getCategoryDataList().size(); i++) { String serName = seriesData.getCategoryDataList().get(i).getCategoryName(); sheet.getRow(i + 1).getCell(0).setCellValue(serName); } numData.getPtCount().setVal(idx); strData.getPtCount().setVal(idx); String numDataRange = new CellRangeAddress(1, rownum - 1, cellNum, cellNum).formatAsString(sheet.getSheetName(), true); val.getNumRef().setF(numDataRange); String axisDataRange = new CellRangeAddress(1, rownum - 1, 0, 0) .formatAsString(sheet.getSheetName(), true); cat.getStrRef().setF(axisDataRange); }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 封装能提供一页PPT的数据实体

/** * <b><code>SlideData</code></b> * <p/> * Description:一页PPT的内容 * <p/> * <b>Creation Time:</b> 2018/10/23 19:34. * * @author huweihui */ public class SlideData implements Serializable { private static final long serialVersionUID = -69655131782023929L; private Integer slidePage;//页码 private List<TableData> tableDataList;//表格数据(有可能有多个表格) private List<ChartData> chartDataList;//图表数据(有可能有多个图表) private Map<String,String> textMap;//文本框里面文本数据 } /** * <b><code>SeriesData</code></b> * <p/> * Description:图表的系列(不能想象的话可以PPT新建一个柱状图就看到了) * <p/> * <b>Creation Time:</b> 2018/10/19 11:37. * * @author huweihui */ public class SeriesData { // 系列名称 private String seriesName; // 所有类别的值 private List<CategoryData> categoryDataList = new ArrayList<>(); } /** * <b><code>SeriesData</code></b> * <p/> * Description:图表的类别 * <p/> * <b>Creation Time:</b> 2018/10/19 11:37. * * @author huweihui */ public class CategoryData { // 类别名称 private String categoryName; // 类别值 private double Val; } /** * <b><code>ChartData</code></b> * <p/> * Description:图表数据 * <p/> * <b>Creation Time:</b> 2018/10/24 11:46. * * @author huweihui */ public class ChartData { private List<SeriesData> seriesDataList; } /** * <b><code>TableData</code></b> * <p/> * Description:表格一行的数据 * <p/> * <b>Creation Time:</b> 2018/10/23 11:34. * * @author huweihui */ public class TableRowData { private List<String> dataList = new ArrayList<>(); } /** * <b><code>TableData</code></b> * <p/> * Description:表格数据 * <p/> * <b>Creation Time:</b> 2018/10/24 14:19. * * @author huweihui */ public class TableData { private List<TableRowData> tableRowDataList; }

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697

总结

1.代码并不全,但核心思想和核心代码都出来了,以后整理放到github再更新链接。

2.这里是PPT的模板构造工具,业务上传过来的数据解析成SlideData这个类。就可以根据模板生成PPT

3.数据获取的配置也是个考验。我们是把数据和查找的SQL放到PPT模板读取并执行SQL后替换数据到PPT

4.读取Config 更为复杂,但项目的业务不一样。往后更新一个DEMO可跑单元测试

相关知识

健康美容养生花茶饮品宣传动态PPT模板
小清新花朵主题工作汇报动态PPT模板免费下载
薰衣草PPT模板下载
垃圾分类PPT模板幼儿园中小学生垃圾处理绿色低碳环保护环境课件 (6).pptx
清新绿色的花草毕业纪念册ppt模板下载
粉色花好月圆主题婚礼婚庆通用ppt模板下载
宿舍收纳整理PPT模板下载
文艺小清新淡雅简约创意毕业论文答辩开题报告课题汇报PPT模板下载
外国节日PPT模板
花卉风格ppt

网址: POI生成动态模板PPT报告 https://www.huajiangbk.com/newsview1546227.html

所属分类:花卉
上一篇: 质量报表图片生成工具phanto
下一篇: 给忙碌的人的图表设计工具。

推荐分享