openxml文书工具 Aspose 工具 word to pdf
aspose模板生成(文书工具)
动态数据
${info}
${list.id}
${list.name}
${list.address}
${list.date}
${list.danwei}
${list.number}
${list.remark}
${imgBase64}
${xw.ask}
${xw.ans}
格式
openxml
openxml
openxml
大坑:!!!!
word转xml记得转这种格式:Word XML文档(xml)
图片
存图片 先用一个照片作为占位符,然后去xml中将那一段base64 代替掉 ${imgBase64}
<pkg:part pkg:name="/word/media/image1.png" pkg:contentType="image/png">
pkg:binaryData${imgBase64}</pkg:binaryData>
</pkg:part>
但是word中保存图片文件的
图片的大小也是可以动态设置的 ${xxx}
遍历list
使用list遍历 (可以用来遍历生成表格,或者问答形式也可以)
只需要 在外面嵌套一层标签
<#list lists(参数) as list>
xxxxxx${list.id}xxxxxxxxxxxx${list.name}
</#list>
页脚
只在最后一页添加页脚、解决方式:
在指定位置加上一个文本框,然后给他设置为 上下环绕型、不允许重叠、然后把边框改为无边框即可
如果生成的pdf格式不对,或者多了一些字一些横线,就去xml中删除即可
删除这几个标签 endnotes 、、 footnotes 这两个是结尾多出来的横线
另一种情况:可能是因为页眉生成了横线,去xml中删除 head 标签
符号
一些特殊符号
https://www.jb51.cc/xml/541196.html
复选框
关于复选框 xxx = 1 就是选中 xxx = 0 就是未选中 这里直接传值就可以了 ${checked} (如果出现xml选中后是R或其他而不是显示√ 可以先在word中打钩先然后去xml给0)
w14:checkbox
<w14:checked w14:val= "${checked}"/>
<w14:checkedState w14:val="2612" w14:font="MS Gothic"/>
<w14:uncheckedState w14:val="2610" w14:font="MS Gothic"/>
</w14:checkbox>
集成SpringBoot中
相关依赖
<!--xml数据填充所需依赖 author: mao-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!--这里需要引入外部的包 maven仓库没有 存在resources下的lib包下-->
<dependency>
<groupId>com.aspose.words</groupId>
<artifactId>aspose-words-jdk16</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/aspose-words-jdk16-15.8.0.jar</systemPath>
</dependency>
Aspose Jar包下载:
蓝奏云:https://wwzv.lanzoue.com/iK7eu0t8twti
密码:1736
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
<includeSystemScope>true</includeSystemScope> <!-- 引入外部的jar包 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
true
DocToPdf
package com.nongyeservice.paper.utils;
import com.aspose.words.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.Base64;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @author mao
* @program paperUtil
* @description word转pdf核心代码
* @description aspose文书工具所需参数(新文书工具)
* @createDate 2023-03-23 16:50:05
**/
@Component
@Slf4j
public class DocToPdf {
/**
* 模板文件存放的路径(绝对路径哈)
*/
@Value("${aspose.defaultTemplatePath}")
public String baseUrl;
// private String baseUrl2 = System.getProperty("java.io.tmpdir");
@Autowired
XmlToDocx xmlToDocx;
public boolean getLicense() {
boolean result = false;
try {
// aspose需要的签名文件名称
InputStream is = DocToPdf.class.getClassLoader().getResourceAsStream("license.xml");
// InputStream is = new FileInputStream(path);
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @param params 需要填充的数据
* @param templateName 模板的文件名
* @param savePdfName 最后保存的pdf文件 可以用 文书名+文书业务id 来命名
* @return 最后生成的文书pdf文件保存路径
* @throws Exception
*/
public String doDocToPdf(Map<String, Object> params, String templateName, String savePdfName){
try {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return null;
}
// String templateUUId = UUID.randomUUID().toString();
String xml = baseUrl + savePdfName + ".xml";
String docx = baseUrl + savePdfName + ".docx";
// XmlToDocx.toDocx(documentXmlName, docTemplatePath + documentDocName, xml, baseUrl + templateUUId + ".docx", params);
boolean b = xmlToDocx.toDocx(templateName + ".xml", baseUrl + templateName + ".docx", xml, docx, params);
if(!b) {
log.error("pdf生成失败,Method:xmlToDocx.toDocx()");
return null;
}
// 新建一个空白pdf文档
String pdf = baseUrl + savePdfName + ".pdf";
File file = new File(pdf);
FileOutputStream os = new FileOutputStream(file);
// docx是将要被转化的word文档
Document doc = new Document(docx);
String osName = isWindows();
String fonts[] = null;
/**
* 适配字体文件
*/
if (osName.equals("linux")) {
// fonts = new String[]{"/usr/share/fonts/chinese/", "/usr/share/fonts/simsun/", "/usr/share/fonts/"};
fonts = new String[]{"/usr/share/fonts/win/Fonts/"};
} else if (osName.equals("mac")) {
fonts = new String[]{"/Users/fonts/chinese/", "/Users/fonts/simsun/", "/Users/fonts/black/", "/Users/fonts/wingdings/"};
} else if (osName.equals("windows")) {
fonts = new String[]{"C:/Windows/Fonts/"};
}
FontSettings.setFontsFolders(fonts, true);
// 保存pdf
// replace(params,docx,docx);
doc.save(os, SaveFormat.PDF);
if (os != null) {
os.close();
}
delete(xml, docx);//删除文件
log.info(templateName + "文书pdf已生成至:" + pdf);
return pdf;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private String isWindows() {
String osName = System.getProperties().getProperty("os.name").toUpperCase();
if (osName.indexOf("WINDOWS") != -1) {
return "windows";
} else if (osName.indexOf("MAC") != -1) {
return "mac";
} else {
return "linux";
}
}
private static String isWindowss() {
String osName = System.getProperties().getProperty("os.name").toUpperCase();
if (osName.indexOf("WINDOWS") != -1) {
return "windows";
} else if (osName.indexOf("MAC") != -1) {
return "mac";
} else {
return "linux";
}
}
/**
* 删除生成的多余文件
*/
public void delete(String xmlPath, String wordPath) {
File file = new File(xmlPath);
if (file.exists()) {
file.delete();
}
File wordFile = new File(wordPath);
if (wordFile.exists()) {
wordFile.delete();
}
}
/**
* aspose word 替换文字/图片。
* @param url 原文件路径
* @param saveurl 保存路径
* @param params {key:value,"$年份$":"2020","$签字1$":"$pic:d/qz1.jpg"} key 为要被替换的字符串,value 为替换为的字符串,替换为图片,则value为$pic:+图片路径
* 图片的传参: params.put("[$pic$]", "$pic:C:\\Users\\86153\\Pictures\\jackChen.jpg");
* @return
*/
public boolean replace(Map<String, Object> params, String url,String saveurl){
if(!getLicense()){
return false;
}
File file = new File(url);
if(!file.exists()){
return false;
}
try {
Document doc = new Document(url);
Range range = doc.getRange();
for(String key:params.keySet()){
if (params.get(key) == null) continue;
String value = params.get(key).toString();
if(value.startsWith("$pic:")){
value = value.substring(5);
key = key.replace("\\", "\\\\");
key = key.replace("$", "\\$");
key = key.replace("[", "\\[");
key = key.replace("]", "\\]");
key = key.replace("(", "\\(");
key = key.replace(")", "\\)");
key = key.replace("|", "\\|");
key = key.replace("+", "\\+");
key = key.replace("?", "\\?");
key = key.replace("*", "\\*");
range.replace( Pattern.compile(key),new ReplaceAndInsertImage(value) , false);
}else{
range.replace(key, value, true, false);
}
}
doc.save(saveurl);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* @param imgFile 文件的路径
* @return 文件转为base64 二进制流
*/
public static String fileToBase64(String imgFile) {
// 将图片文件转化为二进制流
InputStream in = null;
byte[] data = null;
// 读取图片字节数组
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 图片头
//String imghead = "data:image/jpeg;base64,";
// return Base64.encodeBase64String(data);
// mac/linux下base64生成的base64码,换行符是\n,而word原生图片里的base64换行符是\r\n,
// return Base64.getEncoder().encodeToString(data).replace("\n", "\r\n").replace("\r\r\n", "\r\n");
return Base64.getEncoder().encodeToString(data);
}
/**
* @param templateName 模板的文件名
* @param savePdfName 最后保存的pdf文件 可以用 文书名+文书业务id 来命名
* @return 最后生成的文书pdf文件保存路径
* @throws Exception
*/
public static void doDocToPdf(String templateName, String savePdfName) throws Exception {
try {
try {
// aspose需要的签名文件名称
InputStream is = DocToPdf.class.getClassLoader().getResourceAsStream("license.xml");
// InputStream is = new FileInputStream(path);
License aposeLic = new License();
aposeLic.setLicense(is);
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(savePdfName);
FileOutputStream os = new FileOutputStream(file);
// docx是将要被转化的word文档
Document doc = new Document(templateName);
String osName = isWindowss();
String fonts[] = null;
/**
* 适配字体文件
*/
if (osName.equals("linux")) {
// fonts = new String[]{"/usr/share/fonts/chinese/", "/usr/share/fonts/simsun/", "/usr/share/fonts/"};
fonts = new String[]{"/usr/share/fonts/win/Fonts/"};
} else if (osName.equals("mac")) {
fonts = new String[]{"/Users/fonts/chinese/", "/Users/fonts/simsun/", "/Users/fonts/black/", "/Users/fonts/wingdings/"};
} else if (osName.equals("windows")) {
fonts = new String[]{"C:/Windows/Fonts/"};
}
FontSettings.setFontsFolders(fonts, true);
// 保存pdf
// replace(params,docx,docx);
doc.save(os, SaveFormat.PDF);
if (os != null) {
os.close();
}
// delete(null, docx);//删除文件
log.info(templateName + "文书pdf已生成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
XmlToDocx
package com.nongyeservice.paper.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* @author mao
* @program paperUtil
* @description word动态填充数据核心类
* @createDate 2023-03-23 16:50:05
**/
@Component
@Slf4j
public class XmlToDocx {
@Autowired
XmlTplUtil xmlTplUtil;
/**
* @param xmlTemplate xml的文件名
* @param docxTemplate docx的路径和文件名
* @param xmlTemp 填充完数据的临时xml
* @param toFilePath 目标文件名
* @param map 需要动态传入的数据
* @throws IOException
*/
public boolean toDocx(String xmlTemplate, String docxTemplate, String xmlTemp, String toFilePath, Map map) {
try {
// 1.map是动态传入的数据
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w1 = new OutputStreamWriter(new FileOutputStream(xmlTemp), "utf-8");
// 2.把map中的数据动态由freemarker传给xml
xmlTplUtil.process(xmlTemplate, map, w1);
// 3.把填充完成的xml写入到docx中
XmlToDocx xtd = new XmlToDocx();
xtd.outDocx(new File(xmlTemp), docxTemplate, toFilePath);
w1.close();
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("XML to Word Failed {}" , e.getMessage());
return false;
}
}
/**
* @param documentFile 动态生成数据的docunment.xml文件
* @param docxTemplate docx的模板
* @param toFilePath 需要导出的文件路径
* @throws ZipException
* @throws IOException
*/
public void outDocx(File documentFile, String docxTemplate, String toFilePath) throws ZipException, IOException {
File docxFile = new File(docxTemplate);
ZipFile zipFile = new ZipFile(docxFile);
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));
int len = -1;
byte[] buffer = new byte[1024];
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();
InputStream is = zipFile.getInputStream(next);
// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
zipout.putNextEntry(new ZipEntry(next.toString()));
if ("word/document.xml".equals(next.toString())) {
InputStream in = new FileInputStream(documentFile);
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
} else {
while ((len = is.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
is.close();
}
}
zipout.close();
zipFile.close();
}
}
XmlTplUtil
package com.nongyeservice.paper.utils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
/**
* @author mao
* @program paperUtil
* @description word动态填充工具类
* @createDate 2023-03-23 16:50:05
**/
@Component
public class XmlTplUtil {
@Value("${aspose.defaultTemplatePath}")
public String baseUrl;
private XmlTplUtil tplm = null;
private Configuration cfg = null;
private XmlTplUtil() {
// cfg = new Configuration();
// try {
// cfg.setDirectoryForTemplateLoading(new File(baseUrl));
// } catch (Exception e) {
// e.printStackTrace();
// }
}
private Template getTemplate(String name) throws IOException {
if (tplm == null) {
// tplm = new XmlTplUtil();
cfg = new Configuration();
try {
cfg.setDirectoryForTemplateLoading(new File(baseUrl));
} catch (Exception e) {
e.printStackTrace();
}
}
Template template = cfg.getTemplate(name,"utf-8");
return template;
}
/**
* @param templatefile 模板文件
* @param param 需要填充的内容
* @param out 填充完成输出的文件
* @throws IOException
* @throws TemplateException
*/
public void process(String templatefile, Map param, Writer out) throws IOException, TemplateException {
// 获取模板
Template template = getTemplate(templatefile);
template.setOutputEncoding("utf-8");
// 合并数据
template.process(param, out);
if (out != null) {
out.close();
}
}
}
ReplaceAndInsertImage 只需要改word即可
DocToPdf中有一个replace()方法,需要用到这个类
package com.nongyeservice.paper.utils;
import com.aspose.words.*;
public class ReplaceAndInsertImage implements IReplacingCallback{
public String url;
public ReplaceAndInsertImage(String url){
this.url = url;
}
@Override
public int replacing(ReplacingArgs e) throws Exception {
//获取当前节点
Node node = e.getMatchNode();
//获取当前文档
Document document = (Document) node.getDocument();
DocumentBuilder builder = new DocumentBuilder(document);
// //将光标移动到指定节点
builder.moveTo(node);
// //插入图片
builder.insertImage(url);
return ReplaceAction.REPLACE;
}
}
license.xml aspose所需要的证书
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
本文来自博客园,作者:没有烦恼的猫猫,转载请注明原文链接:https://www.cnblogs.com/maomao777/p/17303188.html