插入與追加文件

有時需要將多個文件合併為一個。 您可以手動完成此操作,或使用 Aspose.Words 插入或附加功能。

插入操作讓您將之前創建的文件內容插入新的或現有的文件。

反之,附加功能允許您僅在另一文件的末尾添加一篇文件。

這篇文章解釋了如何以各種方式將文件插入或附加到另一個文件中,並描述了您在插入或附加文件時能應用的常見屬性。

插入一個文件

如上所述,在 Aspose.Words 中,一個文件是作為由節點組成的樹來表示的,將一個文件插入到另一個文件中,就是從第一個文件樹複製節點到第二個文件樹。

你可以用多種不同的方式將文件插入到各個位置。 例如,您可以在替換操作中插入一份文件、在合併操作中使用合併欄位或透過書籤。

您也可以使用類似於在 InsertDocument 中插入文件的 InsertDocumentInline 或 Microsoft Word 方法將整份文件插入到當前光標位置,而無需任何先前的進口。

接下來的程式碼範例示範了透過 InsertDocument 方法插入文件的方法。

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
Document srcDoc = new Document(MyDir + "Document source.docx");
Document dstDoc = new Document(MyDir + "Northwind traders.docx");
DocumentBuilder builder = new DocumentBuilder(dstDoc);
builder.MoveToDocumentEnd();
builder.InsertBreak(BreakType.PageBreak);
builder.InsertDocument(srcDoc, ImportFormatMode.KeepSourceFormatting);
builder.Document.Save(ArtifactsDir + "JoinAndAppendDocuments.InsertDocument.docx");

以下範例會用 InsertDocumentInline 方法插入檔案:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
DocumentBuilder srcDoc = new DocumentBuilder();
srcDoc.Write("[src content]");
// Create destination document.
DocumentBuilder dstDoc = new DocumentBuilder();
dstDoc.Write("Before ");
dstDoc.InsertNode(new BookmarkStart(dstDoc.Document, "src_place"));
dstDoc.InsertNode(new BookmarkEnd(dstDoc.Document, "src_place"));
dstDoc.Write(" after");
Assert.AreEqual("Before after", dstDoc.Document.GetText().TrimEnd());
// Insert source document into destination inline.
dstDoc.MoveToBookmark("src_place");
dstDoc.InsertDocumentInline(srcDoc.Document, ImportFormatMode.UseDestinationStyles, new ImportFormatOptions());
Assert.AreEqual("Before [src content] after", dstDoc.Document.GetText().TrimEnd());

接下來的小節說明在哪些情況下你可以將一張文件插入另一張文件。

在查找與取代操作中插入文件

您可以在進行尋找與取代操作時插入文件。 例如,一篇文件可以包含一段文字 [ INTRODUCTION ] 和 [ CONCLUSION ]。 但在最終的文件中,你需要用從另一個外部文件獲取的內容來替換這些段落。 要達成這個目標,你必須為 replace 事件建立一個處理器。

接下來的程式碼範例顯示如何建立一個取代事件處理常式,以便在插入程序中使用:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
private class InsertDocumentAtReplaceHandler : IReplacingCallback
{
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs args)
{
Document subDoc = new Document(MyDir + "Document insertion 2.docx");
// Insert a document after the paragraph, containing the match text.
Paragraph para = (Paragraph)args.MatchNode.ParentNode;
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-.NET.git.
Document mainDoc = new Document(MyDir + "Document insertion 1.docx");
FindReplaceOptions options = new FindReplaceOptions
{
Direction = FindReplaceDirection.Backward,
ReplacingCallback = new InsertDocumentAtReplaceHandler()
};
mainDoc.Range.Replace(new Regex("\\[MY_DOCUMENT\\]"), "", options);
mainDoc.Save(ArtifactsDir + "CloneAndCombineDocuments.InsertDocumentAtReplace.docx");

在 Mail Merge 操作中插入文件

您可以在 Mail Merge 操作期間將一份文件插入到一個合并欄位中。 例如,一個 Mail Merge 模板可以包含像 [總結] 這樣的合併欄位。 但在最終的文件中,您需要將從另一份外部文件中取得的內容插入此合併欄位。 達到這個目標,您將需要為合併事件建立一個處理器。

以下程式碼範例示範了如何建立併合事件處理常式,以便稍後在插入過程中使用:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
private class InsertDocumentAtMailMergeHandler : 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.
void IFieldMergingCallback.FieldMerging(FieldMergingArgs args)
{
if (args.DocumentFieldName == "Document_1")
{
// Use document builder to navigate to the merge field with the specified name.
DocumentBuilder builder = new DocumentBuilder(args.Document);
builder.MoveToMergeField(args.DocumentFieldName);
// The name of the document to load and insert is stored in the field value.
Document subDoc = new Document((string)args.FieldValue);
InsertDocument(builder.CurrentParagraph, subDoc);
// The paragraph that contained the merge field might be empty now, and you probably want to delete it.
if (!builder.CurrentParagraph.HasChildNodes)
builder.CurrentParagraph.Remove();
// Indicate to the mail merge engine that we have inserted what we wanted.
args.Text = null;
}
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
{
// Do nothing.
}
}

以下範例示範了如何透過已建立的處理常式將檔案插入到合併欄位中:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
Document mainDoc = new Document(MyDir + "Document insertion 1.docx");
mainDoc.MailMerge.FieldMergingCallback = 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.MailMerge.Execute(new[] { "Document_1" }, new object[] { MyDir + "Document insertion 2.docx" });
mainDoc.Save(ArtifactsDir + "CloneAndCombineDocuments.InsertDocumentAtMailMerge.doc");

在ブックマーク {#insert-a-document-at-bookmark} にドキュメントを挿入する

您可以將文字檔輸入到文件中,並在您在文件中定義的書籤後面插入它。 為了做到這點,你必須建立一個你希望在哪裡插入該文件的書籤段落。

接下來的程式碼範例示範了如何將一個文件的內容插入到另一個文件的書籤中:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
Document mainDoc = new Document(MyDir + "Document insertion 1.docx");
Document subDoc = new Document(MyDir + "Document insertion 2.docx");
Bookmark bookmark = mainDoc.Range.Bookmarks["insertionPlace"];
InsertDocument(bookmark.BookmarkStart.ParentNode, subDoc);
mainDoc.Save(ArtifactsDir + "CloneAndCombineDocuments.InsertDocumentAtBookmark.docx");

附加文件

你可能有一個用例,需要將一份文件中的其他頁面附加到現有的文件的末尾。 要做到這點,只需調用 AppendDocument 方法將一篇文件加入另一篇文件的末尾即可。

接下來的程式碼範例示範了如何將一個檔案附加到另一個檔案的結尾:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
Document dstDoc = new Document();
dstDoc.FirstSection.Body.AppendParagraph("Destination document text. ");
Document srcDoc = new Document();
srcDoc.FirstSection.Body.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.KeepSourceFormatting);
dstDoc.Save(ArtifactsDir + "JoinAndAppendDocuments.KeepSourceFormatting.docx");

手動匯入和插入節點

Aspose.Words 讓您可以在沒有任何先前的進口要求的情況下,自動插入和附加文件。 不過,如果您需要在您的文件中插入或附加特定的節點,例如一節或一段,那麼您首先需要手動導入此節點。

當你需要插入或附加一段文字或段落到另一個段落時,基本上你需要用 ImportNode 方法將第一份文件節點樹中的節點導入第二個節點樹。 在導入您的節點後,您需要使用 InsertAfter / InsertBefore 方法插入新節點於参考節點後的/前的。 這讓你能夠透過從一個文件中導入節點,並將其插入到特定位置來,自訂插入過程。

您也可以使用 AppendChild 方法將指定節點附加到子節點列表的末尾,例如如果您想要在段落層次上而不是部分層次上附加內容。

接下來的程式碼範例,說明如何透過 InsertAfter 方法,手動匯入節點,並將其插入到特定節點之後:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.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.NodeType == NodeType.Paragraph || insertionDestination.NodeType == NodeType.Table)
{
CompositeNode destinationParent = insertionDestination.ParentNode;
NodeImporter importer =
new NodeImporter(docToInsert, insertionDestination.Document, ImportFormatMode.KeepSourceFormatting);
// 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.
foreach (Section srcSection in docToInsert.Sections.OfType<Section>())
foreach (Node srcNode in srcSection.Body)
{
if (srcNode.NodeType == 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 ArgumentException("The destination node should be either a paragraph or table.");
}
}

內容會逐段匯入目的地文件,這意味著在匯入時,頁面設定、標題和页脚等設定會保留。 另外,你可以設定格式化設定,當你插入或附加文書時,指定兩個文書如何連結在一起。

插入和附加文件的共性屬性

InsertDocumentAppendDocument 兩種方法都接受 ImportFormatModeImportFormatOptions 作為輸入參數。 ImportFormatMode允許您透過選取不同的格式模式(如 UseDestinationStylesKeepSourceFormattingKeepDifferentStyles),控制在從一文件導入另一文件時,如何處理文檔格式的合併。 此 ImportFormatOptions 可以讓您選擇不同的輸入選項,例如 IgnoreHeaderFooterIgnoreTextBoxesKeepSourceNumberingMergePastedListsSmartStyleBehavior

Aspose.Words 可讓您在將兩份文件合併於插入或附加操作時,使用 SectionPageSetup 屬性調整最終文件的顯示。 PageSetup屬性包含某節的各個屬性,如 SectionStartRestartPageNumberingPageStartingNumberOrientation 等。 最常見的用法是將 SectionStart 屬性設定為定義是否會出現在相同頁面或分開到新的一頁。

以下範例顯示如何在不分裂兩頁的情況下將一文档附加到另一文档:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-.NET.git.
Document srcDoc = new Document(MyDir + "Document source.docx");
Document dstDoc = new Document(MyDir + "Northwind traders.docx");
// Set the source document to continue straight after the end of the destination document.
srcDoc.FirstSection.PageSetup.SectionStart = SectionStart.Continuous;
// Restart the page numbering on the start of the source document.
srcDoc.FirstSection.PageSetup.RestartPageNumbering = true;
srcDoc.FirstSection.PageSetup.PageStartingNumber = 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.FirstSection.PageSetup.PageWidth = dstDoc.LastSection.PageSetup.PageWidth;
srcDoc.FirstSection.PageSetup.PageHeight = dstDoc.LastSection.PageSetup.PageHeight;
srcDoc.FirstSection.PageSetup.Orientation = dstDoc.LastSection.PageSetup.Orientation;
// Iterate through all sections in the source document.
foreach (Paragraph para in srcDoc.GetChildNodes(NodeType.Paragraph, true))
{
para.ParagraphFormat.KeepWithNext = true;
}
dstDoc.AppendDocument(srcDoc, ImportFormatMode.KeepSourceFormatting);
dstDoc.Save(ArtifactsDir + "JoinAndAppendDocuments.DifferentPageSetup.docx");