91名师指路-头部
91名师指路

java将excel转为图片

由于某些原因,现在不支持支付宝支付,如需要购买源码请加博主微信进行购买,微信号:13248254750

一:背景介绍

最近公司有个变态的需求,要求生成excel后发送邮件,并且将sheet2的excel进行截图,然后作为邮件的正文进行发送。


经过网上各种资料查询,一共找到了如下的几种方案:

1)spire.xls,这个有免费版的也有开源版的。但有个缺点,截图的时候对于公式设置的背景色无法展示出来,所以我放弃了(商业版和免费版都有这个bug已经返回给他们的技术人员)

官网:https://www.e-iceblue.cn/

免费版:

<!-- https://mvnrepository.com/artifact/e-iceblue/spire.xls.free -->
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls.free</artifactId>
<version>5.3.0</version>
</dependency>

商业版:

<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
<version>15.1.0</version>
</dependency>


和他们技术人员进行了沟通确定是bug,无法满足我的需求


2)aspose,这个截图能满足我的需求,但是他是商业版的收费贵,如果不购买序列化,则在截图的时候再左上角会有一行小的文字,网上也有破解的办法,使用代码将其去掉,但是作为公司来说,是存在法律风险的,公司不让用。放弃

官网:https://metrics.aspose.com/


3)使用python脚本,我的excel列很多大概30多列,这个脚本转为pdf后会分多页展示,没找到好的方法让所有的列在一行展示。放弃

import subprocess

# 定义输入和输出文件路径
input_file = '/home/zhang/1.xlsx'
output_file = '/home/zhang/1.pdf'

# 使用unoconv进行文档转换
subprocess.run(['/usr/local/bin/unoconv', '-f', 'pdf', input_file])

print(f"文件已转换为:{output_file}")


4)使用命令行工具

将excel转为pdf(还是上面的问题,excel列太多导致pdf分页展示)

/usr/local/bin/unoconv -f pdf /home/xiaobo.zhang/1.xlsx /home/xiaobo.zhang/1.pdf


将excel转为图片(还是上面的问题,excel列太多导致图片展示不完全)

/usr/bin/libreoffice24.8 --invisible --convert-to png /home/xiaobo.zhang/2.xlsx


5)使用jodconverter-local 将excel转为jpg,excel列太多导致图片展示不完全,解决方法:打开excel > 页面布局,设置纸张方向为横向,然后调整纸张大小直到能覆盖excel中所有的列。然后我们发现在转为图片时就能展示excel中所有的图片了,但是还有个问题,excel设置纸张大小的时候不能直接指定高度和宽度为多少cm,这样导致会有很多空白的区域,在转为图片时,图片就很小而且很模糊,解决方法,将excel先转为pdf,然后使用pdfbox 对pdf进行裁剪,将空白区域去掉,然后在在裁剪的pdf转为图片,这样就完美解决了excel转为图片的问题。


5.1)引入jodconverter-local和pdfbox

<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.8</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.33</version>
</dependency>


5.2)excel转pdf,对pdf进行裁剪的代码

public String excelToImage(String excelPath, String imgName){
log.info("开始图片转换");
String imagePath=imagesUploadPath+"/"+imgName;
String pdfPath=imagesUploadPath+"/"+System.currentTimeMillis()+".pdf";
String pdfCutPath=imagesUploadPath+"/"+System.currentTimeMillis()+"_cut.pdf";
OfficeManager officeManager=LocalOfficeManager.builder().install()
.portNumbers(2002)
.officeHome(officeHome)
.build();
try {
officeManager.start();
log.info("imagePath {}", imagePath);
File inputFile=new File(excelPath);
File outputFile=new File(pdfPath);
PagesSelectorFilter selectorFilter=new PagesSelectorFilter(2);

// 执行转换
LocalConverter.builder()
.filterChain(selectorFilter)
.officeManager(officeManager)
.build()
.convert(inputFile)
.to(outputFile)
.execute();
log.info("pdf转换完成");

// 裁剪
float cropX = 0; // 裁剪区域的X坐标(相对于页面左下角)
float cropY = 550; // 裁剪区域的Y坐标(相对于页面左下角)
float cropWidth = 1350; // 裁剪区域的宽度
float cropHeight = 760; // 裁剪区域的高度

PDDocument document = PDDocument.load(new File(pdfPath));
PDPage firstPage = document.getPage(0); // 获取第一页
PDRectangle cropBox = new PDRectangle();
cropBox.setLowerLeftX(cropX);
cropBox.setLowerLeftY(cropY);
cropBox.setUpperRightX(cropX + cropWidth);
cropBox.setUpperRightY(cropY + cropHeight);
firstPage.setCropBox(cropBox); // 设置裁剪区域
document.save(pdfCutPath); // 保存修改后的文件
log.info("pdf裁剪完成");

// 转换图片
pdfCut(pdfCutPath, imagePath);
log.info("图片转换完成");
} catch (OfficeException e) {
e.printStackTrace();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
officeManager.stop();
} catch (OfficeException e) {
e.printStackTrace();
}
}

return imagePath;
}


5.3)pdf转图片代码

public void pdfCut(String pdfPath, String imagePath){
try {
File file=new File(pdfPath);
PDDocument document=PDDocument.load(file);
// 创建PDF渲染器
PDFRenderer renderer=new PDFRenderer(document);
// 选择要转换的页面(例如,页面1)
int page=0; // PDF页面是从0开始的索引
BufferedImage image=renderer.renderImageWithDPI(page, 300); // 可以调整DPI以获得不同质量的图片

// 保存图片到文件
ImageIO.write(image, "jpg", new File(imagePath));
// 关闭文档
document.close();
} catch (IOException e) {
e.printStackTrace();
}
}


二:还有个需要注意的地方,发送邮件,我们是给outlook发送邮件,如果采用html的方式发送邮件,即一个图片链接(如http://91mszl.com/logo.png),但是由于公司的邮箱设置不允许邮件中带有链接,所以我们采用cid的方式来引入图片,这里需要注意的是图片的后缀必须是.jpg,如果是其他格式,图片不会在outlook邮件正文中展示出来,具体什么原因我暂时还不清楚,我这里采用的是hutool工具来发送的邮件

List<String> toList = xx
List<String> ccList = xx
List<String> bccList = xx
File file = new File(excelName);
File imgFile = new File(imgPath);
String yyyymmdd=DateUtils.currentYYYYMMDD();
String subject="这是标题";
String content="<html><body style=\"font-family:'Microsoft YaHei'\">各位主管,下午好!<br>以下是截止到" + yyyymmdd + " xxxxx,校准信息。<br>详细明细可通过查看<br><img src='cid:"+imgName+"'></body></html>";
MailUtil.send(toList, ccList, bccList, subject, content, true, file, imgFile);




2025-01-23 18:49:08     阅读(41)

名师出品,必属精品    https://www.91mszl.com

联系博主    
用户登录遮罩层
x

账号登录

91名师指路-底部