将html网页展示的图表,下载到PPT文档内,以图片的形式展示在PPT内

使用到的工具有:

开发工具:IDEA

报表开发工具:帆软10.0.19

1、针对帆软报表[普通报表]的设置

1.1首先选中在帆软里制作好的报表,选择模板web属性

1.2.选择数据分析模式,添加一个事件设置,该事件应该设置"加载结束"

1.3.在Js脚本里写这段代码:

javascript 复制代码
var node = document.getElementsByClassName('x-table')[0].parentElement;
var message = {
	nodeId: '自定义一个别名',
	nodeInnerHTML: node.innerHTML
};
window.parent.postMessage(message, '*');

--绘制表格及如何将帆软报表展示到html不做过多赘述

给生成PPT方法添加一个按钮事件:

javascript 复制代码
$("#DOWNLOAD").on("click", function () {
        
        //给每个表格设置一个新的ID
        updateTableId();

        var timeBucket = $("#inqu_status-0-timeBucket").val();
        let orderYear = timeBucket.substring(0, 4)
        let orderMonth = timeBucket.substring(4, 6)
        let orderYearC = orderYear + '年'
        let orderMonthC = orderMonth + '月'

        var inInfo = new EiInfo();
        var promises = []; // 存储生成图片的 Promise

		//确保每个table都生成了BASE64编码
        document.querySelectorAll(".html2canvas table").forEach((v, k, p) => {
            var promise = html2canvas(document.querySelector('#' + v.id), {}).then((canvas) => {

                //根据当前id获取tr的数量。1tr假设等于11PX 从而计算出数据表格的高度
                let tableHeight = v.querySelectorAll("tr").length * 11;
                let src = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); // 将canvas转换成img的src流
                console.log(v.id, k)
                inInfo.set(v.id, src)
                inInfo.set(v.id + 'Height', tableHeight.toString())
                
            });
            promises.push(promise);
        })


		//所有报表的base64编码都在promises里后,调用后台服务
        Promise.all(promises).then(() => {
            inInfo.set("{{Year}}", `${orderYear}`)
            inInfo.set("{{Month}}", `${orderMonth}`)
            inInfo.set("{{YearC}}", `${orderYearC}`)
            inInfo.set("{{MonthC}}", `${orderMonthC}`)
            inInfo.set("{{YearMonth}}", `${orderYear}${orderMonth}`)
            inInfo.set("{{YearMonthC}}", `${orderYearC}${orderMonthC}`)

            var jsonEi = inInfo.toJSONString(true);
            console.log(jsonEi)
            post(IPLATUI.CONTEXT_PATH + "/DownloadAgree", {"temporaryId": "PM15", "jsonEi": jsonEi});

            // IPLAT.progress($("#result"), false);
        });

        IPLAT.progress($("#result"), false);

        

    })
javascript 复制代码
function updateTableId() {
    var tables = document.querySelectorAll("table[class^='x-table']");
    for (var i = 0; i < tables.length; i++) {
        tables[i].setAttribute("id", "newTableId" + i);
        num = i;
    }
}

调用后台:DownloadAgree,通过该服务,去调用具体实现方法

java 复制代码
package com.baosight.bgdsp.rp.pm;

import com.baosight.iplat4j.core.ei.EiConstant;
import com.baosight.iplat4j.core.ei.EiInfo;
import com.baosight.iplat4j.core.service.soa.XLocalManager;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class DownloadAgree extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) {
		EiInfo eiInfo = EiInfo.parseJSONString(request.getParameter("jsonEi"));
		String temporaryId = request.getParameter("temporaryId");
		if (temporaryId.equals("PM")) {
			eiInfo.set("response", response);
			eiInfo.set(EiConstant.serviceName, "R07");
			eiInfo.set(EiConstant.methodName, "exportPPT");
			eiInfo = XLocalManager.callNewTx(eiInfo);

		}if (temporaryId.equals("PM15")) {
			eiInfo.set("response", response);
			eiInfo.set(EiConstant.serviceName, "R15");
			eiInfo.set(EiConstant.methodName, "exportPPT");
			eiInfo = XLocalManager.callNewTx(eiInfo);

		}

	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		doGet(request, response);
	}
}

exportPPT方法:

java 复制代码
public EiInfo exportPPT(EiInfo inInfo) throws IOException {
        HttpServletResponse response = (HttpServletResponse) inInfo.get("response");
        // 创建一个空的演示文稿
        String url = "";
        String os = System.getProperty("os.name").toLowerCase();
        boolean isMacOS = os.contains("mac");
        if (isMacOS) {
            url = PlatApplicationContext.getProperty("项目名." + projectEnv + ".share.template.mac");
        } else {
            url = PlatApplicationContext.getProperty("项目名." + projectEnv + ".share.template");
        }
        String tempName = PlatApplicationContext.getProperty("项目名." + projectEnv + ".share.template.rppm15");
        // 读取模板文件
        //InputStream resource = new ClassPathResource("/Users/apple/Desktop/-job/2022-development/iplat4j/渠道长龄库存压降情况汇报_template.pptx").getInputStream();
        FileInputStream inputStream = new FileInputStream(url + tempName);
//        FileInputStream inputStream = new FileInputStream("E://" + tempName);
        // 根据模板,创建一个新的ppt文档
        XMLSlideShow ppt = new XMLSlideShow(inputStream);
        // 读取模板PPT
        inputStream.close();

        Map<String, String> attr = inInfo.getAttr();
        attr.put("netPrice_2", getReportsToimage());

//        List<XSLFSlide> slides = ppt.getSlides();
        // 得到每页ppt
        XSLFSlide[] slides = ppt.getSlides().toArray(new XSLFSlide[0]);
        // 遍历ppt,填充模板
        for (XSLFSlide slide : slides) {
//            List<XSLFShape> shapes = slide.getShapes();
            XSLFShape[] shapes = slide.getShapes().toArray(new XSLFShape[0]);
            // 遍历每页ppt中待填充的形状组件
            for (XSLFShape shape : shapes) {
                if (shape instanceof XSLFTextShape) {
                    // 替换文本
                    XSLFTextShape textShape = (XSLFTextShape) shape;
                    String textValue = textShape.getText();
                    String shapeName = textShape.getShapeName();
                    boolean flag = false;
                    for (String text : extractContent(textValue)) {
                        if (attr.containsKey(text)) {
                            flag = true;
                            //使用mustache语法替换文字 {{YearC}}营{{MonthC}}销预案会
                            textValue = textValue.replace(text, attr.get(text));
                        }
                    }
                    if (flag && StringUtils.isNotBlank(textValue)) {
                        List<XSLFTextParagraph> paragraphs = textShape.getTextParagraphs();
                        for (XSLFTextParagraph paragraph : paragraphs) {
                            List<XSLFTextRun> textRuns = paragraph.getTextRuns();
                            for (XSLFTextRun textRun : textRuns) {
                                textRun.setText("");
                            }
                        }
                        XSLFTextRun textRun2 = textShape.getTextParagraphs().get(0).getTextRuns().get(0);

                        textRun2.setText(textValue);
                    }
                } else if (shape instanceof XSLFPictureShape) {
                    XSLFPictureShape pictureShape = (XSLFPictureShape) shape;
                    XSLFPictureData pictureData = pictureShape.getPictureData();
                    String imageName = pictureShape.getShapeName();
                    String imageBase64 = attr.get(imageName);
                    if (imageBase64 != null) {
                        byte[] bt = Base64.getDecoder().decode(imageBase64.split(",")[1]);
                        XSLFPictureData idx = ppt.addPicture(bt, PictureData.PictureType.PNG);
                        XSLFPictureShape pic = slide.createPicture(idx);
                        Rectangle2D anchor = pictureShape.getAnchor();
                        //高度取决于数据表格的条数 宽度固定
                        pic.setAnchor(new Rectangle2D.Double(anchor.getX(), anchor.getY(), anchor.getWidth(), anchor.getHeight()));
                        pictureShape.setAnchor(new Rectangle2D.Double(10, 0, 0, 0));
                    }
                }
            }
        }
        String fileName = "PPT名字" + DateUtils.curDateTimeStr14() + ".pptx";
        // 保存PPT文件
        //设置输出文件类型为pptx文件
        response.setContentType(CONTENT_TYPE_OF_PPT);
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, CHARSET_OF_UTF8));
        response.setHeader("Pragma", URLEncoder.encode(fileName, CHARSET_OF_UTF8));
        ServletOutputStream outputStream = response.getOutputStream();
        ppt.write(outputStream);
        outputStream.flush();
        outputStream.close();
        return new EiInfo();

    }

extractContent方法:

java 复制代码
public static List<String> extractContent(String input) {
        List<String> contents = new ArrayList<>();
        int startIndex = input.indexOf("{{");
        while (startIndex != -1) {
            int endIndex = input.indexOf("}}", startIndex);
            if (endIndex != -1) {
                String content = input.substring(startIndex, endIndex + 2);
                contents.add(content);
                startIndex = input.indexOf("{{", endIndex);
            } else {
                break;
            }
        }
        return contents;
    }

getReportsToimage()方法:该方法针对的是:帆软报表的普通报表中,出现非表格报表的处理方法[即:柱状图、折线图等],通过直接访问帆软链接的方式去获取表格的base64编码。

java 复制代码
private String getReportsToimage() throws IOException {
        String reportAddress = PlatApplicationContext.getProperty("项目名." + projectEnv + ".report.address");
        // 创建HttpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        try {
            // 构造请求URL
            String apiUrl = reportAddress + "/*/netPrice_2.cpt&format=image&extype=JPG";
            // 创建HttpGet请求
            //HttpPost request = new HttpPost(apiUrl);
            System.out.println("apiUrl");
            System.out.println(apiUrl);
            HttpGet httpGet = new HttpGet(apiUrl);
            // 设置请求头部
            httpGet.addHeader("Content-Type", "text/html; charset=utf-8");
            // 发送请求并获取响应
            HttpResponse responsed = httpClient.execute(httpGet);
            // 解析响应数据
            HttpEntity entity = responsed.getEntity();
            // 检查响应是否成功
            if (responsed.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 获取Content-Type头部信息
                Header contentTypeHeader = entity.getContentType();
                String contentType = contentTypeHeader.getValue();
                // 获取输入流
                InputStream inStream = entity.getContent();
                ByteArrayOutputStream outputStream_u = new ByteArrayOutputStream();

                // 将图片裁剪为宽60px,高60px
                BufferedImage originalImage = ImageIO.read(inStream);
                BufferedImage croppedImage = originalImage.getSubimage(0, 0, 3560, 1560);

                // 将裁剪后的图片转换成字节数组
                ByteArrayOutputStream outputStream_c = new ByteArrayOutputStream();
                ImageIO.write(croppedImage, "png", outputStream_c);
                byte[] croppedImageBytes = outputStream_c.toByteArray();

                // 将图片数据编码为base64格式
                String base64Image = Base64.getEncoder().encodeToString(croppedImageBytes);
                System.out.println(base64Image);
                String responseBody = EntityUtils.toString(entity);
                // 处理响应数据
                System.out.println(responseBody);
                // 关闭输入流和输出流
                inStream.close();
                outputStream_u.close();
                return "data:image/png;base64," + base64Image;
            } else {
                System.out.println("HTTP请求失败!");
            }


        } catch (PlatException e) {

        }
        return "";
    }

最后,在设置PPT模板的时候,将模板内的图片设置为修改后的别名:newTableIdi

相关推荐
90后的晨仔8 分钟前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端
沿着路走到底38 分钟前
JS事件循环
java·前端·javascript
子春一21 小时前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶1 小时前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn2 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪2 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ2 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied3 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一23 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter
QT 小鲜肉3 小时前
【Linux命令大全】001.文件管理之file命令(实操篇)
linux·运维·前端·网络·chrome·笔记