ODT is OpenDocument’s text format.
dotnet add package RecursiveAI.OneDocument.DocumentsRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneDocument.Documents; using var doc = Document.Open("input.odt"); doc.SaveAs("output.docx");
Writes output.docx; prints nothing. The zip’s input.odt contains “Quarterly report” and “Revenue grew this quarter.”
Unzip the example, then dotnet run.
The full program
The program creates that two-paragraph ODT, opens it into the shared document model (the “hub”), saves DOCX, and prints import and export loss counts and any loss codes. Finally, it reopens the DOCX and reads the text.
using RecursiveAI.OneDocument.Documents; using (Document seed = Document.Create()) { seed.Body.AddParagraph("Quarterly report"); seed.Body.AddParagraph("Revenue grew this quarter."); seed.SaveAs("input.odt"); } using Document doc = Document.Open("input.odt"); doc.SaveAs("output.docx"); Console.WriteLine("Wrote output.docx"); Console.WriteLine($"Import losses: {doc.ImportLoss?.Items.Count ?? 0}"); Console.WriteLine($"Export losses: {doc.ExportLoss?.Items.Count ?? 0}"); foreach (var loss in doc.ImportLoss?.Items ?? []) Console.WriteLine($"Import: {loss.Code}"); foreach (var loss in doc.ExportLoss?.Items ?? []) Console.WriteLine($"Export: {loss.Code}"); using Document saved = Document.Open("output.docx"); Console.WriteLine(saved.ExtractText().Trim());
dotnet run prints:
Wrote output.docx Import losses: 0 Export losses: 0 Quarterly report Revenue grew this quarter.
Encrypted ODF packages raise OfficeUnsupportedException; ODF encryption is not implemented.
Variations
Read import loss codes before saving. This lets your application decide whether to accept a conversion.
using RecursiveAI.OneDocument.Documents; using var doc = Document.Open("input.odt"); Console.WriteLine($"Import losses: {doc.ImportLoss?.Items.Count ?? 0}"); foreach (var loss in doc.ImportLoss?.Items ?? []) Console.WriteLine(loss.Code); doc.SaveAs("reviewed.docx");
Import losses: 0Related recipes
The short answer
To convert ODT to DOCX in C#, use OneDocument’s Documents package: Document.Open reads the ODT into the word-processing hub and SaveAs writes a .docx file. This API reads the OpenDocument structure and maps supported content into an in-memory DOCX package.
The downloadable example uses two plain paragraphs so that the input is visible and easy to inspect. It reports zero import and export losses for that sample, then reopens the saved DOCX and prints its text. That result applies to this small document, not every ODT file.
Can you convert ODT to docx?
Yes. Document.Open accepts ODT, OTT and FODT by content, using the package’s mimetype entry or the flat document’s office:mimetype, rather than trusting the extension. The opened object retains its source format in Document.Format, even though the internal hub is a DOCX package. Saving to a .docx filename chooses DOCX output.
For an application, keep the source and destination paths separate, as this example does. Read ImportLoss after opening; inspect ExportLoss after saving. A conversion report gives your code a way to distinguish a simple accepted mapping from a document with unsupported content. The ODF documentation lists supported mappings and loss codes.
How to convert ODT to Word doc?
This recipe writes DOCX, not the older binary DOC format. The output extension in SaveAs("output.docx") is part of that choice. It does not require starting a desktop Word application.
Paragraphs, headings, text formatting, tables, lists, headers, footers, comments and tracked changes have documented ODF-to-hub mappings. That does not mean every layout feature survives identically. Shapes can keep text while losing geometry. Embedded objects, including charts, keep only a preview picture. Linked images are never fetched. Mathematical formulas can keep symbols as text rather than an editable equation. These are practical reasons to inspect the report and review a representative document before converting a collection.
An unreadable XML part raises its typed error when first used. A loss report covers mapped content that could not be carried; it is not a substitute for handling file-opening exceptions.
Are ODT and DOCX the same?
No. In this library they are distinct file formats connected through a shared document model. Opening ODT is an import, not a change of filename. Saving DOCX serializes that model to a different package structure. Zero reported losses does not establish identical page breaks in every viewer, and the text readback in this example checks text, not page layout.
There is also a distinction between converting and preserving an untouched source. The docs state that an ODT, OTT or FODT read and saved in its own format without an edit writes the original bytes. That preservation behavior does not describe an ODT-to-DOCX conversion: a different output format necessarily goes through the hub. Once you edit an ODT and save it back as OpenDocument, the exporter writes its own package and reports what it could not carry. Treat ImportLoss and ExportLoss as separate stages rather than assuming the final report summarizes the whole journey.