Skip to main content

Search OfficeIMO

Enter a topic, API type, or PowerShell command.

Documentation Search all OfficeIMO/

CSV Documents

Edit on GitHub

Overview of the OfficeIMO.CSV package for strongly-typed CSV document workflows. Includes practical examples, limits, and API links.

The OfficeIMO.CSV package provides a fluent, strongly typed CSV document model for .NET. It supports reading, writing, validation, schema enforcement, streaming, and object mapping with zero external dependencies.

Key Classes

ClassDescription
CsvDocumentRoot class for creating, loading, and saving CSV data.
CsvRowRepresents a single data row with typed column access.
CsvSchemaDefines column names, types, and validation rules.
CsvValidatorValidates rows against a schema.
CsvRowWriterWrites objects, projected rows, and data readers without materializing a document.
OfficeIMO.Data.RowMapper<T>Defines neutral explicit typed assignments for trimming and NativeAOT-sensitive code.

Creating a CSV Document

using OfficeIMO.CSV;

var csv = CsvDocument.Create()
    .WithDelimiter(',')
    .WithHeader("Name", "Age", "City")
    .AddRow("Alice", "30", "New York")
    .AddRow("Bob", "25", "London")
    .AddRow("Carol", "35", "Tokyo");

csv.Save("people.csv");

Creating from Objects

Generate a CSV document from any collection of objects. Column names are inferred from property names or dictionary keys:

var employees = new[] {
    new { Name = "Alice", Department = "Engineering", Salary = 95000 },
    new { Name = "Bob", Department = "Design", Salary = 85000 },
    new { Name = "Carol", Department = "Marketing", Salary = 90000 },
};

var csv = CsvDocument.FromObjects(employees);
csv.Save("employees.csv");

You can customize the delimiter, culture, and encoding:

using System.Globalization;

var csv = CsvDocument.FromObjects(
    employees,
    delimiter: ';',
    culture: new CultureInfo("de-DE")
);

Loading a CSV File

var csv = CsvDocument.Load("data.csv");

foreach (CsvRow row in csv.AsEnumerable()) {
    Console.WriteLine($"{row.AsString("Name")}: {row.AsInt32("Age")}");
}

Reader options

using System.Text;

var csv = CsvDocument.Load("data.csv", new CsvLoadOptions {
    Delimiter = '\t',
    HasHeaderRow = true,
    Encoding = Encoding.UTF8
});

Forward-only reading

CsvLoadOptions supplies parsing settings to Load and Parse. CsvReaderOptions supplies parsing and projection settings to OpenReader. Shared parsing concepts use the same property names and defaults on both types. For large files, open a forward-only CsvDataReader instead of loading a document:

using CsvDataReader reader = CsvDocument.OpenReader("large.csv");

while (reader.Read()) {
    Console.WriteLine(reader.GetString(reader.GetOrdinal("Name")));
}

Schema and Validation

Define a schema to enforce column types and constraints:

using System.Text.RegularExpressions;

var validated = csv
    .EnsureSchema(schema => schema
        .Column("Name").AsString().Required()
        .Column("Age").AsInt32().Required().Validate(v => (int)v! >= 0 && (int)v! <= 150, "Age must be between 0 and 150.")
        .Column("Email").AsString().Optional().Validate(
            v => v is null || Regex.IsMatch((string)v, @"^[\w.-]+@[\w.-]+\.\w+$"),
            "Email must be a valid address."))
    .Validate(out var errors);

foreach (var error in errors) {
    Console.WriteLine($"Row {error.RowIndex}, Column '{error.ColumnName}': {error.Message}");
}

Object Mapping

Map CSV rows to strongly-typed objects:

public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
}

var csv = CsvDocument.Load("people.csv");
var people = csv.RowsAs<Person>().ToList();

foreach (var person in people) {
    Console.WriteLine($"{person.Name} ({person.Age}) lives in {person.City}");
}

Save Options

using System.Text;

csv.Save("output.csv", new CsvSaveOptions {
    Delimiter = ',',
    IncludeHeader = true,
    Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)
});

Writing to a Stream

using var stream = new MemoryStream();
csv.Save(stream);

Custom Delimiters

// Tab-separated
var tsv = CsvDocument.Create().WithDelimiter('\t');

// Semicolon-separated (common in European locales)
var csv = CsvDocument.Create().WithDelimiter(';');

// Pipe-separated
var psv = CsvDocument.Create().WithDelimiter('|');

Culture-Aware Formatting

using System.Globalization;

var csv = CsvDocument.Create()
    .WithCulture(new CultureInfo("fr-FR"))
    .WithHeader("Produit", "Prix")
    .AddRow("Widget A", "9,99")   // French decimal separator
    .AddRow("Widget B", "14,99");

Task guides

Convert to other formats

To turn CSV or TSV into JSON, JSON Lines, YAML, TOML, XML or an Excel worksheet, or the other way round, see data conversions.

API used on this page

Example source