excel转pdf 方案 java处理
本帖最后由 二十瞬 于 2022-11-21 22:35 编辑最近项目需要用表单渲染,同时后面要涉及到pdf签章。研究了一下各个实现方案。
最终采用 excel使用 阿里的easyexcel 模板渲染成xlsx. 然后采用aspose的免费版生成pdf并移除水印,aspose的这个效果非常好 。
其余open office的列多一点的表格可能列就换行了。e-iceblue那个太抠了。只能转前3页。
代码大多都是从网上借鉴整合的。
模板如下
aspose生成pdf并移除水印
<repositories>
<repository>
<id>AsposeJavaAPI</id>
<name>Aspose Java API</name>
<url>https://releases.aspose.com/java/repo/</url>
</repository>
</repositories>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>22.11</version>
</dependency>
生成带水印的pdf
public static void aposePdf() throws Exception {
Workbook workbook = new Workbook("d://aaaa.xlsx");
workbook.save("Output.pdf");
}
移除水印
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
使用
Workbook workbook = new Workbook("d://aaaa.xlsx");
workbook.save("the.pdf");
replaceStr("the.pdf","Output1.pdf","Evaluation Only. Created with Aspose.Cells for Java.Copyright 2003 - 2022 Aspose Pty Ltd.");
/**
* 替换指定文字为白色的遮罩层
* @param src 需要被转换的带全路径文件名
* @param dest 转换之后pdf的带全路径文件名
* @param replaceStr 指定转换的文字(水印的文字)
*/
public static void replaceStr(String src, String dest, String replaceStr) {
try {
List<String> resu = new ArrayList<>();
PdfReader reader = new PdfReader(src);
//获取指定文字的坐标(就是上一步生成的pdf水印)
getKeyWords(reader,replaceStr,resu);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
for (int i = 1; i <= resu.size(); i++) {
String xy = resu.get(i - 1);
PdfContentByte canvas = stamper.getOverContent(i);
canvas.saveState();
//设置颜色
canvas.setColorFill(BaseColor.WHITE);
//解析坐标
double x = Double.valueOf(xy.split("--"));
double y = Double.valueOf(xy.split("--")) - 10;
//后面2个参数分别是宽高
canvas.rectangle(x, y, 450, 100);
canvas.fill();
canvas.restoreState();
}
stamper.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取指定文字的坐标
*/
public static void getKeyWords(PdfReader pdfReader, String replaceStr,List<String> resu ) {
try {
int pageNum = pdfReader.getNumberOfPages();
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(
pdfReader);
for (int i = 1; i <= pageNum; i++) {
pdfReaderContentParser.processContent(i, new RenderListener() {
@Override
public void renderText(TextRenderInfo textRenderInfo) {
String text = textRenderInfo.getText(); // 整页内容
if (null != text && text.contains(replaceStr)) {
Rectangle2D.Float boundingRectange = textRenderInfo
.getBaseline().getBoundingRectange();
String xy = boundingRectange.x + "--" + boundingRectange.y;
resu.add(xy);
}
}
@Override
public void renderImage(ImageRenderInfo arg0) {
}
@Override
public void endTextBlock() {
}
@Override
public void beginTextBlock() {
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
要是在前端直接想以网页方式展现出来。 不使用插件pdf.js的话。 可以采用poi 的xls 转html。不过不支持xlsx格式
使用POI把Word Excel转为HTML
1:PoiUtil.java
package com.wzh.poi;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.poi.hssf.converter.ExcelToHtmlConverter;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.w3c.dom.Document;
/**@date 2015-3-16 17:22:05
* @author y
* @desc
*/
*
public class PoiUtil {
/**@param fileName
* @param outputFile
* @throws FileNotFoundException
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerConfigurationException
* @throws TransformerException
*/
* Excel 转为 HTML
*
public static void excelToHtml(String fileName, String outputFile)
throws FileNotFoundException, IOException, ParserConfigurationException,
TransformerConfigurationException, TransformerException {
InputStream is = new FileInputStream(fileName);
HSSFWorkbook excelBook = new HSSFWorkbook(is);
ExcelToHtmlConverter ethc = new ExcelToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
ethc.setOutputColumnHeaders(false);
ethc.setOutputRowNumbers(false);
ethc.processWorkbook(excelBook);
Document htmlDocument = ethc.getDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
out.close();
String htmlStr = new String(out.toByteArray());
htmlStr = htmlStr.replace("<h2>Sheet1</h2>", "")
.replace("<h2>Sheet2</h2>", "")
.replace("<h2>Sheet3</h2>", "")
.replace("<h2>Sheet4</h2>", "")
.replace("<h2>Sheet5</h2>", "");
writeFile(htmlStr, outputFile);
}
/**@param fileName
* @param outputFile
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerException
*/
* Word 转为 HTML
*
*
public static void wordToHtml(String fileName, String outputFile) throws
IOException, ParserConfigurationException, TransformerException {
HWPFDocument wordDoc = new HWPFDocument(new FileInputStream(fileName));
WordToHtmlConverter wthc = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
wthc.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] bytes, PictureType pt, String string, float f, float f1) {
return string;
}
});
wthc.processDocument(wordDoc);
List<Picture> pics = wordDoc.getPicturesTable().getAllPictures();
if (null != pics && pics.size() > 0) {
for (Picture pic : pics) {
pic.writeImageContent(new FileOutputStream(pic.suggestFullFileName()));
}
}
Document htmlDocument = wthc.getDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
out.close();
String htmlStr = new String(out.toByteArray());
writeFile(htmlStr, outputFile);
}
public static void writeFile(String content, String path) {
FileOutputStream fos = null;
BufferedWriter bw = null;
File file = new File(path);
try {
fos = new FileOutputStream(file);
bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
bw.write(content);
} catch (FileNotFoundException ex) {
Logger.getLogger(PoiUtil.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(PoiUtil.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PoiUtil.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (null != bw) {
bw.close();
}
if (null != fos) {
fos.close();
}
} catch (IOException ex) {
Logger.getLogger(PoiUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
2.Test.java
import com.wzh.poi.PoiUtil;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
/**@author y
*/
*
*
public class Test {
/**@param args the command line arguments
*/
*
public static void main(String[] args) {
try {
PoiUtil.excelToHtml("t2.xls", "test.html");
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (ParserConfigurationException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
另外也可以直接使用生产的html转pdf.但是效果和格式没有aspose的那么好
html 转pdf
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>4.0.4</version>
</dependency>
public static void htmlToPdf(String htmlStr, OutputStream outputStream){ ConverterProperties converterProperties = new ConverterProperties(); FontProvider fontProvider= new FontProvider(); fontProvider.addDirectory("C:\\Windows\\Fonts"); fontProvider.addStandardPdfFonts(); fontProvider.addSystemFonts(); //for fallback converterProperties.setFontProvider(fontProvider); HtmlConverter.convertToPdf(htmlStr, outputStream, converterProperties); }
本帖最后由 myxiaowang 于 2022-11-22 10:26 编辑
看看我的
http://119.3.238.152:9001/mybucket/2022-11-22FBJNSGr4lXT1wcfNNq92R.png
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.apache.logging.log4j.util.Strings;
import org.xxx.xxx.base.pojo.PdfData;
import org.xxx.xxx.base.pojo.PdfInfo;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Objects;
/**
* @AuThor coderW
* @version 1.0.0
* @Description
* @createTime 2022年11月14日 15:44:00
*/
public class PdfUtil {
/**
* todo demo
* 创建一个pdf文档的样例
* @Param outPath 输出路径
* @param content 内容集合
* @param titPath 字体
* @param pdfInfo pdf属性
* @throws IOException io
*/
public static void createPdf(String outPath, ArrayList<PdfData> content, String titPath, PdfInfo pdfInfo) throws IOException {
Document document = standA4Document();
try (OutputStream outputStream = Files.newOutputStream(Paths.get(outPath))) {
// 加载文档流
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
// 判断文档是否需要属性
if(Objects.nonNull(pdfInfo)){
setBaseInfo(document, pdfInfo.getAuthor(), pdfInfo.getKeywords(), pdfInfo.getProduct(), pdfInfo.getLink(), pdfInfo.getTitle(), pdfInfo.getSubject());
}
// 打开文档
document.open();
// 创建字体
Font font = createFont(titPath);
createFontStyle(font, 12f,null);
// 创建表这里的数据模拟 从excel读取出来的数据
ArrayList<Object> header = new ArrayList<>();
header.add(" ");
header.add("月总辐射量(kWh/m2)");
header.add("月散射辐射(kWh/m2)");
header.add("月直射辐射(kWh/m2)");
header.add("平均气温(℃)");
ArrayList<ArrayList<Object>> tableBody = new ArrayList<>();
for (int i = 1; i <= 12; i++) {
ArrayList<Object> d1 = new ArrayList<>();
d1.add(i+"月");
d1.add(RandomUtil.randomDouble());
d1.add(RandomUtil.randomDouble());
d1.add(RandomUtil.randomDouble());
d1.add(RandomUtil.randomDouble());
tableBody.add(d1);
}
createTable(document,header,tableBody,font,getBaseColor(244,244,244),new float[]{50,150,150,150,110},PageSize.A4,30,30);
// 关闭文档
document.close();
// 关闭流
writer.close();
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 创建一个表格
* @param header 表头数据
* @param body 表数据
* @param font 字体
* @param headerBaseColor 表头背景颜色 可以为空
* @param colWidth 列宽度
* @param pageSize 表适配大小
* @param headerCellHeight 表头行高
* @param bodyCellHeight 表数据行高
* @throws DocumentException do
*/
public static void createTable(Document document,ArrayList<Object> header,
ArrayList<ArrayList<Object>> body,Font font,
BaseColor headerBaseColor,
float[] colWidth,
Rectangle pageSize,
float headerCellHeight,
float bodyCellHeight
) throws DocumentException {
PdfPTable pdfPTable = pdfPtable(header.size());
pdfPTable.setHorizontalAlignment(Element.ALIGN_CENTER);
if(colWidth != null){
pdfPTable.setWidthPercentage(colWidth,pageSize);
}
// 创建表头
if(CollectionUtil.isNotEmpty(header)){
createTableData(pdfPTable,header,font,headerBaseColor,headerCellHeight);
}
// 填充数据
if(CollectionUtil.isNotEmpty(body)){
for (ArrayList<Object> list : body) {
if(CollectionUtil.isNotEmpty(list)){
createTableData(pdfPTable,list,font,null,bodyCellHeight);
}
}
}
document.add(pdfPTable);
}
/**
* 添加表头
* @param table 表
* @param data 单元格数据
* @param font 字体
* @param cellHeight 行高
* @param baseColor 表头的背景颜色 如果不是表头可以不填写
*/
public static void createTableData(PdfPTable table,ArrayList<Object> data,Font font,BaseColor baseColor,float cellHeight) {
int numberOfColumns = table.getNumberOfColumns();
for (int i = 0; i < numberOfColumns; i++){
// 添加一个单元格
PdfPCell cell = new PdfPCell();
Paragraph elements = new Paragraph(data.get(i).toString(), font);
cell.addElement(elements);
// 设置行高
cell.setLeading(3,3);
// 设置字体居中
cell.setPaddingLeft(10);
cell.setFixedHeight(cellHeight);
cell.setVerticalAlignment(Element.ALIGN_CENTER);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
// 设置背景边框
if(baseColor != null){
cell.setBackgroundColor(baseColor);
}
table.addCell(cell);
}
}
/**
* 创建一个表格
* @param columns 列数
* @Return PdfPTable
*/
public static PdfPTable pdfPtable(int columns){
return new PdfPTable(columns);
}
/**
* 普通文本创建段落
* @param document pdf
* @param data 需要填充的文本
* @param font 字体
* @throws DocumentException do
*/
public static void fillText(Document document,String data,Font font) throws DocumentException {
Paragraph paragraph = createParagraph(font, data);
document.add(paragraph);
}
/**
* 基于对象的填充段落
* @param document 文档
* @param info 数据
* @param titPath 字体路径
* @param font 字体
* @throws DocumentException do
* @throws IOException io
*/
public static void fillText(Document document,PdfData info,String titPath,Font font) throws DocumentException, IOException {
if(Strings.isNotBlank(info.getTitle())){
Font titledFont = createTitledFont(titPath, 18f, Font.BOLD);
Paragraph p1 =createParagraph(titledFont,info.getTitle());
p1.setAlignment(Element.ALIGN_LEFT);
document.add(p1);
}
fillText(document,info.getData(),font);
}
/**
* 添加一张图片
* @param image 图片对象
* @param document 文档
* @throws DocumentException do
*/
public static void addImage(Image image, Document document) throws DocumentException {
setImage(image,100,60);
document.add(image);
}
/**
* 支持像素缩放 查看Image对象
* 按百分比缩放图片 对称缩放
* @param image 图片对象
* @param scalePercent 百分比
*/
public static void setImage(Image image,float scalePercent){
image.scalePercent(scalePercent);
image.setAlignment(Image.MIDDLE);
}
/**
* 百分比缩放
* @param image 图片对象
* @param scalePercentX 长缩放
* @param scalePercentY 宽缩放
*/
public static void setImage(Image image,float scalePercentX,float scalePercentY){
image.scalePercent(scalePercentX,scalePercentY);
image.setAlignment(Image.MIDDLE);
}
/**
* 创建一张图片
* @param path 路径
* @return Image
* @throws BadElementException ex
* @throws IOException io
*/
public static Image getImage(String path) throws BadElementException, IOException {
return Image.getInstance(path);
}
/**
* 写出数据
* @param content 数据
*/
public static void fillText( PdfContentByte content){
content.fill();
content.sanityCheck();
}
/**
* 创建字体
* @return Font
*/
public static Font createFont(){
return new Font();
}
/**
* 给字体设置样式
* @param font 字体
* @param fontSize 字体大小
* @param baseColor 字体颜色
* @param style 样式 Font.BOLD 等方法
*/
public static void createFontStyle(Font font,Float fontSize,BaseColor baseColor,Integer... style){
if(Objects.isNull(font)){
return;
}
font.setSize(fontSize);
if(baseColor != null){
font.setColor(baseColor);
}
if(style != null){
for (Integer integer : style) {
font.setStyle(integer);
}
}
}
/**
* 创建字体颜色
* @param red 红
* @param green 绿
* @param blue 蓝
* @return BaseColor
*/
public static BaseColor getBaseColor(Integer red,Integer green,Integer blue){
return new BaseColor(red,green,blue);
}
/**
* 创建指定字体的font
* @param fontPath font路径
* @return Font
* @throws DocumentException 文档异常
* @throws IOException io异常
*/
public static Font createFont(String fontPath) throws DocumentException, IOException {
BaseFont font = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
return new Font(font);
}
/**
* 添加标题大小的字体
* @param fontPath 字体路径
* @param size 大小
* @param style 样式
* @return Font
* @throws DocumentException dx
* @throws IOException io
*
* tip: createTitleFont(path,22,Font.BOLD)
*/
public static Font createTitledFont(String fontPath,float size,int style) throws DocumentException, IOException {
BaseFont font = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
return new Font(font, size, style);
}
/**
* 创建一个段落
* @param font 字体
* @param content 内容
* @return Paragraph
* @throws DocumentException 文档异常
*/
public static Paragraph createParagraph(Font font,String content) throws DocumentException {
Paragraph elements = new Paragraph(content, font);
// 设置首行缩进
elements.setFirstLineIndent(20f);
return elements;
}
/**
* 创建一个指定大小宽度的页面
* @param width 宽度
* @param height 高度
* @return Rectangle
*/
public static Rectangle createRectangle(Integer width,Integer height){
return new Rectangle(width,height);
}
/**
* 创建一个pdf
* @param pageSize pdf页大小对象
* @param marginLeft 距离左边边距
* @param marginRight 距离右边边距
* @param marginTop 距离上边边距
* @param marginBottom 距离下边边距
* @return Document
*/
public static Document createDocument(Rectangle pageSize,int marginLeft,int marginRight,int marginTop,int marginBottom){
return new Document(pageSize,marginLeft,marginRight,marginTop,marginBottom);
}
/**
* 创建一个标准的pdf
* // todo PageSize 内置很多样式大小
*
* @return Document
*/
public static Document standA4Document(){
return new Document(PageSize.A4);
}
/**
* pdf相关信息
*
* @param document pdf
* @param author 作者
* @param keywords 关键字
* @param product产品
* @param link 官网连接
* @param title 标题
* @param subject主题
*/
public static void setBaseInfo(Document document, String author, String keywords, String product, String link, String title, String subject){
document.addAuthor(author);
document.addCreationDate();
document.addKeywords(keywords);
Meta producer = new Meta("producer", product);
try {
document.add(producer);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
document.addCreator(link);
document.addTitle(title);
document.addSubject(subject);
}
}
其他代码没用贴完 但是做个java都能看出来 iawyxkdn8 发表于 2022-11-22 08:09
你干的活,跟我怎么差不多,一堆的文件+一 堆的章
前段时间接手公司电子证照产品 那才是麻烦。 三十多个证照的模板那个模板还是 word 编写。转xml 去里面写freemaker 标签。 然后渲染出doc再转pdf..... 在任何地方,都有人在创新。{:1_921:} 学习了,楼主厉害 已收藏,慢慢学习 慢慢学习,感谢分享 lou zhu wei wu 正好在学习这个,收藏了 下次一定用,留着有用 学习学习,感谢楼主分享! 你干的活,跟我怎么差不多,一堆的文件+一 堆的章