xlsx
Version, currently main branch1 version
- main branchlatestMay 14, 2026
github.com/nogginly/xlsx.cr
A Crystal shard for reading and writing XLSX files compatible with Excel.
Installation
# Add this to your shard.yml
dependencies:
xlsx:
github: nogginly/xlsx.cr
branch: mainmain is a branch, not a release, so this tracks it rather than pinning a version.
Then run:
shards installshard.yml
- Crystal
- no constraint declared
- License
- MIT
- Author
- nogginly
- Target
csv2xlsxfrom samples/csv2xlsx.cr
Dependencies
Development Dependencies
- ameba*github: crystal-ameba/amebadev
- spectator*gitlab: arctic-fox/spectatordev
README
xlsx
A Crystal shard for reading and writing XLSX files compatible with Excel.
See DISCLOSURE for information how AI is used by this project.
Installation
-
Add the dependency to your
shard.yml:dependencies: xlsx: github: nogginly/xlsx.cr -
Run
shards install
Usage
require "xlsx"
2. Creating a workbook
2.1. Simple CSV‑style builder
File.open("output.xlsx", "w") do | io |
XLSX.build(io) do |b|
b.row("Name", "Age")
b.row("Alice", 30)
b.row("Bob", 24.5)
end
end
The block receives a Builder that accumulates rows and writes to the file.
2.2. Multiple sheets with a span
XLSX.build(File.open("multi.xlsx", "w"),
sheets: ["Data", "Summary"]) do |sheet|
# `sheet` is a `SheetBuilder`
sheet.append_row("Header A", "Header B")
1.upto(5) do |i|
sheet.append_row("Row #{i}A", i)
end
end
2.3. Template‑based build
File.open("template.xlsx") do |template|
File.open("filled.xlsx", "w") do |out|
XLSX.build(out, template: template) do |sheet|
# `sheet` starts with template content
sheet.append_row("Date", Time.utc)
end
end
end
The template file is read but not modified; only the new sheet(s) are written to out.
3. Reading an existing workbook
doc = XLSX::Document.open("existing.xlsx")
# Iterate sheets
doc.each do |sheet|
puts "Sheet: #{sheet.name}"
sheet.each_row do |row, row_id|
row.each_cell do |value, col_id|
puts " R#{row_id}C#{col_id}: #{value}"
end
end
end
You can also fetch a sheet by name:
sheet = doc["Data"]
row = sheet.row(2) # row 2 if present
value = row[3] # cell at column 3
4. Working with different cell types
| Type | How to construct | Example |
|---|---|---|
String | Plain string | "Hello" |
XLSX::InlineStr | #new("text") | ...new("inline") |
Int64 / Float64 | Integer or float literals | 42, 3.14 |
Bool | true / false | |
XLSX::DateValue | #date_time(t), #date_only(t), #time_only(t) | ...date_time(Time.utc) |
XLSX::Formula | #new(formula, pre_calc_value) | ...new("SUM(A1:A5)", 42) |
XLSX::SharedFormulaRef | #new(index, pre_calc_value) | |
XLSX::Empty | INSTANCE (singleton constant ) |
When appending rows you can mix types freely:
builder.append_row("Alice", 30, XLSX::DateValue.date_only(Time.new(2024, 4, 20)))
Development
See DEVELOPMENT
Contributions, by invitation!
With apologies, at this time contributions are by invitation only and limited to people I know and see often.
These are early days for AskElelem and I am busy with family and work.
At this time I want to work on this at a manageable pace.
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This branch
- Branch
main- Seen
- May 14, 2026
- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/nogginly/xlsx.cr
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 14, 2026
- Synced
- Aug 14, 2026
- Versions
- 1