背景:为解决客户动态生成word证书问题
- 制作word模板
- 给模板插入书签;插入书签使用在线编辑word,插入(我使用的是pageoffice,满足需求,但速度慢,稳定性差,经常在客户电脑上报错,而且书签必须以"PO_" 开头)
- 对书签分类;因为书签在word上是不重复的,这里用 PO_***_01 PO_***_02 来表示同一个值,使用aspose只需要获取前后两个_之间值,与书签值一致,即可实现 复用
- 普通书签:直接赋值
- 图片书签:要四个参数①书签名称②图片全路径③宽度④高度
- 表格书签:这里书签 放在了表格的第一个输入位置,例如:PO_用户信息_01
使用的aspose版本
<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>
具体代码如下,已经过测试
import com.aspose.words.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
/**
* @ClassName AsposeWordUtil
* @Description 批量生成文档
* @Date: 2023/6/15 19:50
* @Version 1.0
**/
public class AsposeWordUtil {
static final String bookmarkNameStr = "bookmarkName";
static final String imgAllPathStr = "imgAllPath";
static final String imgWidthStr = "width";
static final String imgHeightStr = "height";
// 1.文档拼接,附页拼接在主页最后面即可
// 2.插入图片,到对应书签位置①生成证书二维码②获取书签图片
// 3.普通书签赋值,<PO_书签名_>相同的要赋同一个值
// 4.表格赋值
// 注意:本文中 书签都以<PO_> 开头,以_01,_02 结尾,中间部分 _***_ 为书签名称
public static void main(String[] args) throws Exception {
// Document dstDoc = new Document(getAllPath( "\\message\\wordfile\\主页文档.doc"));
Document srcDoc = new Document(getAllPath("\\message\\wordfile\\附页文档.docx"));
// Document srcDoc = new Document(getAllPath( "\\message\\wordfile\\主页文档.doc"));
//
// List<Document> documentList = new ArrayList<>();
// //书签插入图片
// List<Map<String,Object>> imageMaps = new ArrayList<>();
// imageMaps.add(getImgConfigMap("检验员","E:\\work\\message\\wordfile\\sign1.jpg",100,120));
// imageMaps.add(getImgConfigMap("核验员","E:\\work\\message\\wordfile\\sign2.png",100,120));
// insertImages(dstDoc,imageMaps,true);
// //书签赋值
// Map<String,String> textMap = new HashMap<>();
// textMap.put("编号","464646546555");
// textMap.put("名称","手机");
// insertText(dstDoc,textMap,true);
// //表格赋值
// List<List<String>> data = new ArrayList<>();
// for (int i = 0; i < 5; i++) {
// List<String> aa = new ArrayList<>();
// for (int i1 = 0; i1 < 3; i1++) {
// aa.add("第"+(i+1)+"行"+"第"+(i1+1)+"列");
// }
// data.add(aa);
// }
// Map<String,List<List<String>>> cc = new HashMap<>();
// cc.put("用户信息",data);
// insertTableText(dstDoc,cc);
// documentList.add(dstDoc);
//
// //书签插入图片
// List<Map<String,Object>> imageMaps1 = new ArrayList<>();
// imageMaps1.add(getImgConfigMap("检验员","E:\\work\\message\\wordfile\\sign3.jpg",100,120));
// imageMaps1.add(getImgConfigMap("核验员","E:\\work\\message\\wordfile\\sign4.png",100,120));
// insertImages(srcDoc,imageMaps1,true);
// //书签赋值
// Map<String,String> textMap1 = new HashMap<>();
// textMap1.put("编号","hahahhahah");
// textMap1.put("名称","笔记本");
// insertText(srcDoc,textMap1,true);
// //表格赋值
// List<List<String>> data1 = new ArrayList<>();
// for (int i = 0; i < 5; i++) {
// List<String> aa = new ArrayList<>();
// for (int i1 = 0; i1 < 3; i1++) {
// aa.add("第"+(i+1)+"行加"+"第"+(i1+1)+"列");
// }
// data1.add(aa);
// }
// Map<String,List<List<String>>> cc1 = new HashMap<>();
// cc1.put("用户信息",data1);
// insertTableText(srcDoc,cc1);
//
// documentList.add(srcDoc);
// Document a = AddDocs2Doc(documentList);
// a.save(getAllPath("\\message\\wordfile\\TestFile Out.docx"));
// a.cleanup();
// System.out.println("Documents appended successfully.");
}
/**
* @Author
* @Description 生成一个word
* @Date 2023/6/19 14:11
* @param textMap 文本数据
* @param imageMaps 签名数据
* @param tableMap 表格数据
* @param dstDoc 主页
* @param srcDoc 附页
* @param targetFilePath 目标路径
* @return void
**/
public static void createWord(Map<String,String> textMap,List<Map<String,Object>> imageMaps,Map<String,List<List<String>>> tableMap
,Document dstDoc,Document srcDoc,String targetFilePath) throws Exception {
if(EmptyUtil.isNotEmpty(textMap)){
insertText(dstDoc,textMap,true);
if(null != srcDoc){
insertText(srcDoc,textMap,true);
}
}
if(EmptyUtil.isNotEmpty(imageMaps)){
insertImages(dstDoc,imageMaps,true);
if(null != srcDoc){
insertImages(srcDoc,imageMaps,true);
}
}
if(EmptyUtil.isNotEmpty(tableMap)){
insertTableText(dstDoc,tableMap);
if(null != srcDoc){
insertTableText(srcDoc,tableMap);
}
}
if(null != srcDoc){
List<Document> documentList = new ArrayList<>();
documentList.add(dstDoc);
documentList.add(srcDoc);
Document a = AddDocs2Doc(documentList);
a.save(getAllPath(targetFilePath));
a.cleanup();
}else{
dstDoc.save(getAllPath(targetFilePath));
dstDoc.cleanup();
}
}
/**
* @Author
* @Description 表格赋值
* @Date 2023/6/16 17:22
* @param doc 文档对象
* @param data <表格书签名称,二维集合>,数据需要提前生成,按行赋值
* @return void
**/
private static void insertTableText(Document doc,Map<String,List<List<String>>> data){
for (String s : data.keySet()) {
Bookmark bk = doc.getRange().getBookmarks().get(s);
if(EmptyUtil.isNotEmpty(bk)){
Table table = (Table) bk.getBookmarkStart().getParentNode().getParentNode().getParentNode().getParentNode();
Row lastRow = table.getLastRow();
for(int i = 0; i < data.get(s).size(); i++){
Row newRow = (Row) lastRow.deepClone(true);
CellCollection cells = newRow.getCells();
List<String> cellText = data.get(s).get(i);
for(int j = 0; j < cellText.size(); j++){
if(j < cells.getCount()){
Cell cell = cells.get(j);
cell.getCellFormat().setVerticalMerge(CellMerge.NONE);
// cell.getCellFormat().setVerticalAlignment(CellVerticalAlignment.CENTER);
Paragraph p = new Paragraph(doc);
p.getParagraphFormat().setAlignment(ParagraphAlignment.CENTER); //水平居中
p.appendChild(new Run(doc,cellText.get(j)));
cell.getParagraphs().clear();
cell.appendChild(p);
}
}
table.insertBefore(newRow,lastRow);
}
lastRow.remove();
}
}
}
/**
* @Author
* @Description 封装map
* @Date 2023/6/15 20:31
* @param bookmarkName 书签名称
* @param imgAllPath 图片全路径
* @param width 宽度
* @param height 高度
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
public static Map<String,Object> getImgConfigMap(String bookmarkName, String imgAllPath, double width, double height){
Map<String,Object> map = new HashMap<>(4);
map.put(bookmarkNameStr,bookmarkName);
map.put(imgAllPathStr,imgAllPath);
map.put(imgWidthStr,width);
map.put(imgHeightStr,height);
return map;
}
/**
* @Author
* @Description 书签赋值
* @Date 2023/6/15 21:07
* @param doc word文档对象
* @param textMap 普通书签赋值<书签名称,赋值>
* @param isRepeat 是否复用
* @return void
**/
private static void insertText(Document doc,Map<String,String> textMap,Boolean isRepeat) throws Exception {
for(Bookmark bm:doc.getRange().getBookmarks()){
for (String labelName : textMap.keySet()) {
if(getBookmarkName(bm.getName(),isRepeat).contains(labelName)){
//替换内容
bm.setText(textMap.get(labelName));
}
}
}
}
/**
* @Author
* @Description
* @Date 2023/6/15 20:23
* @param doc 文档对象
* @param imageMaps 图片配置合集信息
* @return void
**/
public static void insertImages(Document doc, List<Map<String,Object>> imageMaps,Boolean isRepeat) throws Exception {
DocumentBuilder builder = new DocumentBuilder(doc);
//不为空表示可操作
if(EmptyUtil.isNotEmpty(imageMaps)) {
for (Bookmark bookmark : doc.getRange().getBookmarks()) {
for (Map<String, Object> imageMap : imageMaps) {
if (getBookmarkName(bookmark.getName(),isRepeat).contains((String) imageMap.get(bookmarkNameStr))) {
//替换内容为空
bookmark.setText("");
File img = new File(getAllPath((String) imageMap.get(imgAllPathStr)));
if(img.exists()){
byte[] decode = imgToByte(img);
builder.moveToBookmark(bookmark.getName());
if (EmptyUtil.isEmpty(imageMap.get(imgWidthStr))) {
Shape shape = builder.insertImage(decode);
shape.setBehindText(false);
} else {
builder.insertImage(decode, RelativeHorizontalPosition.PAGE, 0,
RelativeVerticalPosition.PAGE, 0
, Double.parseDouble(imageMap.get(imgWidthStr).toString()) * 0.7587
, Double.parseDouble(imageMap.get(imgHeightStr).toString()) * 0.737589
, WrapType.INLINE);
}
}
}
}
}
}
}
/**
* @Author
* @Description 判断是否去除PO
* @Date 2023/6/15 20:41
* @param bookmarkName 原书签名称
* @param isRepeat 是否多书签复用
* @return java.lang.String
**/
private static String getBookmarkName(String bookmarkName, Boolean isRepeat){
int count_ = bookmarkName.split("_").length-1;
if(count_ >1){
return isRepeat?bookmarkName.replace("PO","").substring(0,bookmarkName.lastIndexOf("_")-1):bookmarkName;
}else{
return isRepeat?bookmarkName.replace("PO",""):bookmarkName;
}
}
/**
* 拼接多个word模板
* @param documentList
* @throws Exception
*/
public static Document AddDocs2Doc(List<Document> documentList){
if (documentList.size()>0){
// 取第一个文档作为主文档,将其与的文档合并到它这里
Document docAll = documentList.get(0);
for (int i = 1; i < documentList.size(); i++) {
Document doc = documentList.get(i);
//CONTINUOUS:分节;length:分页
doc.getFirstSection().getPageSetup().setSectionStart(SectionStart.CONTINUOUS);
docAll.appendDocument(doc, ImportFormatMode.KEEP_DIFFERENT_STYLES);
}
return docAll;
}
return null;
}
/**
* @Author
* @Description 图片转base64
* @Date 2021/3/11 17:55
* @param img
* @return byte[]
**/
public static byte[] imgToByte(File img){
byte[] bytes = new byte[0];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
BufferedImage bi = ImageIO.read(img);
ImageIO.write(bi, "png", baos);
bytes = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
/**
* @Author
* @Description 获取对应系统的全目录
* @Date 2023/6/15 19:59
* @param filePath
* @return java.lang.String
**/
public static String getAllPath(String filePath) throws IOException {
String osName = System.getProperties().getProperty("os.name");
if (osName.equals("Linux")) {
//linux 文件路径
String uploadDir = new File("").getCanonicalPath() + "File" + filePath;
String wordPath = uploadDir.replaceAll("/", "//");
return wordPath;
} else {
//win 文件路径
String uploadDir = new File("").getCanonicalPath() + "File" + filePath;
String wordPath = uploadDir.replaceAll("/", Matcher.quoteReplacement(File.separator));
return wordPath;
}
}
/**
* @Author
* @Description 目标文件夹不存在就创建
* @Date 2023/6/20 17:10
* @param folderPath
* @return void
**/
public static void createFolder(String folderPath) throws IOException {
folderPath = getAllPath(folderPath);
File folder = new File(folderPath);
//文件夹路径不存在
if (!folder.exists() && !folder.isDirectory()) {
folder.mkdirs();
}
}
}
这块是其他资料找到的,在书签处插入文档(未经测试)
/**
* @Author
* @Description 向书签后插入文档
* @Date 2023/6/28 16:56
* @param mainDoc 主文档
* @param tobeInserted 拼接的文档
* @param bookmark 书签
* @return com.aspose.words.Document
**/
private static Document insertDocumentAfterBookMark(Document mainDoc, Document tobeInserted, String bookmark)throws Exception {
if (mainDoc == null) {
return null;
} else if (tobeInserted == null) {
return mainDoc;
} else {
//构建新文档
DocumentBuilder mainDocBuilder = new DocumentBuilder(mainDoc);
if (bookmark != null && bookmark.length() > 0) {
//获取到书签
BookmarkCollection bms = mainDoc.getRange().getBookmarks();
Bookmark bm = bms.get(bookmark);
if (bm != null) {
mainDocBuilder.moveToBookmark(bookmark, true, false);
mainDocBuilder.writeln();//获取到插入的位置
Node insertAfterNode = mainDocBuilder.getCurrentParagraph().getPreviousSibling();
insertDocumentAfterNode(insertAfterNode, mainDoc, tobeInserted);
}
} else {
appendDoc(mainDoc, tobeInserted, true);
}
return mainDoc;
}
}
/**
* @Author
* @Description 插入的位置
* @Date 2023/6/28 16:56
* @param insertAfterNode
* @param mainDoc
* @param srcDoc
* @return void
**/
private static void insertDocumentAfterNode(Node insertAfterNode, Document mainDoc, Document srcDoc)throws Exception {
if (insertAfterNode.getNodeType() != 8 & insertAfterNode.getNodeType() != 5) {
throw new Exception("The destination node should be either a paragraph or table.");
}else{
CompositeNode dstStory=insertAfterNode.getParentNode();
while (null !=srcDoc.getLastSection().getBody().getLastParagraph()
&& !srcDoc.getLastSection().getBody().getLastParagraph().hasChildNodes()) {
srcDoc.getLastSection().getBody().getLastParagraph().remove();
}
NodeImporter importer= new NodeImporter(srcDoc, mainDoc, 1);
int sectCount =srcDoc.getSections().getCount();
for (int sectIndex = 0; sectIndex < sectCount; ++sectIndex) {
Section srcSection=srcDoc.getSections().get(sectIndex);
int nodeCount =srcSection.getBody().getChildNodes().getCount();
for (int nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
Node srcNode=srcSection.getBody().getChildNodes().get(nodeIndex);
Node newNode= importer.importNode(srcNode, true);
dstStory.insertAfter(newNode, insertAfterNode);
insertAfterNode=newNode;
}
}
}
}
/**
* @Author
* @Description 文档拼接
* @Date 2023/6/28 16:56
* @param dstDoc
* @param srcDoc
* @param includeSection
* @return void
**/
private static void appendDoc(Document dstDoc, Document srcDoc, boolean includeSection) throws Exception {
if(includeSection) {
Iterator var3 =srcDoc.getSections().iterator();
while(var3.hasNext()) {
Section srcSection=(Section) var3.next();
Node dstNode= dstDoc.importNode(srcSection, true, 0);
dstDoc.appendChild(dstNode);
}
}else{
Node node=dstDoc.getLastSection().getBody().getLastParagraph();
if (node == null) {
node= new Paragraph(srcDoc);
dstDoc.getLastSection().getBody().appendChild(node);
}if (node.getNodeType() != 8 & node.getNodeType() != 5) {
throw new Exception("Use appendDoc(dstDoc, srcDoc, true) instead of appendDoc(dstDoc, srcDoc, false)");
}
insertDocumentAfterNode(node, dstDoc, srcDoc);
}
}