Java生成PPT之路:一次独特的业务需求之旅

      在我的编程生涯中,首次面对一个令人挑战的任务。使用Java生成并下载PPT文件。这看似不可思议的需求让我陷入了艰难的挣扎,我相信你们也没听过这个需求吧。

        这一过程虽然曲折,但最终的成果证明了“功夫不负有心人”的真谛。在漫长的探索和实践中,最终一点一点根据自身的业务需求精心设计实现。

        编写这个博客不仅是为了分享成功的经验,更是为了让大家少走弯路,避免在类似的挑战中迷失方向。

b035e9e102a74e2a8478e1f3f96f2b79.png

cff60a06632f4fef91fcfcc1278aaaf4.png

一、导入依赖

  1. org.apache.poi:poi-ooxml:5.2.2

    处理Office Open XML格式文件。
  2. org.apache.poi:ooxml-schemas:1.4

    提供Office Open XML的验证和模式支持。
  3. org.slf4j:slf4j-api:2.0.7

    提供日志记录的简单接口,方便更换底层日志库。

<dependency>
     <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>5.2.2</version>

</dependency>

<dependency>
       <groupId>org.apache.poi</groupId>
       <artifactId>ooxml-schemas</artifactId>
       <version>1.4</version>

</dependency>

<dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <version>2.0.7</version>

</dependency>

二、导入工具包

由于工具包代码较长,我就上传到资源下载去了。小伙伴们可以前往下载:PPTUtils

6f3851d96ccc4291bdbeaefa620ec58f.png

三、准备一个PPT模板

1.ppt文本替换

a88eb2897f2742cbb3e5dbcfcc6d7d5f.png

343eb02b39974a88832780ce623c81fe.png

2.ppt图片插入

615bc064ebf942f08e7fb9e2e7c65811.png

3.ppt文本拼接成列表

a9b94716e38b4e71bc800fb46ae3723b.png

4.生成ppt表格

准备一个表头

aa28bb87cf544dd3856d0d04743abaec.png

8aab5fe65b064f8a8be43ecebfb14871.png

5.生成饼图

准备一个模板饼图

298ab0043fc24d628980273368c16bfa.png

168078f0e1684ca9b789789cea1d374f.png

6.生成雷达图

准备一个模板雷达图

e5129b7556154fbab57cb1afb58f7cbc.png

四、Doem代码示例

        这份测试代码仅供参考,是我在面对不同的业务需求时所设计的灵活解决方案。在具体应用中,你可以根据自身业务的独特性进行调整,或者将其封装成接口,以方便未来的调用和集成。

注意:根据ppt模板页码来填充数据。获取ppt页码,下标是从0开始的。

package com.pptx;

import com.utils.PPTUtil;
import com.utils.ParagraphTextStyle;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.xslf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarChart;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

public class CustomerPPTX {
    public static void main(String[] args) {
        // PPT模板路径
        String path = "D:\\BaiduNetdiskDownload\\template-wealthRisk.pptx";
        // 通过pptx工具类读取文件路径
        PPTUtil pptUtil = new PPTUtil(path);

        // 1.ppt文本替换
        getPageCustomerName(pptUtil);

        // 2.ppt图片插入
        getImagesInfo(pptUtil);

        // 3.ppt文本拼接成列表
        getCustomerDemands(pptUtil);

        // 4.生成ppt表格
        getCustomerTable(pptUtil);

        // 5.生成饼图
        getCustomerPieChart(pptUtil);

        // 6.生成雷达图
        getCustomerRadarMap(pptUtil);

        // 生成填充完数据PPT报告
        pptUtil.writePPT("D:\\BaiduNetdiskDownload\\张三财富报告.pptx");
    }

    /**
     * 获取ppt第一页,ppt文本替换
     *
     * @param pptUtil
     */
    public static void getPageCustomerName(PPTUtil pptUtil) {
        // 获取第一页,下标从0开始
        List<XSLFTextParagraph> paragraphs = pptUtil.getParagraphsFromSlide(pptUtil.getSlides().get(0));
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 通过Map定义内容
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put("name", "彭先生");
        keyMap.put("dateTime", sdf.format(new Date()));

        for (XSLFTextParagraph paragraph : paragraphs) {
            // 对该段落中所有的标签 {**} 进行替换
            pptUtil.replaceTagInParagraph(paragraph, keyMap);
        }
    }

    /**
     * 获取ppt第四页,ppt插入图片
     *
     * @param pptUtil
     */
    public static void getImagesInfo(PPTUtil pptUtil) {
        // 获取第四页pptx
        XSLFSlide slide = pptUtil.getSlides().get(3);

        // 调用getPPTX方法获取当前的PPTX对象,然后使用addPicture方法将两张图片插入到PPT中
        // XSLFPictureData是Apache POI库中表示PowerPoint中的图像对象的一个类
        XSLFPictureData xslfPictureData = null;
        try {
            // addPicture方法支持File、byte[]、InputStream
            xslfPictureData = pptUtil.getPPTX().addPicture(new File("D:\\BaiduNetdiskDownload\\jtsrwgxtzmha.png"), PictureData.PictureType.PNG);
            // 创建图片
            XSLFPictureShape picture = slide.createPicture(xslfPictureData);

            // 设置图片位置:x坐标、y坐标、宽度、高度
            picture.setAnchor(new Rectangle(50, 130, 410, 410));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取第五页ppt,诉求列表
     *
     * @param pptUtil
     */
    public static void getCustomerDemands(PPTUtil pptUtil) {
        // 获取第五页pptx
        List<XSLFTextParagraph> paragraphs = pptUtil.getParagraphsFromSlide(pptUtil.getSlides().get(4));
        String[] str = {"婚姻关系中的问题", "离婚和财产分割", "孩子的抚养和教育", "家庭财产问题"};

        StringBuffer stringBuffer = new StringBuffer();
        int sort = 0;
        for (String name : str) {
            // 拼接诉求
            sort = (sort + 1);
            stringBuffer.append(sort + "、" + name + "\n\n");
        }
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put("typeName", stringBuffer);
        for (XSLFTextParagraph paragraph : paragraphs) {
            // 对该段落中所有标签 {**} 进行替换
            pptUtil.replaceTagInParagraph(paragraph, keyMap);
        }
    }

    /**
     * 测试数据集合
     * @return list
     */
    private static List<CustomerAssets> customerAssetList(){
        List<CustomerAssets> list = new ArrayList<>();
        list.add(
                new CustomerAssets("住宅", "别墅花园", "人民币", BigDecimal.valueOf(100), "境内")
        );
        list.add(
                new CustomerAssets("住宅", "阳光小区", "人民币", BigDecimal.valueOf(200), "境内")
        );
        list.add(
                new CustomerAssets("古董","宋代花瓶","美元",BigDecimal.valueOf(300),"境内")
        );
        list.add(
                new CustomerAssets("古董","清婉瓷器","美元",BigDecimal.valueOf(90),"境内")
        );
        return list;
    }

    /**
     * 获取第六页ppt,生成表格
     *
     * @param pptUtil
     */
    public static void getCustomerTable(PPTUtil pptUtil) {
        // 从指定的幻灯片中获取表格元素
        XSLFTable xslfTable = pptUtil.getTableFromSlide(pptUtil.getSlides().get(6));
        // 全局设置样式
        ParagraphTextStyle cellStyle = new ParagraphTextStyle();
        // 设置字体大小
        cellStyle.setFontSize("8");
        // 调用测试数据集合
        List<CustomerAssets> list = customerAssetList();
        // 统计总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (CustomerAssets customerAssets : list) {
            XSLFTableRow newRow = xslfTable.addRow();
            // 资产类别
            XSLFTableCell cell1 = newRow.addCell();
            cell1.setText(customerAssets.getCategory());
            pptUtil.setCellTextStyle(cell1,cellStyle);
            // 资产名称
            XSLFTableCell cell2 = newRow.addCell();
            cell2.setText(customerAssets.getAssetsName());
            pptUtil.setCellTextStyle(cell2,cellStyle);
            // 币种
            XSLFTableCell cell3 = newRow.addCell();
            cell3.setText(customerAssets.getCurrency());
            pptUtil.setCellTextStyle(cell3,cellStyle);

            // 计算累加总金额
            totalAmount = totalAmount.add(customerAssets.getAmount());

            // 金额(万元)
            XSLFTableCell cell4 = newRow.addCell();
            cell4.setText(String.valueOf(customerAssets.getAmount()));
            pptUtil.setCellTextStyle(cell4,cellStyle);
            // 境内/境外
            XSLFTableCell cell5 = newRow.addCell();
            cell5.setText(customerAssets.getIsInland());
            pptUtil.setCellTextStyle(cell5,cellStyle);
        }
        XSLFTableRow xslfTableCells = xslfTable.addRow();
        // 初始化
        fullTableCell(xslfTableCells,4);
        // 取初始化的第1个单元格,下标为0的
        XSLFTableCell cell = xslfTableCells.getCells().get(0);
        cell.setText("合计");
        pptUtil.setCellTextStyle(cell,cellStyle);

        // 取初始化的4个单元格,下标为3的
        cell = xslfTableCells.getCells().get(3);
        cell.setText(String.valueOf(totalAmount));
        pptUtil.setCellTextStyle(cell,cellStyle);
        // 统计住宅、古董数量,可以自己封装一下方便调用
        long count1 = list.stream().filter(item -> item.getCategory().equals("住宅")).count();
        long count2 = list.stream().filter(item -> item.getCategory().equals("古董")).count();
        // 合并相同类别名称单元表格
        int mergeIndex = mergeCellsRow(xslfTable,1, (int) count1);
        mergeCellsRow(xslfTable,mergeIndex, (int) count2);
    }

    /**
     * 通用合并单元格
     * @param table
     * @param mergeIndex
     * @param size
     * @return
     */
    private static int mergeCellsRow(XSLFTable table,int mergeIndex,int size){
        if (size > 0){
            table.mergeCells(mergeIndex,mergeIndex + size -1,0,0);
            mergeIndex += size;
        }
        return mergeIndex;
    }

    /**
     * 初始化列
     * @param row
     * @param num
     */
    private static void fullTableCell(XSLFTableRow row,int num){
        for (int i = 0; i < num; i++) {
            row.addCell();
        }
    }

    /**
     * 获取第七页ppt,生成饼图
     * @param pptUtil
     */
    public static void getCustomerPieChart(PPTUtil pptUtil){
        XSLFChart chart = pptUtil.getChartFromSlide(pptUtil.getSlides().get(7));

        // 存储数据
        List<List<String>> data = new ArrayList<>();
        List<String> tempData1 = new ArrayList<>();
        List<String> tempData2 = new ArrayList<>();

        // 构造数据
        Map<String,Double> map = new HashMap<>();
        map.put("金融资产",160.00);
        map.put("实物资产",50.00);
        map.put("流动性资产",30.00);
        map.put("其他资产",10.00);

        for (Map.Entry<String, Double> entry : map.entrySet()) {
            String key = entry.getKey();
            Double value = entry.getValue();
            tempData1.add(key);
            tempData2.add(value + "");
        }
        data.add(tempData1);
        data.add(tempData2);

        CTPieChart pieChart = pptUtil.getPieChartFromChart(chart).get(0);
        pptUtil.updatePieCat(pieChart,0,data);
        // 替换缓存数据
        pptUtil.updatePieDataCache(pieChart,0,tempData2);
    }

    public static void getCustomerRadarMap(PPTUtil pptUtil){
        // 获取雷达图
        XSLFChart chart = pptUtil.getAllChartFromSlide(pptUtil.getSlides().get(9)).get(0);

        // 存储数据
        List<List<String>> data = new ArrayList<>();
        List<String> tempData1 = new ArrayList<>();
        List<String> tempData2 = new ArrayList<>();

        // 构造数据
        Map<String,Long> map = new HashMap<>();
        map.put("财富档案",160L);
        map.put("财富保全",50L);
        map.put("定向传承",30L);
        map.put("家企隔离",10L);
        map.put("财富隔离",80L);

        for (Map.Entry<String, Long> entry : map.entrySet()) {
            String key = entry.getKey();
            Long value = entry.getValue();

            tempData1.add(key);
            tempData2.add(value + "");
        }
        data.add(tempData1);
        data.add(tempData2);

        CTRadarChart radarChart = pptUtil.getRadarChartFromChart(chart).get(0);
        pptUtil.updateRadarCat(radarChart,0,data);
        // 替换缓存数据
        pptUtil.updateRadarDataCache(radarChart,0,tempData2);
    }

}

  • 21
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行舟、668

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值