使用到的工具有:
开发工具:IDEA
报表开发工具:帆软10.0.19
1、针对帆软报表[普通报表]的设置
1.1首先选中在帆软里制作好的报表,选择模板web属性
1.2.选择数据分析模式,添加一个事件设置,该事件应该设置“加载结束”
1.3.在Js脚本里写这段代码:
var node = document.getElementsByClassName('x-table')[0].parentElement;
var message = {
nodeId: '自定义一个别名',
nodeInnerHTML: node.innerHTML
};
window.parent.postMessage(message, '*');
–绘制表格及如何将帆软报表展示到html不做过多赘述
给生成PPT方法添加一个按钮事件:
$("#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);
})
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,通过该服务,去调用具体实现方法
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, "RPPM07");
eiInfo.set(EiConstant.methodName, "exportPPT");
eiInfo = XLocalManager.callNewTx(eiInfo);
}if (temporaryId.equals("PM15")) {
eiInfo.set("response", response);
eiInfo.set(EiConstant.serviceName, "RPPM15");
eiInfo.set(EiConstant.methodName, "exportPPT");
eiInfo = XLocalManager.callNewTx(eiInfo);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
doGet(request, response);
}
}
exportPPT方法:
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("bgdsp." + projectEnv + ".share.template.mac");
} else {
url = PlatApplicationContext.getProperty("bgdsp." + projectEnv + ".share.template");
}
String tempName = PlatApplicationContext.getProperty("bgdsp." + 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方法:
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编码。
private String getReportsToimage() throws IOException {
String reportAddress = PlatApplicationContext.getProperty("bgdsp." + projectEnv + ".report.address");
// 创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
// 构造请求URL
String apiUrl = reportAddress + "/rp/pm/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