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

Иногда требуется объединить несколько документов в один. Вы можете сделать это вручную или воспользоваться функцией вставки или добавления Aspose.Words.

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

В свою очередь, функция добавления позволяет добавлять документ только в конце другого документа.

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

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

Как упоминалось выше, в Aspose.Words документ представлен в виде дерева узлов, и операция вставки одного документа в другой заключается в копировании узлов из первого дерева документов во второе.

Вы можете вставлять документы в различные места различными способами. Например, вы можете вставить документ с помощью операции замены, поля объединения во время операции объединения или с помощью закладки.

Вы также можете использовать метод InsertDocument, который аналогичен вставке документа в Microsoft Word, чтобы вставить весь документ в текущее положение курсора без предварительного импорта.

В следующем примере кода показано, как вставить документ с помощью метода InsertDocument:

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

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

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

Вы можете вставлять документы во время выполнения операций поиска и замены. Например, документ может содержать абзацы с текстом [ВВЕДЕНИЕ] и [ЗАКЛЮЧЕНИЕ]. Но в конечном документе вам необходимо заменить эти абзацы содержимым, полученным из другого внешнего документа. Чтобы добиться этого, вам нужно будет создать обработчик для события replace.

В следующем примере кода показано, как создать обработчик для события замены, чтобы использовать его позже в процессе вставки:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
class InsertDocumentAtReplaceHandler : public IReplacingCallback
{
private:
ReplaceAction Replacing(SharedPtr<ReplacingArgs> args) override
{
auto subDoc = MakeObject<Document>(MyDir + u"Document insertion 2.docx");
// Insert a document after the paragraph, containing the match text.
auto para = System::ExplicitCast<Paragraph>(args->get_MatchNode()->get_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-C.git.
auto mainDoc = MakeObject<Document>(MyDir + u"Document insertion 1.docx");
// Set find and replace options.
auto options = MakeObject<FindReplaceOptions>();
options->set_Direction(FindReplaceDirection::Backward);
options->set_ReplacingCallback(MakeObject<CloneAndCombineDocuments::InsertDocumentAtReplaceHandler>());
// Call the replace method.
mainDoc->get_Range()->Replace(MakeObject<System::Text::RegularExpressions::Regex>(u"\\[MY_DOCUMENT\\]"), u"", options);
mainDoc->Save(ArtifactsDir + u"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-C.git.
class InsertDocumentAtMailMergeHandler : public IFieldMergingCallback
{
private:
void FieldMerging(SharedPtr<FieldMergingArgs> args) override
{
if (args->get_DocumentFieldName() == u"Document_1")
{
// Use document builder to navigate to the merge field with the specified name.
auto builder = MakeObject<DocumentBuilder>(args->get_Document());
builder->MoveToMergeField(args->get_DocumentFieldName());
// The name of the document to load and insert is stored in the field value.
auto subDoc = MakeObject<Document>(System::ObjectExt::Unbox<String>(args->get_FieldValue()));
InsertDocument(builder->get_CurrentParagraph(), subDoc);
// The paragraph that contained the merge field might be empty now, and you probably want to delete it.
if (!builder->get_CurrentParagraph()->get_HasChildNodes())
{
builder->get_CurrentParagraph()->Remove();
}
// Indicate to the mail merge engine that we have inserted what we wanted.
args->set_Text(nullptr);
}
}
void ImageFieldMerging(SharedPtr<ImageFieldMergingArgs> args) override
{
ASPOSE_UNUSED(args);
// Do nothing.
}
};

В следующем примере кода показано, как вставить документ в поле слияния с помощью созданного обработчика:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto mainDoc = MakeObject<Document>(MyDir + u"Document insertion 1.docx");
mainDoc->get_MailMerge()->set_FieldMergingCallback(MakeObject<CloneAndCombineDocuments::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->get_MailMerge()->Execute(MakeArray<String>({u"Document_1"}),
MakeArray<SharedPtr<System::Object>>({System::ObjectExt::Box<String>(MyDir + u"Document insertion 2.docx")}));
mainDoc->Save(ArtifactsDir + u"CloneAndCombineDocuments.InsertDocumentAtMailMerge.doc");

Вставьте документ в закладку

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

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

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto mainDoc = MakeObject<Document>(MyDir + u"Document insertion 1.docx");
auto subDoc = MakeObject<Document>(MyDir + u"Document insertion 2.docx");
SharedPtr<Bookmark> bookmark = mainDoc->get_Range()->get_Bookmarks()->idx_get(u"insertionPlace");
InsertDocument(bookmark->get_BookmarkStart()->get_ParentNode(), subDoc);
mainDoc->Save(ArtifactsDir + u"CloneAndCombineDocuments.InsertDocumentAtBookmark.docx");

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

Возможно, у вас есть вариант использования, когда вам нужно добавить дополнительные страницы из документа в конец существующего документа. Для этого вам просто нужно вызвать метод AppendDocument, чтобы добавить документ в конец другого документа.

В следующем примере кода показано, как добавить документ в конец другого документа:

// For complete examples and data files, please go to https://github.com/aspose-words/Aspose.Words-for-C.git.
auto dstDoc = MakeObject<Document>();
dstDoc->get_FirstSection()->get_Body()->AppendParagraph(u"Destination document text. ");
auto srcDoc = MakeObject<Document>();
srcDoc->get_FirstSection()->get_Body()->AppendParagraph(u"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 + u"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-C.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>
static void InsertDocument(SharedPtr<Node> insertionDestination, SharedPtr<Document> docToInsert)
{
if (insertionDestination->get_NodeType() == NodeType::Paragraph || insertionDestination->get_NodeType() == NodeType::Table)
{
SharedPtr<CompositeNode> destinationParent = insertionDestination->get_ParentNode();
auto importer = MakeObject<NodeImporter>(docToInsert, insertionDestination->get_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.
for (const auto& srcSection : System::IterateOver(docToInsert->get_Sections()->LINQ_OfType<SharedPtr<Section>>()))
{
for (const auto& srcNode : System::IterateOver(srcSection->get_Body()))
{
if (srcNode->get_NodeType() == NodeType::Paragraph)
{
auto para = System::ExplicitCast<Paragraph>(srcNode);
if (para->get_IsEndOfSection() && !para->get_HasChildNodes())
{
continue;
}
}
SharedPtr<Node> newNode = importer->ImportNode(srcNode, true);
destinationParent->InsertAfter(newNode, insertionDestination);
insertionDestination = newNode;
}
}
}
else
{
throw System::ArgumentException(u"The destination node should be either a paragraph or table.");
}
}

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

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

Как InsertDocument, так и Приложение к документу методы принимают 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-C.git.
auto srcDoc = MakeObject<Document>(MyDir + u"Document source.docx");
auto dstDoc = MakeObject<Document>(MyDir + u"Northwind traders.docx");
// Set the source document to continue straight after the end of the destination document.
srcDoc->get_FirstSection()->get_PageSetup()->set_SectionStart(SectionStart::Continuous);
// Restart the page numbering on the start of the source document.
srcDoc->get_FirstSection()->get_PageSetup()->set_RestartPageNumbering(true);
srcDoc->get_FirstSection()->get_PageSetup()->set_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->get_FirstSection()->get_PageSetup()->set_PageWidth(dstDoc->get_LastSection()->get_PageSetup()->get_PageWidth());
srcDoc->get_FirstSection()->get_PageSetup()->set_PageHeight(dstDoc->get_LastSection()->get_PageSetup()->get_PageHeight());
srcDoc->get_FirstSection()->get_PageSetup()->set_Orientation(dstDoc->get_LastSection()->get_PageSetup()->get_Orientation());
// Iterate through all sections in the source document.
for (const auto& para : System::IterateOver<Paragraph>(srcDoc->GetChildNodes(NodeType::Paragraph, true)))
{
para->get_ParagraphFormat()->set_KeepWithNext(true);
}
dstDoc->AppendDocument(srcDoc, ImportFormatMode::KeepSourceFormatting);
dstDoc->Save(ArtifactsDir + u"JoinAndAppendDocuments.DifferentPageSetup.docx");