Talaan 0.3.0
dotnet add package Talaan --version 0.3.0
NuGet\Install-Package Talaan -Version 0.3.0
<PackageReference Include="Talaan" Version="0.3.0" />
<PackageVersion Include="Talaan" Version="0.3.0" />
<PackageReference Include="Talaan" />
paket add Talaan --version 0.3.0
#r "nuget: Talaan, 0.3.0"
#:package Talaan@0.3.0
#addin nuget:?package=Talaan&version=0.3.0
#tool nuget:?package=Talaan&version=0.3.0
<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 asbool, 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 getsyyyy-mm-dd hh:mm:ss. Both read back asCellKind.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, namedHistory(Excel reserves it), or repeating another name (case-insensitive) throwsArgumentException. 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.xlsxit 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
WriteFilewrites a temp file then moves it into place.
Design notes
- Dates.
.xlsxstores dates as serial numbers; Talaan inspects the workbook stylesheet (cellXfsto number format) to decide whether a numeric cell is a date, then converts via the OLE Automation epoch. Ambiguousm(month vs. minute) is ignored in favour of unambiguousy/d. - Column alignment. Cell references (
A1,AB12) are honoured, so skipped/blank cells becomeCellValue.Emptyand 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 | Versions 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. |
-
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.
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.