什么是aspose?
Aspose是一套强大的文档处理工具,被超过80%的财富100强公司信赖,用于在应用程序中创建、编辑、导出和转换100多种文件格式。无论是PDF、Word文档、Excel表格还是PowerPoint演示文稿,Aspose都能轻松胜任。
我的需求:
word动态合同,加入用户信息、手签字、公章、骑缝章、word转pdf、隐私合同马赛克遮挡替换。
实现逻辑:
在不同位置加入书签,通过书签替换文本或者图片,根据页数分割公章,每页固定位置加入分好的公章,将word转pdf。
提前准备:
准备好一个word原始合同模板,在模板中加入书签,具体步骤:插入->书签->书签名->添加
最后记得保存哟!
代码实现:
- 核心jar包
<dependency>
<groupId>org.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>8.5.2</version>
</dependency>
<dependency>
<groupId>org.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>19.5</version>
</dependency>
- 具体代码如下,已经过测试
package zf;
import cn.hutool.core.collection.CollectionUtil;
import com.aspose.words.*;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zf.academic.constant.EmpowerConst;
import com.zf.academic.utils.SealUtil;
import com.zf.common.exception.base.BaseException;
import com.zf.common.utils.DateUtil;
import org.apache.commons.io.FileUtils;
import wordUtil.LicenseLoad;
import javax.annotation.Nullable;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhangfan
*/
public class AddSeal {
static String mosaic = "D:\\ok.png";
static byte[] base643en = Base64.getDecoder().decode(EmpowerConst.MARK_BASE64);
static Map<String, String> map = new HashMap<>();
static Map<String, String> mosaicTag = new HashMap<>();
static String userName = "展亚鹏";
static String worksName = "补单后续";
static String contractNo = "";
static Date startDate = DateUtil.getYdDate("2024-12-29");
//合同日期只有年
static boolean isOnlyYear = true;
// 是否少量遮挡开关
static boolean littleMark = true;
// static String empowerDetail = "在 经生论与经无理 发表 张三 的《 我爱说实话论及其在企业中的运用 》,出版时间 2001-02-18;";
// static String empowerPeriod = "5";
// 作者实际签字日期
// static String authorSignDate = "29";
// static String buyoutAmount = "1000";
static String year = DateUtil.getYear(startDate);
// static String month = DateUtil.getYearMm(startDate);
// static String day = DateUtil.getYearDd(startDate);
static String templatePath = "D:\\download\\1.doc";
static String empowerType = EmpowerConst.BUY_OUT;
static String signaturePath = "C:\\Users\\zf176\\Desktop\\2.jpg";
static String targetPath = "D:\\1.doc";
static String sealPath = "D:\\seal.png";
// static String empowerTimeSegment = buildTimeSegment(startDate);
// private static String buildTimeSegment(Date startDate) {
// StringBuilder builder = new StringBuilder();
// if (ObjectUtil.isNotEmpty(startDate)) {
// Date endDate = DateUtil.addDays(DateUtil.addYears(startDate, Integer.parseInt(empowerPeriod)), -1);
// builder.append("( ");
// builder.append(com.zf.common.utils.DateUtil.parseDateToStr("yyyy-MM-dd", startDate));
// builder.append(" 至 ");
// builder.append(com.zf.common.utils.DateUtil.parseDateToStr("yyyy-MM-dd", endDate));
// builder.append(" )");
// }
// return builder.toString();
// }
public static void main(String[] args) throws Exception {
Map<String, String> fileTag = buildPrivacyContractTag();
Map<String, String> mosaicTag = builderMosaicTag();
toSignature(templatePath, empowerType, sealPath, targetPath, sealPath, fileTag, mosaicTag);
wordToPdf(targetPath);
// pdfToWord("C:\\Users\\zf176\\Desktop\\2.pdf");
}
private static void wordToPdf(String wordId) throws Exception {
LicenseLoad.getLicense();
File file = new File("D:" + File.separator + userName + "-"
+ worksName
+ EmpowerConst.FILE_PDF_TYPE);
FileOutputStream out = new FileOutputStream(file);
Document doc = new Document(wordId);
doc.save(out, SaveFormat.PDF);
}
private static void pdfToWord(String wordId) throws Exception {
LicenseLoad.getLicense();
File file = new File("D:" + File.separator + userName + "-"
+ worksName
+ EmpowerConst.FILE_DOC_TYPE);
FileOutputStream out = new FileOutputStream(file);
Document doc = new Document(wordId);
doc.save(out, SaveFormat.DOC);
}
/**
* pdf完整合同
*
* @return
*/
private static Map<String, String> builderContractDate() {
map.put(EmpowerConst.YEAR, year);
// map.put("month", month);
// map.put("day", day);
// map.put(EmpowerConst.YEAR2, year);
// map.put("month2", month);
// map.put("day2", day);
// map.put(EmpowerConst.YEAR3, year);
// map.put("month3", month);
// map.put("day3", day);
// map.put(EmpowerConst.YEAR4, year);
// map.put("month4", month);
// map.put("day4", day);
return map;
}
/**
* 隐私合同
*
* @return
*/
private static Map<String, String> buildPrivacyContractTag() {
// map.put(EmpowerConst.OWNER, userName);
// map.put(EmpowerConst.OWNER1, userName);
// map.put(EmpowerConst.OWNER2, userName);
if (isOnlyYear) {
map.put(EmpowerConst.CONTRACT_NO, contractNo);
map.put(EmpowerConst.YEAR, year);
map.put(EmpowerConst.YEAR2, year);
map.put(EmpowerConst.YEAR3, year);
map.put(EmpowerConst.YEAR4, year);
}
// map.put(EmpowerConst.CONTRACT_NO, contractNo);
// map.put(EmpowerConst.PRODUCTION, worksName);
// map.put(EmpowerConst.PRODUCTION2, worksName);
// 构建少量遮挡参数
// if (littleMark) {
// map.put(EmpowerConst.MONTH, month);
// map.put(EmpowerConst.MONTH2, month);
// map.put(EmpowerConst.MONTH3, month);
// map.put(EmpowerConst.MONTH4, month);
// map.put(EmpowerConst.DAY, day);
// map.put(EmpowerConst.DAY2, day);
// map.put(EmpowerConst.DAY3, day);
// map.put(EmpowerConst.DAY4, day);
// map.put(EmpowerConst.BUY_OUT_AMOUNT, buyoutAmount);
// map.put(EmpowerConst.BUY_OUT_AMOUNT2, MoneySwitch.toChinese(buyoutAmount));
// map.put(EmpowerConst.EMPOWER_PERIOD, empowerPeriod);
// map.put(EmpowerConst.EMPOWER_PERIOD1, empowerTimeSegment);
// map.put(EmpowerConst.PRODUCTION_DETAIL, empowerDetail);
// }
return map;
}
private static Map<String, String> builderMosaicTag() {
mosaicTag.put(EmpowerConst.OWNER, userName);
mosaicTag.put(EmpowerConst.OWNER1, userName);
mosaicTag.put(EmpowerConst.OWNER2, userName);
mosaicTag.put(EmpowerConst.PRODUCTION, worksName);
mosaicTag.put(EmpowerConst.PRODUCTION2, worksName);
return mosaicTag;
}
public static void toSignature(String wordId, String empowerType, String picture, String fullWordFile, String sealPath, Map<String, String> tag, Map<String, String> wordTag) throws Exception {
if (StringUtils.isBlank(wordId)) {
throw new BaseException("数据错误!授权后的doc文件ID为空");
}
File destFile = new File(fullWordFile);
File file = new File(wordId);
String newPath = destFile.getPath();
FileUtils.copyFile(file, destFile);
LicenseLoad.getLicense();
Document doc = new Document(newPath);
DocumentBuilder builder = new DocumentBuilder(doc);
BookmarkCollection bookmarks = doc.getRange().getBookmarks();
if (CollectionUtil.isNotEmpty(tag)) {
for (Map.Entry<String, String> entry : tag.entrySet()) {
String key = entry.getKey();
if (builder.moveToBookmark(key)) {
builder.write(entry.getValue());
bookmarks.remove(key);
}
}
}
// 单个字换打码图
if (CollectionUtil.isNotEmpty(wordTag)) {
for (Map.Entry<String, String> entry : wordTag.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (builder.moveToBookmark(key) && StringUtils.isNotBlank(value)) {
int mosaticSize = value.length() - 1;
String surname = value.substring(0, 1);
builder.write(surname);
for (int j = 0; j < mosaticSize; j++) {
builder.insertImage(base643en, 18, 15);
}
bookmarks.remove(key);
}
}
int length = userName.length();
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_A)) {
for (int i = 0; i < length; i++) {
builder.insertImage(Base64.getDecoder().decode(EmpowerConst.SIGN_BASE64), 80D, 100D).setWrapType(WrapType.INLINE);
}
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_A);
}
//附件 二次写入签字区域
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_B)) {
for (int i = 0; i < length; i++) {
builder.insertImage(Base64.getDecoder().decode(EmpowerConst.SIGN_BASE64), 80D, 100D).setWrapType(WrapType.INLINE);
}
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_B);
}
} else {
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_A)) {
Shape shape = builder.insertImage(picture, 245D, 130D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_A);
}
//附件 二次写入签字区域
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_B)) {
Shape shape = builder.insertImage(picture, 245D, 130D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_B);
}
}
if (builder.moveToBookmark(EmpowerConst.PUBLIC_SEAL)) {
Shape shape = builder.insertImage(sealPath, 150D, 150D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.PUBLIC_SEAL);
}
doc.save(newPath);
buildCrossPageSeal(newPath, sealPath);
// if(EmpowerConst.PRO_RATA.equals(empowerType)){
//// SealUtil.addNewLine(newPath);
// }
File filePath = new File(picture);
// if (filePath.exists()) {
// filePath.delete();
// }
}
public static void goMosaicSignature(String wordId, String empowerType, String picture, String fullWordFile, String sealPath, @Nullable Map<String, String> tag, Map<String, String> wordTag) throws Exception {
if (StringUtils.isBlank(wordId)) {
throw new BaseException("数据错误!授权后的doc文件ID为空");
}
File destFile = new File(fullWordFile);
File file = new File(wordId);
String newPath = destFile.getPath();
FileUtils.copyFile(file, destFile);
LicenseLoad.getLicense();
Document doc = new Document(newPath);
DocumentBuilder builder = new DocumentBuilder(doc);
BookmarkCollection bookmarks = doc.getRange().getBookmarks();
if (CollectionUtil.isNotEmpty(tag)) {
for (Map.Entry<String, String> entry : tag.entrySet()) {
String key = entry.getKey();
if (builder.moveToBookmark(key)) {
builder.write(entry.getValue());
bookmarks.remove(key);
}
}
}
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_A)) {
Shape shape = builder.insertImage(picture, 245D, 130D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_A);
}
if (builder.moveToBookmark(EmpowerConst.PUBLIC_SEAL)) {
Shape shape = builder.insertImage(sealPath, 150D, 150D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.PUBLIC_SEAL);
}
//附件 二次写入签字区域
if (builder.moveToBookmark(EmpowerConst.SIGNATURE_OF_PARTY_B)) {
Shape shape = builder.insertImage(picture, 245D, 130D);
shape.setWrapType(WrapType.NONE);
bookmarks.remove(EmpowerConst.SIGNATURE_OF_PARTY_B);
}
doc.save(newPath);
buildCrossPageSeal(newPath, sealPath);
// if(EmpowerConst.PRO_RATA.equals(empowerType)){
//// SealUtil.addNewLine(newPath);
// }
File filePath = new File(picture);
// if (filePath.exists()) {
// filePath.delete();
// }
}
/**
* 加入骑缝章
*
* @param filePath 文件路径
* @param sealPath 工章路径
*/
public static void buildCrossPageSeal(String filePath, String sealPath) throws Exception {
if (StringUtils.isBlank(filePath) || StringUtils.isBlank(sealPath)) {
throw new BaseException("合同加入骑缝章发生错误,参数为空");
}
Document doc;
float y;
int num;
DocumentBuilder builder;
LayoutCollector layoutCollector;
LicenseLoad.getLicense();
InputStream inputStream = Files.newInputStream(Paths.get(filePath));
doc = new Document(inputStream);
builder = new DocumentBuilder(doc);
num = doc.getPageCount();
layoutCollector = new LayoutCollector(doc);
doc.updatePageLayout();
float widthInPoints = doc.getPageInfo(0).getWidthInPoints();
float heightInPoints = doc.getPageInfo(0).getHeightInPoints();
y = heightInPoints / 2 - 100;
int sealCross = 150 / num;
float left = widthInPoints - sealCross;
BufferedImage[] images = SealUtil.splitSeal(sealPath, 1, num);
NodeCollection runs = doc.getChildNodes(NodeType.PARAGRAPH, true);
int tempPage = 0;
for (int i = 0; i < runs.getCount(); i++) {
Node r = runs.get(i);
int numPage = layoutCollector.getStartPageIndex(r);
if (numPage != tempPage) {
builder.moveTo(r);
builder.insertImage(images[numPage - 1], 1, left, 1, y, sealCross - 2, 150, WrapType.NONE);
doc.save(filePath);
}
tempPage = numPage;
}
}
}
官方文档:
除上述外Aspose.Words还提供
- 邮件合并:邮件合并是Aspose.Words的核心功能之一,可以在Word模板中定义邮件合并区域,使用Java代码填充数据源,大批量生成自定义Word文件。相关API主要有:MailMerge、MergeField 等。
- 比较文档:Aspose.Words提供比较两个文档差异的功能,可以生成详细的HTML格式比较报告。使用Document.compare()方法传入要比较的两个Document对象即可。
- 搜索与替换:Aspose.Words提供丰富的搜索与替换功能,可以按内容、格式、样式等条件搜索与替换,使用FindReplaceOptions设置选项,调用Document.getRange().replace()方法替换。
- 文档保护:可以使用ProtectionType枚举设置文档保护类型(如只读、注释等),并用Document.protect()方法进行保护。使用密码可以解除保护。
- 文档版本控制:可以使用Document.startTrackRevisions()开启修订,修改后调用Document.stopTrackRevisions()停止修订。之后就可以使用比较方法比较不同版本的修订情况。
- PDF & HTML导入导出:可以将Word文档导入/导出为PDF或HTML格式。
- 文档编辑限制:可以限制文档的编辑、打印等功能。使用EditRestriction类型进行设置。
- 自定义XML:Aspose.Words提供丰富的自定义XML功能,可以定义XML元素与属性,进行导入导出及操作。
- 文档优化:提供清理未使用的样式、列出文档中的所有样式、检测潜在问题等优化功能。
- 文档转换:可以方便地在Word文档与其他格式(PDF, HTML等)之间转换
- 插件:Aspose还提供Excel公式、PDF阅读器、图片处理等插件,可插入到Word文档中使用。