---
title: "Import CSV into an Excel workbook in C#"
url: https://recursiveai.org/onedocument/cookbook/import-csv-to-workbook/
description: "Import CSV into an Excel workbook in C# with OneDocument for .NET 10, with typed inspection, a runnable example and actual output."
version: "1.0.0"
---

# Import CSV into an Excel workbook in C#

**OneDocument** is a free, open-source Word, Excel and PowerPoint document library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneDocument.Spreadsheets) · [GitHub](https://github.com/recursive-ai-oss/onedocument-csharp) · [Docs](https://recursiveai.org/onedocument/docs/) · [Download example (.zip)](https://recursiveai.org/onedocument/cookbook/import-csv-to-workbook/import-csv-to-workbook.zip)

Leading zeros such as 007 stay as text.

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

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

```csharp
using RecursiveAI.OneDocument.Spreadsheets.Csv;
using var book = CsvDocument.ToWorkbook(
    "stock.csv");
book.SaveAs("stock.xlsx");
Console.WriteLine(book.Sheets[0]["A2"].Text);
```

`stock.csv` is UTF-8 text included in the example:

```csv
Id,Item,Quantity
007,"Pens, blue",12
008,Paper,5
```

The snippet prints:

```text
007
```

Unzip [the example](https://recursiveai.org/onedocument/cookbook/import-csv-to-workbook/import-csv-to-workbook.zip), then `dotnet run`.

## The full program

The snippet at the top writes `stock.xlsx`. The full program makes the comma delimiter, UTF-8 encoding, header row and value-inference policy explicit, then prints cell types and any parsing defects.

```csharp
using System.Text;
using RecursiveAI.OneDocument;
using RecursiveAI.OneDocument.Diagnostics;
using RecursiveAI.OneDocument.Spreadsheets.Csv;

var defects = new DefectCollection();
using var book = CsvDocument.ToWorkbook("stock.csv", new CsvImportOptions
{
    HasHeader = true,
    SheetName = "Stock",
    Read = new CsvReadOptions { Delimiter = ',', Encoding = Encoding.UTF8 },
    Values = new CsvValueOptions { Infer = true, PreserveLeadingZeros = true }
}, new OpenContext(defects: defects));
var sheet = book.Sheets[0];
foreach (string address in new[] { "A2", "B2", "C2" })
    Console.WriteLine($"{address}: {sheet[address].Value.Kind} {sheet[address].Text}");
Console.WriteLine($"Defects: {defects.Count}");
foreach (var defect in defects)
    Console.WriteLine(defect.Code);
book.SaveAs("stock.xlsx");
Console.WriteLine("Wrote stock.xlsx");
```

```text
A2: Text 007
B2: Text Pens, blue
C2: Number 12
Defects: 0
Wrote stock.xlsx
```

An unreadable source throws an I/O exception; recoverable CSV problems appear in the defect collection, so inspect it before accepting the import.

## Variations

Keep every field as text instead of inferring numeric values:

```csharp
using RecursiveAI.OneDocument.Spreadsheets.Csv;
using var book = CsvDocument.ToWorkbook("stock.csv",
    new CsvImportOptions
    {
        Values = new CsvValueOptions { Infer = false }
    });
Console.WriteLine(book.Sheets[0]["C2"].Value.Kind);
```

```text
Text
```

## Related recipes

[Export XLSX as CSV](https://recursiveai.org/onedocument/cookbook/convert-xlsx-to-csv/) · [Read Excel cells](https://recursiveai.org/onedocument/cookbook/read-excel-file/)

## The short answer

Use `CsvDocument.ToWorkbook` to import CSV data into a OneDocument workbook, then `SaveAs` with an `.xlsx` destination. Unlike changing a filename’s extension, this creates an Excel workbook with typed worksheet cells. The defaults recognize numbers, dates, booleans and error values while preserving whole-number identifiers written with leading zeros.

The sample tests two common import mistakes: the comma inside `"Pens, blue"` must not become another column, and `007` must not become the number 7. Its full-program output shows the item as one text cell, the identifier as text, and the quantity as a number. The shorter snippet uses the default policies; the full program records the choices explicitly for a repeatable import.

## How do I import CSV into an Excel workbook in C#?

Pass `CsvImportOptions` when the source format is known. `Read` configures splitting and decoding, `Values` configures type inference, `HasHeader` keeps the first record as text, and `SheetName` names the resulting worksheet. These are separate decisions: choosing a comma delimiter says nothing about whether a field is an identifier or a numeric measure.

The [CSV documentation](https://recursiveai.org/onedocument/docs/csv/) describes a forward-only text reader and a bridge into the editable workbook model. The reader understands quoted delimiters, quoted line breaks and doubled quote characters. Splitting lines on commas is not equivalent: it would break the sample’s item name into multiple fields.

Use the defect collection shown in the program to decide whether an import is acceptable. Ragged records are returned without padding or truncation and report `csv.ragged-record`. An unterminated quoted field is repaired at the end of input and reported. A successfully returned workbook therefore does not, by itself, mean that the source was free of defects. For a strict import workflow, inspect the defects before saving or handing the workbook to another system.

## How do I convert CSV to XLSX in C#?

Import the CSV, inspect the resulting cells, then save the workbook with an `.xlsx` extension. The sample writes one worksheet called Stock. CSV does not contain multiple sheets, styles, charts or a workbook structure to preserve; the importer creates that workbook structure from the text table.

Keep leading zeros when values are identifiers. `PreserveLeadingZeros = true` is the default and is explicit in the full program. If your application requires every field to remain text, set `Infer = false` as the variation does. That also makes a quantity such as `12` text rather than a number, so later arithmetic needs a deliberate conversion. Quoting alone is not a type policy: CSV quoting controls how a field is split, not what type it becomes.

Encoding is another independent choice. The full program specifies UTF-8 because the included file is UTF-8. A byte-order mark takes precedence over the configured encoding. Without a mark or an explicit encoding, the reader uses valid UTF-8, otherwise Windows-1252 with `csv.encoding-assumed`. Check the producer’s encoding rather than assuming every CSV is UTF-8.

CSV formula-looking fields remain text by default. A value beginning with `=` is data here, not an instruction to calculate. This is distinct from a real workbook formula that you explicitly assign through the worksheet API. The import options let you control inference without pretending that CSV itself carries cell types.
