背景:
最近接到一个需求,步骤表单数据融合到world里。
这个听起来简单,结合三方的DocxHelper填充数据不是什么难事,但是其中有一个需求是将动态将一个模版拼接多次。
这个模版的数据是一个表格,每一列数据都要填充一次模版,所以模版循环拼接的次数是动态的。
常规的子模版文件拼接父模版文件也是通过Aspose.Words完成的,拼接的位置是通过模版中的书签来确定,但是如果循环拼接就存在一个问题,这个书签我要动态的调整。昨天也是花了好久找这个修改书签的资料,但是大多都不好用,最后摸索出来一个方法,记录一下。
代码:
要知道模版最初是有一个书签的,这个书签是在我们制作模版时添加的,至于位置自定义。后续的需要调整的书签也是需要只要原始的书签位置才可以做修改。
修改书签:
/**
* 修改书签
* @param documentPath 要修改书签的文档
* @param alertBookmark 要修改的书签名称
* @param newText 新的文本内容
*/
public static String modifyBookmark(String documentPath, String alertBookmark, String newText) {
StringUtils.isBlankAssert(documentPath,"修改路径不能为空");
String outputFilePath = "C:/ace/test" + File.separator + uString.getUUID() + ".docx";
try {
// 加载文档
Document doc = new Document(documentPath);
// 获取指定的书签
Bookmark bookmark = doc.getRange().getBookmarks().get(alertBookmark);
if (bookmark != null) {
// 更新书签内容
bookmark.setName(newText);
// 保存文档
doc.save(outputFilePath);
}
} catch (Exception e) {
throw new Exception("修改书签错误: " + e.getMessage(), e);
}
return outputFilePath;
}
文档拼接方法:
/**
* @Description 文档拼接
* @param mainDocuPath 主文档
* @param appendDocumPath 要拼接的文档
* @param tabCode 书签名称,将add文档拼接到主文档哪个位置
*/
public static void wordFileMerge(String mainDocuPath, String appendDocumPath, String tabCode, String mergedWordPath,String waterCenter){
StringUtils.isBlankAssert(mainDocuPath,"主文档路径不能为空");
StringUtils.isBlankAssert(appendDocumPath,"追加文档路径不能为空");
StringUtils.isBlankAssert(mergedWordPath,"最终的文档路径不能为空");
isWordLicense();
try{
//主文档
Document mainDocument = new Document(mainDocuPath);
//需要进行追加的文档
Document addDocument = new Document(appendDocumPath);
//第四个参数是书签名,需要和步骤1在大word文档中定义的书签名对上
FileMergeUtil.appendDocument(mainDocument, addDocument, true, tabCode);
//将最终合并完成后的文档对象保存到文件中 设置只读 密码
mainDocument.protect(ProtectionType.READ_ONLY,"password");
if(StringUtils.isBlank(waterCenter)){
WaterUtil.insertWatermarkText(mainDocument,"");
}else{
WaterUtil.insertWatermarkText(mainDocument,waterCenter);
}
mainDocument.save(mergedWordPath);
}catch (Exception e){
throw new Exception("合并出错 :" + e.getMessage());
}
}
文档拼接调用类:
/**
* @Description 文档拼接
* @param mainDoc 主文档
* @param addDoc 要拼接的文档
* @param isPortrait 是否横向拼接
* @param bookmark 书签名称,将add文档拼接到主文档哪个位置
*/
public static void appendDocument(Document mainDoc, Document addDoc, boolean isPortrait, String bookmark){
DocumentBuilder builder = null;
try{
if(StringUtils.isNotBlank(bookmark)){
builder = new DocumentBuilder(mainDoc);
BookmarkCollection bms = mainDoc.getRange().getBookmarks();
Bookmark bm = bms.get(bookmark);
if (bm != null){
builder.moveToBookmark(bookmark, true, false);
builder.writeln();
builder.getPageSetup().setPaperSize(PaperSize.A4);
if (isPortrait){
builder.getPageSetup().setOrientation(Orientation.PORTRAIT);
}else{
builder.getPageSetup().setOrientation(Orientation.LANDSCAPE);
}
Node insertAfterNode = builder.getCurrentParagraph().getPreviousSibling();
insertDocumentAfterNode(insertAfterNode, mainDoc, addDoc);
}
}
if(StringUtils.isBlank(bookmark)){
mainDoc.appendDocument(addDoc, ImportFormatMode.USE_DESTINATION_STYLES);
}
}catch (Exception e){
e.printStackTrace();
}
}
insertDocumentAfterNode方法:
/**
* @Description
* @param insertAfterNode 插入的位置
* @param mainDoc 主文档
* @param srcDoc 要拼接进去的文档
* @Return void
*/
@SuppressWarnings("rawtypes")
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();
Body body = srcDoc.getLastSection().getBody();
while (null != body.getLastParagraph() && !body.getLastParagraph().hasChildNodes()){
srcDoc.getLastSection().getBody().getLastParagraph().remove();
}
NodeImporter importer = new NodeImporter(srcDoc, mainDoc, ImportFormatMode.KEEP_SOURCE_FORMATTING);
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;
}
}
}
}