Talaan 0.3.0

dotnet add package Talaan --version 0.3.0
                    
NuGet\Install-Package Talaan -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Talaan" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Talaan" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Talaan" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Talaan --version 0.3.0
                    
#r "nuget: Talaan, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Talaan@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Talaan&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Talaan&version=0.3.0
                    
Install as a Cake Tool

<div align="center"> <img src="https://raw.githubusercontent.com/BaryoDev/Talaan/master/assets/icon.png" width="96" height="96" alt="Talaan logo" /> <h1>Talaan</h1> <p><em>A zero-dependency spreadsheet & CSV reader for .NET.</em></p> </div>


Talaan (Filipino for record / list / table) reads and writes .xlsx and CSV files as a simple, typed cell grid, with no external dependencies. No Excel Interop, no ClosedXML, no OpenXML SDK. An .xlsx is just a zip of XML, and Talaan walks those parts directly using only the .NET base class library (System.IO.Compression + System.Xml).

Why

  • Zero dependencies. Nothing to audit, nothing to update, no transitive surprises. One small assembly.
  • Typed cells. Numbers come back as numbers, dates as DateTime, booleans as bool, not stringly-typed guesses. Excel serial dates and shared strings are resolved for you.
  • Raw grid, no magic. Talaan hands you the sheet exactly as laid out. You decide which row is the header and which rows to skip, which suits real-world files with title rows, sections, and blanks.

Install

dotnet add package Talaan

Quick start

using Talaan;

// From a file…
SheetData sheet = Spreadsheet.ReadFile("members.xlsx");

// …or a stream (an upload, say), dispatched by file name:
SheetData sheet = Spreadsheet.Read(uploadStream, fileName);

for (int r = 0; r < sheet.RowCount; r++)
{
    CellValue name = sheet.At(r, 1);   // row r, column B
    if (name.Kind == CellKind.Text)
        Console.WriteLine(name.Text);
}

Every cell is a CellValue:

public readonly record struct CellValue(
    CellKind Kind,        // Empty | Text | Number | Date | Boolean
    string?  Text,
    double?  Number,
    DateTime? Date,
    bool?    Boolean);

cell.IsBlank      // empty, or whitespace-only text
cell.AsString()   // best-effort display: invariant numbers, ISO-8601 dates

Supported formats

Format Extension Notes
Excel .xlsx Read: first worksheet. Write: every sheet. Shared strings, inline strings, booleans, numbers, and style-based date detection.
CSV .csv, .txt RFC-4180: quoted fields, escaped "", embedded commas and newlines.
TSV .tsv Tab-delimited.

You can also bypass detection: Spreadsheet.Read(stream, SpreadsheetFormat.Xlsx).

Reading a CSV in a non-UTF-8 encoding

CSV defaults to UTF-8. A file exported by "Excel on Windows > CSV (Comma delimited)" is usually Windows-1252 with no byte-order mark, so it needs an explicit encoding:

using System.Text;

// Code page 1252 needs the CodePages package, which Talaan does not depend on:
//   dotnet add package System.Text.Encoding.CodePages
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
SheetData sheet = Spreadsheet.ReadFile("members.csv", Encoding.GetEncoding(1252));

Encoding.Latin1 is built in and works without the package, but it is not the same as 1252: bytes 0x80 to 0x9F (the euro sign, curly quotes, dashes) come back as control characters.

CsvReader.Read(stream, encoding) takes the same encoding for CSV/TSV without going through Spreadsheet.

Writing

var people = new SheetData(new IReadOnlyList<CellValue>[]
{
    new[] { CellValue.OfText("name"), CellValue.OfText("joined"), CellValue.OfText("active") },
    new[] { CellValue.OfText("Ana"), CellValue.OfDate(new DateTime(2024, 5, 6)), CellValue.OfBoolean(true) },
}, name: "People");
var archive = new SheetData(new IReadOnlyList<CellValue>[]
{
    new[] { CellValue.OfText("name"), CellValue.OfNumber(42) },
}, name: "Archive");
using var responseStream = new MemoryStream();

// To a file. The extension picks the format and an existing file is overwritten.
Spreadsheet.WriteFile("members.xlsx", new[] { people, archive });  // every sheet
Spreadsheet.WriteFile("members.csv", new[] { people });               // first sheet only
Spreadsheet.WriteFile("members.tsv", new[] { people });               // first sheet only, tab-delimited

// To a stream. The stream is left open.
Spreadsheet.WriteXlsx(responseStream, new[] { people });
CsvWriter.Write(responseStream, people, delimiter: ',');             // Talaan.Csv
  • Text is written as inline strings, so "00123" stays text. Booleans and numbers are typed cells. Numbers use invariant culture and round-trip exactly. NaN and infinity throw.
  • Dates are written as serial numbers. A date with no time gets the number format yyyy-mm-dd, one with a time gets yyyy-mm-dd hh:mm:ss. Both read back as CellKind.Date. Dates before 1900-03-01 throw, because Excel's serials for them differ from .NET's by a day.
  • Empty cells are skipped. Cell references stay correct past column Z, up to XFD.
  • Characters XML 1.0 forbids (most control characters, lone surrogates) are dropped from text and sheet names.
  • Sheet names: a null or blank name becomes Sheet{N} (its 1-based position). A name over 31 characters, containing any of [ ] : * ? / \, starting or ending with an apostrophe, containing a tab, CR or LF, named History (Excel reserves it), or repeating another name (case-insensitive) throws ArgumentException. An empty sheet list also throws.
  • CSV and TSV follow RFC 4180: a field is quoted when it holds the delimiter, a quote, CR or LF, and inner quotes are doubled. Rows end with CRLF. Cells are written with AsString(). A row with one empty cell is written as "" so it is not a blank line.
  • CSV encoding is UTF-8 without a byte-order mark. Excel on Windows opens a BOM-less CSV in the system code page, so non-ASCII text can show up garbled. Import it with "From Text/CSV" and pick UTF-8, or write the file yourself with a BOM.
  • Formulas. Text starting with =, +, - or @ is written as is. A CSV opened in Excel treats it as a formula, so escape or reject that text first if the data is untrusted. In .xlsx it is stored as a string and is not evaluated.
  • Extreme numbers. Values outside Excel's double range (denormals such as double.Epsilon) are written as given, and Excel may read them as 0.
  • Limits. Text over 32767 characters in a cell throws. Nothing is written to a stream when any sheet or cell is rejected, and WriteFile writes a temp file then moves it into place.

Design notes

  • Dates. .xlsx stores dates as serial numbers; Talaan inspects the workbook stylesheet (cellXfs to number format) to decide whether a numeric cell is a date, then converts via the OLE Automation epoch. Ambiguous m (month vs. minute) is ignored in favour of unambiguous y/d.
  • Column alignment. Cell references (A1, AB12) are honoured, so skipped/blank cells become CellValue.Empty and columns stay aligned.
  • Streaming input. Non-seekable streams are buffered automatically for zip access.

Scope (by design)

Reading returns the first worksheet only. Formulas are returned by their last cached result. Writing produces a plain workbook: values and the date formats above, no styling, formulas, column widths or merged cells. If you need those, this isn't that library, and that is the point.

License

MPL-2.0 © BaryoDev

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Talaan:

Package Downloads
BarakoCMS.Import

Optional bulk-import module for barakoCMS: analyze .xlsx/CSV uploads and bulk-create content. Zero-dependency parsing via Talaan.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 3,288 10/13/2026
0.2.0 3,011 9/24/2026
0.1.0 11,300 7/15/2026

0.3.0
New:
- Spreadsheet.WriteXlsx(Stream, IEnumerable<SheetData>) writes every sheet to an .xlsx and leaves the stream open.
- Spreadsheet.WriteFile(path, sheets) picks the format from the extension (.xlsx every sheet, .csv and .tsv the first sheet), writes a temp file and moves it into place.
- CsvWriter.Write(Stream, SheetData, char delimiter) and CsvWriter.Write(Stream, IEnumerable<SheetData>) write RFC 4180 CSV or TSV as UTF-8 without a BOM.

Writing rules:
- Text is written as inline strings, so "00123" stays text. Numbers use invariant culture and round-trip. NaN and infinity throw.
- Dates are serial numbers formatted yyyy-mm-dd, or yyyy-mm-dd hh:mm:ss when they have a time, and read back as dates. Dates before 1900-03-01 throw.
- Invalid sheet names, an empty sheet list and cell text over 32767 characters throw ArgumentException, and nothing is written.
- Characters XML 1.0 forbids are dropped from text and sheet names.
- No styling, formulas, column widths or merged cells.