---
title: "Merge Word documents in C#"
url: https://recursiveai.org/onedocument/cookbook/merge-word-documents/
description: "Append DOCX files into one document."
version: "1.0.0"
---

Append DOCX files into one document.

```shell
dotnet add package RecursiveAI.OneDocument.Documents
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneDocument.Documents;
using var dest = Document.Open("first.docx");
using var source = Document.Open("second.docx");
dest.Append(source);
dest.SaveAs("merged.docx");
```

Writes `merged.docx`; the snippet prints nothing.

Unzip [the example](https://recursiveai.org/onedocument/cookbook/merge-word-documents/merge-word-documents.zip), then `dotnet run`.

## Full program

The example includes `first.docx` with “Project summary” in a black Body style and `second.docx` with “Budget approved.” in a blue Body style. This deliberately creates a style conflict.

```csharp
using RecursiveAI.OneDocument.Documents;

using var dest = Document.Open("first.docx");
using var source = Document.Open("second.docx");
var report = dest.Append(source);
dest.SaveAs("merged.docx");
Console.WriteLine($"Appended blocks: {report.CountOf("blocks")}");
foreach (var item in report.Resolutions)
    Console.WriteLine($"{item.Code}: {item.Resolution}");
foreach (var item in report.Loss.Items)
    Console.WriteLine($"{item.Code}: {item.Message}");
foreach (var item in report.Problems)
    Console.WriteLine($"{item.Code}: {item.Message}");
Console.WriteLine(dest.ExtractText().Trim());
```

`dotnet run` prints:

```text
Appended blocks: 1
merge.style-conflict: kept destination
Project summary
Budget approved.
```

Combining Strict and Transitional documents (the two OOXML conformance variants) throws `OfficeUnsupportedException`; inspect `Resolutions`, `Loss.Items` and `Problems` for conflicts and content the merge did not carry over.

## Variations

### Keep both styles and the source section

This writes `keep-both.docx`, retaining the conflicting source style under a new name. `KeepSource` also keeps the source’s final section settings when the copied range reaches its end.

```csharp
using RecursiveAI.OneDocument.Documents;

using var dest = Document.Open("first.docx");
using var source = Document.Open("second.docx");
var report = dest.Append(source, new MergeOptions {
    Styles = StyleConflict.KeepBoth,
    Sections = SectionHandling.KeepSource
});
dest.SaveAs("keep-both.docx");
foreach (var item in report.Resolutions)
    Console.WriteLine($"{item.Code}: {item.Resolution}");
```

Output:

```text
merge.style-conflict: kept both
```

## Related recipes

- [Split a Word document by heading in C#](https://recursiveai.org/onedocument/cookbook/split-word-by-heading/)
- [Find and replace text in a Word document in C#](https://recursiveai.org/onedocument/cookbook/find-and-replace-in-word/)

## The short answer

Open the first Word document as the destination, open the next as the source, call `dest.Append(source)`, then save the destination to a new DOCX. OneDocument edits the destination in memory; the source is only read. Appending combines document bodies rather than extracting plain text, so the operation can copy tables, pictures, styles, notes and their relationships.

For production files, keep the returned `MergeReport`. A saved DOCX does not mean every source setting won. The full program prints resolved conflicts, losses and problems so you can decide whether its result is suitable for your documents.

## Can I merge multiple Word documents into one?

Yes. Use the first document as the base and append the remaining documents in the order you want them to appear. Save once after the last append. Choose the order explicitly rather than treating a folder’s enumeration order as the document order. The first document supplies the destination’s theme, font table and document defaults.

An append copies body blocks. A block is a direct child of the document body, such as a paragraph, table or content control, excluding the final section-properties element. `MergeOptions.SourceStart` and `SourceCount` can select a range instead of the whole body. To insert at a particular block rather than at the end, use `Document.Insert(index, source, options)`.

The [merge documentation](https://recursiveai.org/onedocument/docs/operations-merge/) describes how relationships and identifiers are rewritten. Related parts are copied with their relationship graphs, and identical pictures with the same content type can be stored once. Bookmark names that already exist are renamed, with references in the copied content updated. Those rules are why appending document markup is different from concatenating the text of each file.

## How do I merge a bunch of documents into one?

```csharp
using RecursiveAI.OneDocument.Documents;

string[] files = ["first.docx", "second.docx"];
using var dest = Document.Open(files[0]);
foreach (string path in files.Skip(1))
{
    using var source = Document.Open(path);
    dest.Append(source);
}
dest.SaveAs("combined.docx");
Console.WriteLine(dest.ExtractText().Trim());
```

Output:

```text
Project summary
Budget approved.
```

The list uses the two included inputs; add filenames in the order they should appear. This writes `combined.docx`.

First choose a formatting policy. The default is `StyleConflict.KeepDestination`: styles with the same name and type are compared, and a different source definition loses to the destination’s definition. In this example, the blue source Body style becomes the black destination Body style. The report names that decision as `merge.style-conflict` with resolution `kept destination`.

Use `KeepBoth`, as in the variation, when copied text should use a separate source style. OneDocument adds the source definition with a name such as “Body (2)”. Use `UseSource` only when replacing the destination definition is intentional: existing destination text that uses it can change appearance too. Equal definitions are reused without a conflict report.

Next choose list and section behavior. Lists continue by default when their definitions and level overrides match; `NumberingContinuation.Restart` makes a new list instance. The default section policy uses the destination’s governing section for appended content, while section boundaries inside the copied range keep their own page setup.

For source headers and footers at the end of an appended document, use `SectionHandling.KeepSource` and copy through the source’s end. Headers and footers are copied when a copied section references them. This still is not a promise of identical page layout: destination fonts, theme and defaults win, data bindings can be dropped, and comment replies and resolved state are not carried. Review `Loss.Items` alongside `Resolutions` and `Problems`, then inspect the saved document’s appearance before distributing it.
