Chèn và Thêm Tài liệu

Đôi khi cần kết hợp vài tài liệu thành một. Bạn có thể thực hiện việc này một cách thủ công hoặc bạn có thể sử dụng tính năng Aspose.Words chèn hoặc nối đuôi.

Hành động chèn cho phép bạn chèn nội dung của các tài liệu trước đó đã được tạo vào một tài liệu mới hoặc hiện có.

Trong khi đó, tính năng thêm vào cho phép bạn thêm một tài liệu chỉ ở cuối của một tài liệu khác.

Bài viết này giải thích cách chèn hoặc nối một tài liệu vào tài liệu khác theo nhiều cách và mô tả các thuộc tính thông dụng mà bạn có thể áp dụng khi chèn hoặc nối các tài liệu.

Chèn Tài liệu

Như đã đề cập ở trên, trong Aspose.Words một tài liệu được đại diện dưới dạng cây của các nút, và hoạt động chèn một tài liệu vào một tài liệu khác là sao chép các nút từ cây tài liệu đầu tiên sang cái thứ hai.

Bạn có thể chèn tài liệu ở nhiều vị trí khác nhau theo các cách khác nhau. Ví dụ, bạn có thể chèn một tài liệu thông qua một thao tác thay thế, một trường kết hợp trong một thao tác kết hợp hoặc qua một dấu hiệu sách.

Bạn cũng có thể dùng phương pháp InsertDocument hoặc InsertDocumentInline tương tự như chèn một tài liệu vào Microsoft Word để chèn toàn bộ tài liệu tại vị trí con trỏ hiện tại mà không cần nhập trước.

Mã ví dụ sau cho thấy cách chèn một tài liệu bằng phương pháp 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");

Ví dụ về mã sau cho thấy cách chèn một tài liệu bằng phương pháp 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());

Các tiểu mục sau mô tả các lựa chọn mà bạn có thể chèn một tài liệu vào tài liệu khác.

Chèn tài liệu trong quá trình Tìm và Thay thế

Bạn có thể chèn tài liệu trong khi thực hiện các thao tác tìm và thay thế. Ví dụ, một tài liệu có thể chứa các đoạn văn với văn bản “[MỞ ĐẦU]” và “[KẾT THÚC]. Nhưng trong bản tài liệu cuối cùng, bạn cần thay thế những đoạn văn đó bằng nội dung được lấy từ một tài liệu bên ngoài khác. Để đạt được điều đó, bạn sẽ cần phải tạo một người xử lý cho sự kiện thay thế.

Ví dụ về mã sau cho thấy cách tạo một trình xử lý cho sự kiện thay thế để sử dụng nó sau trong quá trình chèn:

// 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;
}
}

Ví dụ mã sau cho thấy cách chèn nội dung của một tài liệu vào tài liệu khác trong quá trình tìm và thay thế:

// 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");

Chèn tài liệu trong quá trình Mail Merge hoạt động

Bạn có thể chèn một tài liệu vào trường hợp kết hợp trong một Mail Merge hoạt động. Ví dụ một mẫu Mail Merge có thể chứa một trường kết hợp như [Tóm tắt]. Nhưng trong tài liệu cuối cùng, bạn cần chèn nội dung được lấy từ một tài liệu bên ngoài khác vào trường kết hợp này. Để đạt được điều đó, bạn cần tạo một xử lý cho sự kiện hợp nhất.

Ví dụ mã sau cho thấy cách tạo một trình xử lý cho sự kiện hợp nhất để sử dụng nó sau trong quá trình chèn”:

// 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.
}
}

Mẫu mã sau cho thấy cách chèn một tài liệu vào trường kết hợp bằng cách sử dụng bộ xử lý được tạo ra:

// 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");

Nhập tài liệu tại đánh dấu

Bạn có thể nhập một tập tin văn bản vào một tài liệu và chèn nó ngay sau một dấu trang mà bạn đã xác định trong tài liệu đó. Để làm điều này, hãy tạo một đoạn văn được đánh dấu nơi bạn muốn tài liệu được chèn vào.

Mã ví dụ dưới đây cho thấy cách chèn nội dung của một tài liệu vào dấu đánh chỉ trang trong một tài liệu khác:

// 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");

Thêm một tài liệu

Bạn có thể có trường hợp sử dụng trong đó bạn cần bao gồm thêm các trang từ một tài liệu đến cuối một tài liệu hiện có. Để làm điều này, bạn chỉ cần gọi phương thức AppendDocument để thêm một tài liệu vào cuối của một tài liệu khác.

Mã ví dụ sau cho thấy cách kết nối một tài liệu vào cuối một tài liệu khác:

// 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");

Nhập và chèn nút thủ công

Aspose.Words cho phép bạn chèn và đính kèm các tài liệu tự động mà không cần bất kỳ yêu cầu nhập trước nào. Tuy nhiên, nếu bạn cần chèn hoặc nối tiếp một nút cụ thể trong tài liệu của mình, chẳng hạn như một phần hoặc một đoạn, sau đó trước tiên bạn cần nhập nút này theo cách thủ công.

Khi bạn cần chèn hoặc nối thêm một phần đoạn hoặc câu vào một phần khác, bản thân bạn cần nhập các nút của cây nút tài liệu đầu tiên vào thứ hai bằng phương pháp ImportNode. Sau khi nhập các node của bạn, bạn cần phải dùng phương thức InsertAfter để chèn một node mới sau/trước node tham chiếu. Điều này cho phép bạn tùy chỉnh quá trình chèn bằng cách nhập các node từ một tài liệu và chèn nó ở vị trí được chỉ định.

Bạn cũng có thể sử dụng phương pháp AppendChild để thêm một nút mới được chỉ định vào cuối danh sách các nút con, ví dụ, nếu bạn muốn nối tiếp nội dung ở mức đoạn văn thay vì ở mức mục nhập.

Mã ví dụ sau cho thấy cách nhập thủ công các nút và chèn chúng sau một nút cụ thể sử dụng phương pháp 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.");
}
}

Nội dung được nhập vào phần tài liệu đích từng phần, có nghĩa là các cài đặt như bố cục trang và tiêu đề hoặc chân trang, vẫn được giữ lại trong quá trình nhập. Bạn cũng có thể ghi chú rằng bạn có thể định nghĩa các cài đặt định dạng khi chèn hoặc thêm một tài liệu để chỉ định cách hai tài liệu được kết nối với nhau.

Thuộc tính chung cho việc chèn và thêm tài liệu

Cả InsertDocumentAppendDocument phương pháp đều chấp nhận ImportFormatModeImportFormatOptions làm tham số đầu vào. Cụm từ ImportFormatMode cho phép bạn kiểm soát cách định dạng tài liệu được kết hợp khi bạn nhập nội dung từ một tài liệu vào tài liệu khác bằng cách chọn các chế độ định dạng khác nhau như UseDestinationStyles, KeepSourceFormattingKeepDifferentStyles. The ImportFormatOptions cho phép bạn chọn các tùy chọn nhập khác nhau như IgnoreHeaderFooter, IgnoreTextBoxes, KeepSourceNumbering, MergePastedListsSmartStyleBehavior.

Aspose.Words cho phép bạn điều chỉnh hình thức hiển thị của một tài liệu kết quả khi hai tài liệu được cộng lại trong một hoạt động chèn hoặc nối thêm bằng cách sử dụng các thuộc tính SectionPageSetup. Cái thuộc tính PageSetup chứa tất cả các đặc điểm của một phần như SectionStart, RestartPageNumbering, PageStartingNumber, Orientation và những cái khác. Trường hợp phổ biến nhất là đặt thuộc tính SectionStart để xác định nội dung được thêm vào sẽ hiển thị trên cùng một trang hay chia tách thành một trang mới.

Ví dụ mã sau cho thấy cách nối một tài liệu với một tài liệu khác trong khi giữ nội dung không bị chia trên hai trang:

// 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");