Word Document Append

Hi,
Is there any way to append multile word documents simultaneously, similar to the concatenate method exposed by PdfKit?
Thanks & Regards
Binu

Hi

Thanks for your request. No, there is no method to merge multiple documents. However, you can easily create such method yourself. For instance see the following code:

[Test]
public void Test001()
{
    // Create input stream objects holding the PDF files to be concatenated
    FileStream inStream1 = new FileStream(@"Test001\in1.doc", FileMode.Open);
    FileStream inStream2 = new FileStream(@"Test001\in2.doc", FileMode.Open);
    FileStream inStream3 = new FileStream(@"Test001\in3.doc", FileMode.Open);
    FileStream inStream4 = new FileStream(@"Test001\in4.doc", FileMode.Open);
    // Store all input streams in an Array
    Stream[] inStreams = new Stream[]
    {
        inStream1,
        inStream2,
        inStream3,
        inStream4
    };
    // Create output stream object that would contain the final PDF file
    using(FileStream outStream = new FileStream(@"Test001\out.doc", FileMode.Create))
    {
        // COncatenate documents.
        Concatenate(inStreams, outStream, ImportFormatMode.UseDestinationStyles, SaveFormat.Doc);
    }
    // Do not forget to dispose input streams.
    foreach(Stream stream in inStreams)
    stream.Dispose();
}

///
/// Concatenates documents and saves the result into the output stream.
///
/// Array of streams with source documents.
/// Stream where the result document should be saved.
/// Import format mode that hsould be used upon concatenating the documents.
/// Format of the output document.
private void Concatenate(Stream[] inStreams, Stream outStream, ImportFormatMode importFormatMode, SaveFormat saveFormat)
{
    if (inStreams.Length <= 0)
        throw new ArgumentException("There should be at least one input stream");
    if (outStream == null)
        throw new ArgumentException("Output stream cannot be null.");
    // Create main document.
    Document doc = new Document(inStreams[0]);
    // Append all other documents to the main document.
    // Start from the second item, because the first one if the main document.
    for (int docIndex = 1; docIndex <inStreams.Length; docIndex++)
        doc.AppendDocument(new Document(inStreams[docIndex]), importFormatMode);
    // Save output.
    doc.Save(outStream, saveFormat);
}

Hope this helps.
Best regards,

Hi Alexey,
Thanks for the update and sample code.
Regards,
Binu

Hi Alexey,
I uses your code to combine > 2 doc files together. I want to keep the page number and total pages number as it is in original documents.
For ex: I have 2 doc files, first doc has 15 pages and 2nd doc has 10 pages. I want in the combine doc the first 15 pages will be: Page 1 of 15, Page 2 of 15 and for the last 10 pages it must be Page 1 of 10, Page 2 of 10.
I searched in the forum and use the example of UnlinkFields to remove the total page number:

NodeCollection starts = doc.GetChildNodes(NodeType.FieldStart, true);
foreach(Aspose.Words.Fields.FieldStart start in starts)
{
    if (start.FieldType == Aspose.Words.Fields.FieldType.FieldNumPages)
    {
        Node currentNode = start;
        Node fieldSeparator = null;
        while (currentNode.NodeType != NodeType.FieldSeparator && currentNode.NodeType != NodeType.FieldEnd)
        {
            currentNode = currentNode.NextSibling;
            currentNode.PreviousSibling.Remove();
        }
        if (currentNode.NodeType == NodeType.FieldSeparator)
        {
            fieldSeparator = currentNode;
            while (currentNode.NodeType != NodeType.FieldEnd)
            {
                currentNode = currentNode.NextPreOrder(doc);
            }
            fieldSeparator.Remove();
        }
        currentNode.Remove();
    }
}

It works for the the total page number but for the page number, it still has issue with the 2nd doc when it has the first page is Page 16 of 10 (because my first doc has 15 pages). I tried to remove Aspose.Words.Fields.FieldType.FieldPage but it is not working.
Thanks a lot for help.
Tom Do.

Hi Tom,
Thanks for your inquiry.
I think you can use the code from this article to achieve what you are looking for. https://docs.aspose.com/words/net/replace-fields/
The code does the exact same thing as UnlinkFields but is a little more robust.
However if you have any page fields in a header or footer then the above technique will not work. You may also want to look into “Multiple numbering schemes” on this page here: https://docs.aspose.com/words/net/insert-and-append-documents/
If I can help you with anything else please feel free to ask.
Thanks,

I used the latest Aspose.Words 10.4 with c#2010.
I used the ConvertFieldsToStaticText with this code:

Document doc = new Document(@"C:\Temp\doc\in3org.doc");
// UnlinkFields(doc);
ConvertFieldsToStaticText(doc, Aspose.Words.Fields.FieldType.FieldNumPages);
doc.UpdateFields();
doc.UpdatePageLayout();
doc.Save(@"C:\Temp\doc\in3.doc", SaveFormat.Doc);
doc = null;

and the result in3.doc return total page is 21 but the doc file only has 20 pages, the last section (last 2 pages - Addendums) return correct 20 pages. If I used UnlinkField, it returns correct 20 but the last 2 pages Addendums, the NumPages field was not removed.
I attach the org doc and in3.doc is returned by ConvertFieldsToStaticText, in3Unlinked.doc is returned by UnlinkFields.
Thanks,
Tom.

I used the latest Aspose.Words 10.4 with c#2010.
And this is another issue related with combine reports, I used the code like AppendDocument_ConvertNumPageFields(), here is my code:

private void CombineFiles()
{
    // Create input stream objects holding the PDF files to be concatenated
    FileStream inStream1 = new FileStream(@"C:\Temp\doc\in1.doc", FileMode.Open);
    FileStream inStream2 = new FileStream(@"C:\Temp\doc\in2.doc", FileMode.Open);
    // Store all input streams in an Array
    Stream[] inStreams = new Stream[]
    {
        inStream1,
        inStream2
    };
    // Create output stream object that would contain the final PDF file
    using(FileStream outStream = new FileStream(@"C:\Temp\doc\out.pdf", FileMode.Create))
    {
        // COncatenate documents.
        Concatenate(inStreams, outStream, ImportFormatMode.KeepSourceFormatting, SaveFormat.Pdf);
    }
    // Do not forget to dispose input streams.
    foreach(Stream stream in inStreams)
    stream.Dispose();
}
private void Concatenate(Stream[] inStreams, Stream outStream, ImportFormatMode importFormatMode, SaveFormat saveFormat)
{
    if (inStreams.Length <= 0)
        throw new ArgumentException("There should be at least one input stream");
    if (outStream == null)
        throw new ArgumentException("Output stream cannot be null.");
    // Create main document.
    Document doc = new Document(inStreams[0]);
    // Append all other documents to the main document.
    // Start from the second item, because the first one if the main document.
    for (int docIndex = 1; docIndex <inStreams.Length; docIndex++)
    {
        Document otherDoc = new Document(inStreams[docIndex]);
        otherDoc.FirstSection.PageSetup.RestartPageNumbering = true;
        otherDoc.FirstSection.PageSetup.PageStartingNumber = 1;
        doc.AppendDocument(otherDoc, importFormatMode);
        ConvertNumPageFieldsToPageRef(doc);
        otherDoc = null;
    }
    doc.UpdateTableLayout();
    doc.UpdatePageLayout();
    // Save output.
    doc.Save(outStream, saveFormat);
}

I want the first doc working as cover page, so it must be in seperate page with the rest. And another issue is the page number, why I don’t have Page 1 of 4 but it is as Page 2 of 4, Page 3 of 4, Page 3 of 4 and Page 4 of 4. I attach 2 original doc files and pdf result file.
Thanks,
Tom.

Hi there,
Thanks for attaching your documents here.
Using DocumentExplorer I can see that last result which is stored in the NUMPAGES field shows the total page numbers as “21”. This is an out of date value which is why is differs from the expected value. When the document is opened in Microsoft Word this field in the footer is automatically updated which is why it appears correct there. The reason for the difference between UnlinkFields is probably that you called UpdateFields before calling this method. So the behaviour of ConvertFieldsToStatic text is actually correct, to avoid this issue you can simply call UpdateFields first.
Regarding the second issue you can fix both issues by including this code below:

otherDoc.FirstSection.PageSetup.RestartPageNumbering = true;
otherDoc.FirstSection.PageSetup.PageStartingNumber = 1;
otherDoc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;

Thanks,