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

Іноді потрібно об’єднати кілька документів в один. Ви можете зробити це вручну або скористатися функцією вставки або додавання 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");

У наступних підрозділах описані параметри, за допомогою яких ви можете вставляти один документ в інший.

Вставте документ під час операції пошуку та заміни

Ви можете вставляти документи під час виконання операцій пошуку і заміни. Наприклад, документ може містити абзаци з текстом [INTRODUCTION] та [CONCLUSION]. Але в кінцевому документі вам потрібно замінити ці абзаци вмістом, отриманим з іншого зовнішнього документа. Щоб досягти цього, вам потрібно буде створити обробник для події 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, так і 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-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");