Wstawianie i dołączanie dokumentów

Czasami wymagane jest połączenie kilku dokumentów w jeden. Możesz to zrobić ręcznie lub możesz użyć funkcji wstawiania lub dołączania Aspose.Words.

Operacja Wstaw umożliwia wstawienie zawartości wcześniej utworzonych dokumentów do nowego lub istniejącego.

Z kolei funkcja dołączania umożliwia dodanie dokumentu tylko na końcu innego dokumentu.

W tym artykule wyjaśniono, jak wstawić lub dołączyć dokument do innego dokumentu na różne sposoby i opisano typowe właściwości, które można zastosować podczas wstawiania lub dołączania dokumentów.

Wstaw dokument

Jak wspomniano powyżej, w Aspose.Words dokument jest reprezentowany jako drzewo węzłów, a operacja wstawiania jednego dokumentu do drugiego polega na kopiowaniu węzłów z pierwszego drzewa dokumentów do drugiego.

Możesz wstawiać dokumenty w różnych lokalizacjach na różne sposoby. Na przykład możesz wstawić dokument za pomocą operacji zamiany, pola scalania podczas operacji scalania lub zakładki.

Możesz także użyć metody InsertDocument, która jest podobna do wstawiania dokumentu w Microsoft Word, Aby wstawić cały dokument w bieżącej pozycji kursora bez wcześniejszego importowania.

Poniższy przykład kodu pokazuje, jak wstawić dokument przy użyciu metody 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");

Poniższe podsekcje opisują opcje, podczas których można wstawić jeden dokument do drugiego.

Wstawianie dokumentu podczas operacji znajdź i zamień

Możesz wstawiać dokumenty podczas wykonywania operacji znajdź i zamień. Na przykład dokument może zawierać akapity z tekstami [INTRODUCTION] i [CONCLUSION]. Ale w dokumencie końcowym musisz zastąpić te akapity treścią uzyskaną z innego dokumentu zewnętrznego. Aby to osiągnąć, musisz utworzyć procedurę obsługi dla zdarzenia replace.

Poniższy przykład kodu pokazuje, jak utworzyć procedurę obsługi dla zdarzenia zastępującego, aby użyć go później w procesie wstawiania:

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

Poniższy przykład kodu pokazuje, jak wstawiać zawartość jednego dokumentu do drugiego podczas operacji znajdź i zamień:

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

Wstawianie dokumentu podczas operacji Mail Merge

Możesz wstawić dokument do pola scalania podczas operacji Mail Merge. Na przykład szablon Mail Merge może zawierać pole scalania, takie jak [podsumowanie]. Ale w dokumencie końcowym musisz wstawić zawartość uzyskaną z innego dokumentu zewnętrznego do tego pola scalania. Aby to osiągnąć, musisz utworzyć procedurę obsługi dla zdarzenia scalania.

Poniższy przykład kodu pokazuje, jak utworzyć procedurę obsługi dla zdarzenia scalania, aby użyć go później w procesie wstawiania:

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

Poniższy przykład kodu pokazuje, jak wstawić dokument do pola scalania za pomocą utworzonego programu obsługi:

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

Wstaw dokument w zakładce

Możesz zaimportować plik tekstowy do dokumentu i wstawić go zaraz po zakładce zdefiniowanej w dokumencie. Aby to zrobić, utwórz akapit z zakładkami, w którym chcesz wstawić dokument.

Poniższy przykład kodowania pokazuje, jak wstawić zawartość jednego dokumentu do zakładki w innym dokumencie:

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

Dołącz dokument

Możesz mieć przypadek użycia, w którym musisz dołączyć dodatkowe strony od dokumentu do końca istniejącego dokumentu. Aby to zrobić, wystarczy wywołać metodę AppendDocument, aby dodać dokument na końcu innego.

Poniższy przykład kodu pokazuje, jak dołączyć dokument na końcu innego dokumentu:

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

Importuj i wstawiaj węzły ręcznie

Aspose.Words umożliwia automatyczne wstawianie i dołączanie dokumentów bez wcześniejszych wymagań importowania. Jeśli jednak chcesz wstawić lub dołączyć określony węzeł dokumentu, taki jak sekcja lub akapit, najpierw musisz zaimportować ten węzeł ręcznie.

Gdy musisz wstawić lub dołączyć jedną sekcję lub akapit do drugiej, zasadniczo musisz zaimportować węzły pierwszego drzewa węzłów dokumentu do drugiego przy użyciu metody ImportNode. Po zaimportowaniu węzłów należy użyć metody InsertAfter / InsertBefore, aby wstawić nowy węzeł po / przed węzłem odniesienia. Pozwala to dostosować proces wstawiania poprzez importowanie węzłów z dokumentu i wstawianie go w określonych pozycjach.

Możesz także użyć metody AppendChild, aby dodać nowy określony węzeł na końcu listy węzłów podrzędnych, na przykład, jeśli chcesz dołączyć zawartość na poziomie akapitu zamiast na poziomie sekcji.

Poniższy przykład kodu pokazuje, jak ręcznie importować węzły i wstawiać je po określonym węźle przy użyciu metody 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.");
}
}

Zawartość jest importowana do dokumentu docelowego sekcja po sekcji, co oznacza, że ustawienia, takie jak konfiguracja strony oraz nagłówki lub stopki, są zachowywane podczas importu. Warto również zauważyć, że podczas wstawiania lub dołączania dokumentu można zdefiniować ustawienia formatowania, aby określić sposób łączenia dwóch dokumentów.

Wspólne właściwości wstawiania i dołączania dokumentów

Zarówno InsertDocument, jak i AppendDocument metody akceptują ImportFormatMode i ImportFormatOptions jako parametry wejściowe. ImportFormatMode pozwala kontrolować sposób scalania formatowania dokumentu podczas importowania zawartości z jednego dokumentu do drugiego, wybierając różne tryby formatu, takie jak UseDestinationStyles, KeepSourceFormatting i KeepDifferentStyles. ImportFormatOptions pozwala wybrać różne opcje importu, takie jak IgnoreHeaderFooter, IgnoreTextBoxes, KeepSourceNumbering, MergePastedLists, i SmartStyleBehavior.

Aspose.Words umożliwia dostosowanie wizualizacji wynikowego dokumentu, gdy dwa dokumenty są dodawane razem w operacji wstawiania lub dołączania przy użyciu właściwości Section i PageSetup. Właściwość PageSetup zawiera wszystkie atrybuty sekcji, takie jak SectionStart, RestartPageNumbering, PageStartingNumber, Orientation, i inni Najczęstszym przypadkiem użycia jest ustawienie właściwości SectionStart, aby określić, czy dodana zawartość pojawi się na tej samej stronie, czy zostanie podzielona na nową.

Poniższy przykład kodu pokazuje, jak dołączyć jeden dokument do drugiego, jednocześnie zapobiegając dzieleniu zawartości na dwie strony:

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