Вставка и добавление документов

Иногда требуется объединить несколько документов в один. Вы можете сделать это вручную или воспользоваться функцией вставки или добавления 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-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());

В следующих подразделах описаны параметры, с помощью которых вы можете вставлять один документ в другой.

Вставьте документ во время операции поиска и замены

Вы можете вставлять документы во время выполнения операций поиска и замены. Например, документ может содержать абзацы с текстом [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

Вы можете вставить документ в поле для объединения во время операции Mail Merge. Например, шаблон Mail 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.");
}
}

Содержимое импортируется в целевой документ по разделам, что означает, что при импорте сохраняются такие параметры, как настройка страницы и верхние и нижние колонтитулы. Также полезно отметить, что вы можете задать параметры форматирования при вставке или добавлении документа, чтобы указать, как два документа будут объединены.

Общие свойства для вставки и добавления документов

Оба метода InsertDocument и AppendDocument принимают ImportFormatMode и ImportFormatOptions в качестве входных параметров. Функция ImportFormatMode позволяет управлять объединением форматирования документов при импорте содержимого из одного документа в другой, выбирая различные режимы форматирования, такие как UseDestinationStyles, KeepSourceFormatting и KeepDifferentStyles. Параметр ImportFormatOptions позволяет выбрать различные параметры импорта, такие как IgnoreHeaderFooter, IgnoreTextBoxes, KeepSourceNumbering, MergePastedLists, и SmartStyleBehavior.

Aspose.Words позволяет настроить визуализацию результирующего документа при объединении двух документов в операции вставки или добавления с помощью свойств Section и PageSetup. Свойство 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");