插入和追加文档

有时需要将多个文档合并为一个。 您可以手动执行此操作,也可以使用Aspose.Words插入或追加功能。

插入操作允许您将以前创建的文档的内容插入到新的或现有的文档中。

反过来,追加功能允许您仅在另一个文档的末尾添加文档。

本文介绍了如何以不同的方式将文档插入或附加到另一个文档,并介绍了在插入或附加文档时可以应用的常见属性。

插入文档

如上所述,在Aspose.Words中,文档表示为节点树,将一个文档插入另一个文档的操作是将节点从第一个文档树复制到第二个文档树。

您可以通过不同的方式在各种位置插入文档。 例如,您可以通过替换操作、合并操作期间的合并字段或通过书签插入文档。

您还可以使用InsertDocumentInsertDocumentInline方法,类似于在Microsoft Word中插入文档,在当前光标位置插入整个文档,而无需任何先前的导入。

下面的代码示例演示如何使用InsertDocument方法插入文档:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document srcDoc = new Document(getMyDir() + "Document source.docx");
Document dstDoc = new Document(getMyDir() + "Northwind traders.docx");
DocumentBuilder builder = new DocumentBuilder(dstDoc);
builder.moveToDocumentEnd();
builder.insertBreak(BreakType.PAGE_BREAK);
builder.insertDocument(srcDoc, ImportFormatMode.KEEP_SOURCE_FORMATTING);
builder.getDocument().save(getArtifactsDir() + "JoinAndAppendDocuments.insertDocument.docx");

下面的代码示例演示如何使用InsertDocumentInline方法插入文档:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
DocumentBuilder srcDoc = new DocumentBuilder();
srcDoc.write("[src content]");
// Create destination document.
DocumentBuilder dstDoc = new DocumentBuilder();
dstDoc.write("Before ");
dstDoc.insertNode(new BookmarkStart(dstDoc.getDocument(), "src_place"));
dstDoc.insertNode(new BookmarkEnd(dstDoc.getDocument(), "src_place"));
dstDoc.write(" after");
Assert.assertEquals("Before after", dstDoc.getDocument().getText().trim());
// Insert source document into destination inline.
dstDoc.moveToBookmark("src_place");
dstDoc.insertDocumentInline(srcDoc.getDocument(), ImportFormatMode.USE_DESTINATION_STYLES, new ImportFormatOptions());
Assert.assertEquals("Before [src content] after", dstDoc.getDocument().getText().trim());

以下小节描述了可以将一个文档插入另一个文档的选项。

在查找和替换操作 {#insert-a-document-during-find-and-replace-operation}期间插入文档

您可以在执行查找和替换操作时插入文档。 例如,文档可以包含文本为[INTRODUCTION]和[CONCLUSION]的段落。 但在最终文档中,您需要将这些段落替换为从另一个外部文档中获取的内容。 为此,您需要为replace事件创建一个处理程序。

下面的代码示例演示如何为替换事件创建处理程序,以便稍后在插入过程中使用它:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
private static class InsertDocumentAtReplaceHandler implements IReplacingCallback
{
public /*ReplaceAction*/int /*IReplacingCallback.*/replacing(ReplacingArgs args) throws Exception
{
Document subDoc = new Document(getMyDir() + "Document insertion 2.docx");
// Insert a document after the paragraph, containing the match text.
Paragraph para = (Paragraph)args.getMatchNode().getParentNode();
insertDocument(para, subDoc);
// Remove the paragraph with the match text.
para.remove();
return ReplaceAction.SKIP;
}
}

下面的代码示例演示如何在查找和替换操作期间将一个文档的内容插入到另一个文档中:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document mainDoc = new Document(getMyDir() + "Document insertion 1.docx");
// Set find and replace options.
FindReplaceOptions options = new FindReplaceOptions();
{
options.setDirection(FindReplaceDirection.BACKWARD);
options.setReplacingCallback(new InsertDocumentAtReplaceHandler());
}
// Call the replace method.
mainDoc.getRange().replace(Pattern.compile("\\[MY_DOCUMENT\\]"), "", options);
mainDoc.save(getArtifactsDir() + "CloneAndCombineDocuments.InsertDocumentAtReplace.docx");

在Mail Merge操作 {#insert-a-document-during-mail-merge-operation}期间插入文档

您可以在Mail Merge操作期间将文档插入合并字段。 例如,Mail Merge模板可以包含[Summary]等合并字段。 但在最终文档中,您需要将从另一个外部文档获取的内容插入到此合并字段中。 为此,您需要为merge事件创建一个处理程序。

下面的代码示例演示如何为合并事件创建处理程序,以便稍后在插入过程中使用它:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
private static class InsertDocumentAtMailMergeHandler implements IFieldMergingCallback
{
// This handler makes special processing for the "Document_1" field.
// The field value contains the path to load the document.
// We load the document and insert it into the current merge field.
public void /*IFieldMergingCallback.*/fieldMerging(FieldMergingArgs args) throws Exception
{
if ("Document_1".equals(args.getDocumentFieldName()))
{
// Use document builder to navigate to the merge field with the specified name.
DocumentBuilder builder = new DocumentBuilder(args.getDocument());
builder.moveToMergeField(args.getDocumentFieldName());
// The name of the document to load and insert is stored in the field value.
Document subDoc = new Document((String)args.getFieldValue());
insertDocument(builder.getCurrentParagraph(), subDoc);
// The paragraph that contained the merge field might be empty now, and you probably want to delete it.
if (!builder.getCurrentParagraph().hasChildNodes())
builder.getCurrentParagraph().remove();
// Indicate to the mail merge engine that we have inserted what we wanted.
args.setText(null);
}
}
public void /*IFieldMergingCallback.*/imageFieldMerging(ImageFieldMergingArgs args)
{
// Do nothing.
}
}

下面的代码示例演示如何使用创建的处理程序将文档插入到合并字段中:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document mainDoc = new Document(getMyDir() + "Document insertion 1.docx");
mainDoc.getMailMerge().setFieldMergingCallback(new InsertDocumentAtMailMergeHandler());
// The main document has a merge field in it called "Document_1".
// The corresponding data for this field contains a fully qualified path to the document.
// That should be inserted to this field.
mainDoc.getMailMerge().execute(new String[] { "Document_1" }, new Object[] { getMyDir() + "Document insertion 2.docx" });
mainDoc.save(getArtifactsDir() + "CloneAndCombineDocuments.InsertDocumentAtMailMerge.doc");

在书签处插入文档

您可以将文本文件导入到文档中,并将其插入到文档中定义的书签之后。 为此,请创建一个书签段落,您希望在其中插入文档。

下面的编码示例演示如何将一个文档的内容插入到另一个文档中的书签中:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document mainDoc = new Document(getMyDir() + "Document insertion 1.docx");
Document subDoc = new Document(getMyDir() + "Document insertion 2.docx");
Bookmark bookmark = mainDoc.getRange().getBookmarks().get("insertionPlace");
insertDocument(bookmark.getBookmarkStart().getParentNode(), subDoc);
mainDoc.save(getArtifactsDir() + "CloneAndCombineDocuments.InsertDocumentAtBookmark.docx");

追加文档

您可能有一个用例,您需要包括从文档到现有文档末尾的其他页面。 为此,您只需要调用AppendDocument方法将文档添加到另一个文档的末尾。

下面的代码示例演示如何将文档追加到另一个文档的末尾:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document dstDoc = new Document();
dstDoc.getFirstSection().getBody().appendParagraph("Destination document text. ");
Document srcDoc = new Document();
srcDoc.getFirstSection().getBody().appendParagraph("Source document text. ");
// Append the source document to the destination document.
// Pass format mode to retain the original formatting of the source document when importing it.
dstDoc.appendDocument(srcDoc, ImportFormatMode.KEEP_SOURCE_FORMATTING);
dstDoc.save(getArtifactsDir() + "JoinAndAppendDocuments.KeepSourceFormatting.docx");

手动导入和插入节点

Aspose.Words允许您自动插入和附加文档,而无需任何先前的导入要求。 但是,如果您需要插入或追加文档的特定节点,例如部分或段落,则首先需要手动导入此节点。

当您需要将一个部分或段落插入或附加到另一个部分或段落时,您基本上需要使用ImportNode方法将第一个文档节点树的节点导入到第二个文档节点树中。 导入节点后,您需要使用InsertAfter方法在引用节点之后/之前插入一个新节点。 这允许您通过从文档导入节点并在给定位置插入来自定义插入过程。

您还可以使用AppendChild方法将新的指定节点添加到子节点列表的末尾,例如,如果要在段落级别而不是在节级别追加内容。

下面的代码示例演示如何手动导入节点并使用InsertAfter方法将它们插入到特定节点之后:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
/// <summary>
/// Inserts content of the external document after the specified node.
/// Section breaks and section formatting of the inserted document are ignored.
/// </summary>
/// <param name="insertionDestination">Node in the destination document after which the content
/// Should be inserted. This node should be a block level node (paragraph or table).</param>
/// <param name="docToInsert">The document to insert.</param>
private static void insertDocument(Node insertionDestination, Document docToInsert)
{
if (insertionDestination.getNodeType() == NodeType.PARAGRAPH || insertionDestination.getNodeType() == NodeType.TABLE)
{
CompositeNode destinationParent = insertionDestination.getParentNode();
NodeImporter importer =
new NodeImporter(docToInsert, insertionDestination.getDocument(), ImportFormatMode.KEEP_SOURCE_FORMATTING);
// Loop through all block-level nodes in the section's body,
// then clone and insert every node that is not the last empty paragraph of a section.
for (Section srcSection : docToInsert.getSections())
for (Node srcNode : srcSection.getBody())
{
if (srcNode.getNodeType() == NodeType.PARAGRAPH)
{
Paragraph para = (Paragraph)srcNode;
if (para.isEndOfSection() && !para.hasChildNodes())
continue;
}
Node newNode = importer.importNode(srcNode, true);
destinationParent.insertAfter(newNode, insertionDestination);
insertionDestination = newNode;
}
}
else
{
throw new IllegalArgumentException("The destination node should be either a paragraph or table.");
}
}

内容逐段导入到目标文档中,这意味着在导入过程中保留设置(如页面设置和页眉或页脚)。 还需要注意的是,您可以在插入或追加文档时定义格式设置,以指定如何将两个文档连接在一起。

插入和追加文档的常用属性

InsertDocumentAppendDocument方法都接受ImportFormatModeImportFormatOptions作为输入参数。 ImportFormatMode允许您通过选择不同的格式模式(如UseDestinationStylesKeepSourceFormattingKeepDifferentStyles)来控制将内容从一个文档导入到另一个文档时文档格式的合并方式。 ImportFormatOptions允许您选择不同的导入选项,例如IgnoreHeaderFooter, IgnoreTextBoxes, KeepSourceNumbering, MergePastedLists, 和SmartStyleBehavior

Aspose.Words允许您使用SectionPageSetup属性在插入或追加操作中添加两个文档时调整结果文档的可视化。 PageSetup属性包含节的所有属性,例如SectionStart, RestartPageNumbering, PageStartingNumber, Orientation, 和其他人。 最常见的用例是设置SectionStart属性以定义添加的内容是出现在同一页面上还是拆分为新页面。

下面的代码示例演示如何将一个文档附加到另一个文档,同时防止内容在两个页面之间分裂:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-Java.git.
Document srcDoc = new Document(getMyDir() + "Document source.docx");
Document dstDoc = new Document(getMyDir() + "Northwind traders.docx");
// Set the source document to continue straight after the end of the destination document.
srcDoc.getFirstSection().getPageSetup().setSectionStart(SectionStart.CONTINUOUS);
// Restart the page numbering on the start of the source document.
srcDoc.getFirstSection().getPageSetup().setRestartPageNumbering(true);
srcDoc.getFirstSection().getPageSetup().setPageStartingNumber(1);
// To ensure this does not happen when the source document has different page setup settings, make sure the
// settings are identical between the last section of the destination document.
// If there are further continuous sections that follow on in the source document,
// this will need to be repeated for those sections.
srcDoc.getFirstSection().getPageSetup().setPageWidth(dstDoc.getLastSection().getPageSetup().getPageWidth());
srcDoc.getFirstSection().getPageSetup().setPageHeight(dstDoc.getLastSection().getPageSetup().getPageHeight());
srcDoc.getFirstSection().getPageSetup().setOrientation(dstDoc.getLastSection().getPageSetup().getOrientation());
// Iterate through all sections in the source document.
for (Paragraph para : (Iterable<Paragraph>) srcDoc.getChildNodes(NodeType.PARAGRAPH, true))
{
para.getParagraphFormat().setKeepWithNext(true);
}
dstDoc.appendDocument(srcDoc, ImportFormatMode.KEEP_SOURCE_FORMATTING);
dstDoc.save(getArtifactsDir() + "JoinAndAppendDocuments.DifferentPageSetup.docx");