RepoPilotOpen in app →

randym/axlsx

xlsx generation with charts, images, automated column width, customizable styles and full schema validation. Axlsx excels at helping you generate beautiful Office Open XML Spreadsheet documents without having to understand the entire ECMA specification. Check out the README for some examples of how easy it is. Best of all, you can validate your xlsx file before serialization so you know for sure that anything generated is going to load on your client's machine.

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 19 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Tests present
  • Stale — last commit 3y ago
  • Concentrated ownership — top contributor handles 57% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/randym/axlsx)](https://repopilot.app/r/randym/axlsx)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/randym/axlsx on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: randym/axlsx

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/randym/axlsx shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 19 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 3y ago
  • ⚠ Concentrated ownership — top contributor handles 57% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live randym/axlsx repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/randym/axlsx.

What it runs against: a local clone of randym/axlsx — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in randym/axlsx | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 1203 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>randym/axlsx</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of randym/axlsx. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/randym/axlsx.git
#   cd axlsx
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of randym/axlsx and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "randym/axlsx(\\.git)?\\b" \\
  && ok "origin remote is randym/axlsx" \\
  || miss "origin remote is not randym/axlsx (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/axlsx.rb" \\
  && ok "lib/axlsx.rb" \\
  || miss "missing critical file: lib/axlsx.rb"
test -f "lib/axlsx/package.rb" \\
  && ok "lib/axlsx/package.rb" \\
  || miss "missing critical file: lib/axlsx/package.rb"
test -f "lib/axlsx/stylesheet/styles.rb" \\
  && ok "lib/axlsx/stylesheet/styles.rb" \\
  || miss "missing critical file: lib/axlsx/stylesheet/styles.rb"
test -f "lib/axlsx/drawing/chart.rb" \\
  && ok "lib/axlsx/drawing/chart.rb" \\
  || miss "missing critical file: lib/axlsx/drawing/chart.rb"
test -f "lib/axlsx/content_type/content_type.rb" \\
  && ok "lib/axlsx/content_type/content_type.rb" \\
  || miss "missing critical file: lib/axlsx/content_type/content_type.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1203 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1173d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/randym/axlsx"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Axlsx is a Ruby gem that generates Office Open XML (.xlsx) spreadsheet files with charts, images, automated column width, conditional formatting, and full ECMA-376 schema validation. It lets developers programmatically create Excel-compatible workbooks without understanding the entire Office Open XML specification—handling serialization of lib/axlsx/drawing/, lib/axlsx/styles/, lib/axlsx/worksheet/, and content_type definitions automatically. Monolithic gem structure: lib/axlsx/ contains the core engine organized into subdirectories (lib/axlsx/content_type/, lib/axlsx/doc_props/, lib/axlsx/drawing/, lib/axlsx/styles/, lib/axlsx/worksheet/, lib/axlsx/chart/) mirroring the ECMA-376 spec. examples/ folder has 30+ runnable demo files (examples/basic_charts.rb, examples/conditional_formatting/, examples/pivot_table.rb) showing common patterns. Test suite is in spec/ (inferred from .travis.yml and Rakefile).

👥Who it's for

Ruby developers and Rails engineers who need to generate Excel reports programmatically—particularly those building data export features, financial dashboards, or batch reporting systems. Users leverage it via acts_as_xlsx (ActiveRecord mixin), axlsx_rails (view renderer), or activeadmin-axlsx (admin UI plugin) rather than raw XML manipulation.

🌱Maturity & risk

This is a production-ready but officially unmaintained project. The original repo (randym/axlsx) reached v3.0.0 in 2013 and was last maintained in 2017. It has been formally forked and moved to the caxlsx community organization (https://github.com/caxlsx/caxlsx) for active maintenance. CI/CD is set up (Travis CI, AppVeyor), but this original fork shows no recent activity.

Critical risk: the original maintainer has abandoned this repo—all development moved to caxlsx/caxlsx in 2017. New code should use the community fork, not this original. The gem has minimal external dependencies (Ruby 2.2.7+ required), but using the orphaned version introduces merge/security lag. No visible open issues or PR backlog here, because the project is no longer accepting contributions.

Active areas of work

Nothing. This is the original, abandoned randym/axlsx repo. All active development and maintenance is happening in the caxlsx community fork at https://github.com/caxlsx/caxlsx. The README explicitly warns users not to use this version.

🚀Get running

Check README for instructions.

Daily commands:

bundle exec rake spec          # Run test suite
bundle exec ruby examples/example.rb  # Run a basic demo
bundle exec ruby examples/pivot_table.rb  # Run pivot table demo

Each example/*.rb file is standalone and generates an .xlsx file in the examples/ directory.

🗺️Map of the codebase

  • lib/axlsx.rb — Main entry point that loads all axlsx modules; every contributor must understand the public API surface exposed here
  • lib/axlsx/package.rb — Core Package class that orchestrates workbook creation, serialization, and OOXML file generation; central to all spreadsheet workflows
  • lib/axlsx/stylesheet/styles.rb — Manages all styling abstractions (fonts, fills, borders, alignment); foundational for the declarative style API
  • lib/axlsx/drawing/chart.rb — Base Chart class hierarchically extended by all chart types; critical for understanding the drawing architecture
  • lib/axlsx/content_type/content_type.rb — Handles OOXML content type registration and validation; required for proper file structure generation
  • lib/axlsx/rels/relationships.rb — Manages internal relationships between workbook components; essential for understanding OOXML linking

🛠️How to make changes

Add a new chart type

  1. Create a new chart class inheriting from Chart in lib/axlsx/drawing/ (e.g., lib/axlsx/drawing/doughnut_chart.rb) (lib/axlsx/drawing/chart.rb)
  2. Implement required chart XML serialization methods (to_xml, plot_area configuration) (lib/axlsx/drawing/doughnut_chart.rb)
  3. Create corresponding series class (e.g., DoughnutSeries) in lib/axlsx/drawing/ (lib/axlsx/drawing/pie_series.rb)
  4. Register the new chart type in the Package's drawing relationship managers and content type registry (lib/axlsx/package.rb)
  5. Add example usage to examples/ directory (optional but recommended) (examples/basic_charts.rb)

Add a new cell styling option

  1. Create a new styling class in lib/axlsx/stylesheet/ (e.g., lib/axlsx/stylesheet/shadow.rb) with OOXML attribute mappings (lib/axlsx/stylesheet/font.rb)
  2. Add the new style to the Styles orchestrator in lib/axlsx/stylesheet/styles.rb (add registry and builder methods) (lib/axlsx/stylesheet/styles.rb)
  3. Expose the style property on the CellStyle class to allow end-user configuration (lib/axlsx/stylesheet/cell_style.rb)
  4. Implement to_xml_string method to generate OOXML markup for the new style (lib/axlsx/stylesheet/shadow.rb)

Add a new data validation rule

  1. Examine the existing data validation example structure in examples/data_validation.rb (examples/data_validation.rb)
  2. Create a validation class following the worksheet's add_data_validation method pattern (lib/axlsx/package.rb)
  3. Implement validation rule XML serialization (formula, type, operator) following OOXML spec (lib/axlsx/package.rb)
  4. Register validation on worksheet cells and test round-trip XLSX generation (examples/data_validation.rb)

Add conditional formatting

  1. Create a conditional formatting rule class following the pattern in examples/conditional_formatting/ (lib/axlsx/stylesheet/dxf.rb)
  2. Define rule logic (comparison operators, value/formula evaluation) and style application (examples/conditional_formatting/stop_and_go.rb)
  3. Generate OOXML conditional formatting markup (cfRule elements) with proper priority ordering (lib/axlsx/stylesheet/dxf.rb)
  4. Attach rules to worksheet cell ranges and serialize with worksheet (examples/conditional_formatting/example_conditional_formatting.rb)

🔧Why these technologies

  • Ruby DSL for spreadsheet definition — Eliminates manual OOXML boilerplate; developers declare intent (add_row, add_chart) and let the gem handle ECMA-376 serialization
  • ZIP archive (OLE2 container) — OOXML (xlsx) is a standardized ZIP format with XML parts; native Ruby Zip gem provides built-in compression and reliable file packaging
  • XML generation (via Nokogiri-like string building) — Direct XML markup generation ensures schema compliance and avoids external XML dependencies; simplifies validation against OOXML spec
  • Relationship/ContentType registry — OOXML requires explicit part relationships (workbook→sheet→chart) and MIME type declarations in [Content_Types].xml; centralized registry prevents manual errors

⚖️Trade-offs already made

  • Single-pass stylesheet deduplication (font/fill/border reuse via registry)

    • Why: OOXML requires deduplication of styles in a single stylesheet; avoids duplicate definitions that bloat file size
    • Consequence: Requires style objects to be immutable after registry insertion; cannot modify style after it has been applied to a cell
  • Chart types use class hierarchy (BarChart < Chart) rather than composition

    • Why: OOXML has distinct chart element structures (barChart, lineChart, pieChart); inheritance maps naturally to XML schema polymorphism
    • Consequence: Adding a chart variant requires subclassing; shared logic must be in the Chart base class; limits runtime chart type switching
  • Validation is optional and run before serialization, not during definition

    • Why: Full ECMA-376 validation is expensive; developers can choose to skip it for performance if confident in their usage
    • Consequence: Invalid spreadsheets may silently generate if validation is disabled; developer must test output in Excel/LibreOffice
  • No built-in formula caching or lazy evaluation

    • Why: Formulas are passed as strings; Excel evaluates them at open time, not at generation time
    • Consequence: Axlsx cannot pre-compute formula results; users must validate formulas are correct in the target Excel version

🚫Non-goals (don't propose these)

  • Real-time spreadsheet collaboration or versioning
  • Reading/parsing existing .xlsx files (write-only)
  • VBA macro embedding or Office macro security
  • PDF or other export formats
  • Automatic SQL-to-spreadsheet mapping (acts_as_axlsx is a separate gem)
  • Chart animation or dynamic conditional formatting evaluation at runtime

🪤Traps & gotchas

  1. Use caxlsx/caxlsx, not randym/axlsx: This repo is abandoned; the README warns users to switch to the community fork. Security fixes and new features only exist in caxlsx/caxlsx. 2. Ruby version requirement: Only Ruby 2.2.7+ is supported; older Rubies will fail silently. 3. Nokogiri native extensions: Requires a C compiler; Windows users may hit build issues. 4. Schema validation is optional but slow: Calling workbook.validate() before serialize can take seconds on large files; it's not the default. 5. Chart positioning is anchor-based: Charts use Axlsx::Anchor objects for positioning; pixel-perfect placement requires understanding the anchor grid system (see examples/anchor_swapping.rb).

🏗️Architecture

💡Concepts to learn

  • Office Open XML (ECMA-376) — Axlsx generates .xlsx files by assembling XML documents that conform to the ECMA-376 spec; understanding this standard is essential to debug serialization issues or extend the gem
  • ZIP-based compound document format — .xlsx files are actually ZIP archives containing XML files, relationships, and media; Axlsx uses ZipContainer to package these correctly
  • XML schema validation — Axlsx can validate generated XLSX against the ECMA-376 schema before writing; this prevents 'file corrupted' errors in Excel, though it's slow on large documents
  • Cell coordinate system (A1 notation) — Axlsx uses Excel's A1 notation (A1, B2, AA100) for cell references; understanding row/column indices is critical for merged cells, named ranges, and conditional formatting
  • Drawing relationships and anchoring — Charts and images in OOXML are drawn objects anchored to cells via relationship IDs; Axlsx abstracts this but understanding Anchor objects explains why chart positioning can be finicky
  • Builder pattern (fluent API) — Axlsx uses method chaining and block-based builders (e.g., package.workbook do |wb| wb.add_worksheet) to make spreadsheet code readable and composable
  • Number format codes (numFmtId) — Excel cells reference number format codes (currency, date, percentage); Axlsx manages these IDs and exposes them via the Styles API, but off-by-one errors in format IDs can corrupt output
  • caxlsx/caxlsx — The actively maintained community fork of this project; all security updates and new features are here, not in randym/axlsx
  • caxlsx/acts_as_xlsx — Official Rails mixin that pairs with Axlsx—lets you call .to_xlsx on ActiveRecord collections
  • caxlsx/axlsx_rails — Rails view renderer for Axlsx—lets you write .xlsx.axlsx template files instead of putting generation logic in controllers
  • caxlsx/activeadmin-axlsx — Plugin for ActiveAdmin that generates downloadable XLSX reports via DSL
  • jmcgehee/simple_xlsx_writer — Lightweight alternative to Axlsx for simple Excel generation without charts or images; good for comparison of API philosophies

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for Drawing module classes

The lib/axlsx/drawing directory contains 20+ chart and graphic-related classes (area_chart.rb, bar_chart.rb, line_chart.rb, bubble_chart.rb, etc.) but based on the file structure, there's no visible spec/test directory. Charts are complex objects that serialize to XML, making them critical for xlsx validity. Adding unit tests for chart initialization, property validation, and XML serialization would prevent regressions and ensure all chart types work correctly.

  • [ ] Create spec/axlsx/drawing directory structure mirroring lib/axlsx/drawing
  • [ ] Add unit tests for lib/axlsx/drawing/bar_chart.rb covering initialization, axis configuration, and series addition
  • [ ] Add unit tests for lib/axlsx/drawing/chart.rb base class covering validation and XML serialization
  • [ ] Add integration test that creates multiple chart types and validates generated xlsx file opens correctly
  • [ ] Ensure tests validate schema compliance using the project's mentioned schema validation capability

Add GitHub Actions CI workflow to replace Travis CI

.travis.yml exists and Travis CI badge is in README, but Travis CI has deprecated free builds for open source. The repo should migrate to GitHub Actions (native to GitHub, free for public repos, more flexible). This will keep CI running automatically and provide clearer status to contributors. The appveyor.yml suggests Windows testing was already attempted.

  • [ ] Create .github/workflows/test.yml with Ruby matrix testing (2.6, 2.7, 3.0, 3.1+)
  • [ ] Configure workflow to run bundle install && bundle exec rake (following Rakefile conventions)
  • [ ] Add workflow to test multiple OS: ubuntu-latest, windows-latest, macos-latest
  • [ ] Update README.md badges to point to GitHub Actions instead of Travis CI
  • [ ] Keep .travis.yml for backward compatibility but add note in README about migration

Add validation tests for ContentType and DocProps serialization

lib/axlsx/content_type/ and lib/axlsx/doc_props/ contain classes (abstract_content_type.rb, content_type.rb, default.rb, override.rb, app.rb, core.rb) that generate XML metadata critical for xlsx validity. These are foundational to every generated file. Tests should verify XML structure, required attributes, and edge cases (special characters, unicode, empty values) to prevent subtle xlsx corruption bugs.

  • [ ] Create spec/axlsx/content_type/content_type_spec.rb testing ContentType.new, adding overrides/defaults, and to_xml output structure
  • [ ] Create spec/axlsx/doc_props/core_spec.rb testing metadata fields (creator, modified, title) with special characters and unicode
  • [ ] Create spec/axlsx/doc_props/app_spec.rb testing application properties and sheet counts
  • [ ] Add tests validating XML against ECMA-376 schema for [Content_Types].xml and docProps/app.xml
  • [ ] Test edge cases: missing optional fields, extremely long strings, special XML characters

🌿Good first issues

  • Add test coverage for lib/axlsx/drawing/radar_chart.rb and lib/axlsx/drawing/bubble_chart.rb (these classes exist but no examples/radar_chart_example.rb or examples/bubble_chart_example.rb in the examples/ folder; contribute a runnable demo and corresponding test case).
  • Document the validator system: lib/axlsx/util/validators.rb has custom validators for cell types, numeric ranges, and enums, but the main README lacks a 'Validation API' section. Write a doc file with concrete validator examples (e.g., required_attribute validator, required_relationship validator).
  • Implement streaming / low-memory mode for large datasets: Currently Package serializes the entire workbook in memory. Add a stream-write option to Worksheet that flushes rows to disk incrementally (like openpyxl's write_only mode). This is a significant feature gap visible in the lack of streaming examples.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 8e7b4b3 — Merge pull request #650 from westonganger/patch-2 (noniq)
  • c1e1b07 — Clarify caxlsx notice (westonganger)
  • 2891eb2 — Fix link to caxlsx (noniq)
  • a5e75ac — Update README to prominently mention caxlsx (noniq)
  • c593a08 — Merge pull request #532 from olleolleolle/patch-3 (randym)
  • 251fb80 — Travis: use jruby-9.1.17.0 (olleolleolle)
  • 73d9477 — chore(examples): include examples for customized locking and single print area specification with defined names (randym)
  • 5e1f560 — chore(examples): do more crazy in the data_validation example (randym)
  • cef4664 — chore(examples): update data validation example to show raw list validation (randym)
  • ab9b221 — Merge pull request #575 from randym/release-3.0.0 (randym)

🔒Security observations

Failed to generate security analysis.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · randym/axlsx — RepoPilot