Export an Excel worksheet as comma-separated text for a data import or a plain-text copy.
dotnet add package RecursiveAI.OneDocument.SpreadsheetsRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneDocument.Spreadsheets; using var book = Workbook.Open("stock.xlsx"); book.SaveAs("stock.csv"); Console.Write(File.ReadAllText("stock.csv"));
Item,Quantity "Pens, blue",12 Paper,5
Unzip the example, then dotnet run.
The zip includes stock.xlsx: a sheet with the columns Item and Quantity and the rows “Pens, blue”, 12 and “Paper”, 5. The full program recreates it.
The full program
The download’s Program.cs uses the supplied samples:
using RecursiveAI.OneDocument.Spreadsheets; using (Workbook sample = Workbook.Create()) { sample.Sheets[0].Range("A1:B3").Values = new object?[,] { { "Item", "Quantity" }, { "Pens, blue", 12 }, { "Paper", 5 } }; sample.SaveAs("stock.xlsx"); } using Workbook book = Workbook.Open("stock.xlsx"); book.SaveAs("stock.csv"); Console.Write(File.ReadAllText("stock.csv"));
dotnet run prints:
Item,Quantity "Pens, blue",12 Paper,5
Only the first visible sheet is exported by default; formulas become cached values, not formula expressions.
Variations
Write tab-separated text
using RecursiveAI.OneDocument.Spreadsheets; using var book = Workbook.Open("stock.xlsx"); book.SaveAs("stock.tsv"); Console.Write(File.ReadAllText("stock.tsv"));
Output:
Item Quantity Pens, blue 12 Paper 5
Export a chosen sheet and read the losses
Pass a worksheet to CsvDocument.Write: book.Sheets[0] selects the first sheet by index; book.Sheets["Sheet1"] selects this sample’s sheet by name. The LossReport lists features that CSV cannot keep. This sample has no export losses.
using RecursiveAI.OneDocument.Diagnostics; using RecursiveAI.OneDocument.Spreadsheets; using RecursiveAI.OneDocument.Spreadsheets.Csv; using var book = Workbook.Open("stock.xlsx"); var losses = new LossReport(); using (var output = File.Create("first-sheet.csv")) CsvDocument.Write(book.Sheets[0], output, new CsvWriteOptions { Formatted = false }, losses); Console.WriteLine($"Export losses: {losses.Items.Count}"); foreach (var loss in losses.Items) Console.WriteLine($"{loss.Code}: {loss.Message}"); Console.Write(File.ReadAllText("first-sheet.csv"));
Output:
Export losses: 0 Item,Quantity "Pens, blue",12 Paper,5
Related recipes
The short answer
Open the XLSX with Workbook.Open, then call SaveAs with a .csv destination. OneDocument writes the first visible worksheet, not a combined export of every worksheet. Use this when the receiving system expects a flat table. Keep the original workbook when you also need charts, formulas or formatting.
The snippet at the top writes the CSV and prints it back. The quotation marks around “Pens, blue” belong to the file: the comma is part of one field, not a new column. You don’t need to join cells with commas or escape quotes yourself. The CSV documentation describes the writer and its workbook bridge.
How do I convert Excel to CSV in C# without Interop?
Use the Spreadsheets package and the workbook model shown above. The conversion runs in .NET; it does not launch Excel or use an Office automation object. The package is free and open source, and the downloadable project pins the package version used for this example.
Choose separate source and destination paths. Opening the source and saving a new CSV lets you keep the workbook for later edits. For a repeated import job, first agree with the receiving application on the delimiter and whether it expects display text or raw numbers. The TSV variation changes the separator by choosing a .tsv extension. Renaming an XLSX file to CSV is not a conversion; SaveAs writes the worksheet values as text.
How can I convert XLSX to CSV for free?
The code on this page uses the free OneDocument package, without a service account or an online upload. CSV is an export of values, not a workbook preservation format. A formula cell writes its cached result rather than the formula expression. With the default formatted export, numeric values use their number format, so dates become date text rather than raw date serials.
That choice matters for identifiers and amounts. Decide whether the receiving application needs what a person sees in Excel or the underlying numeric data. CSV cannot retain cell styles or merged-cell structure. The writer reports losses for formulas, cell styles, omitted sheets, merged cells and embedded objects. Consult those losses if the source contains more than an ordinary table.
By default the writer also escapes text beginning with a formula-triggering character, such as =, by adding a single quote and quoting the field. Numeric negative amounts are not changed. This helps when the exported CSV will be opened in a spreadsheet; it also means the text may not be byte-for-byte identical to the source string. Use CsvWriteOptions.FormulaInjection = CsvFormulaInjection.Escape (the default) for escaping, or CsvFormulaInjection.None when a data-only consumer needs the original text. Set CsvWriteOptions.Formatted = true (the default) for display text, or false for raw numeric values, as in the chosen-sheet variation. See the writer options and formula injection rules.