Module: Rbxl
- Defined in:
- lib/rbxl.rb,
lib/rbxl/row.rb,
lib/rbxl/cell.rb,
lib/rbxl/errors.rb,
lib/rbxl/version.rb,
lib/rbxl/empty_cell.rb,
lib/rbxl/editable_cell.rb,
lib/rbxl/read_only_cell.rb,
lib/rbxl/write_only_cell.rb,
lib/rbxl/editable_workbook.rb,
lib/rbxl/editable_worksheet.rb,
lib/rbxl/read_only_workbook.rb,
lib/rbxl/read_only_worksheet.rb,
lib/rbxl/write_only_workbook.rb,
lib/rbxl/write_only_worksheet.rb,
lib/rbxl/shared_strings_loader.rb,
ext/rbxl_native/native.c
Overview
Minimal, memory-friendly XLSX reader/writer inspired by openpyxl.
Rbxl exposes three explicit, non-overlapping modes, each picked up by Rbxl.open / Rbxl.new:
-
Rbxl.open returns a ReadOnlyWorkbook for row-by-row reads
-
Rbxl.open with
edit: truereturns a EditableWorkbook for surgical read-modify-save passes that round-trip every untouched part byte-for-byte -
Rbxl.new returns a WriteOnlyWorkbook for one-shot writes
The API is intentionally narrow so that memory usage stays predictable for large workbooks. Neither mode materializes the full workbook in memory; reads pull rows from the underlying XML one at a time, and writes accumulate only the rows added before WriteOnlyWorkbook#save.
Reading
require "rbxl"
book = Rbxl.open("report.xlsx")
sheet = book.sheet("Report")
sheet.each_row(values_only: true) { |values| p values }
book.close
Pass date_conversion: true to return Date/Time objects for numeric cells that carry a date numFmt style.
Writing
require "rbxl"
book = Rbxl.new
sheet = book.add_sheet("Report")
sheet << ["id", "name", "score"]
sheet << [1, "alice", 100]
book.save("report.xlsx")
Native extension
Requiring "rbxl/native" after "rbxl" swaps the hot worksheet XML paths for a libxml2-backed C implementation with the same observable behavior. See the README for build requirements.
Defined Under Namespace
Modules: Native, SharedStringsLoader Classes: Cell, CellValueError, ClosedWorkbookError, EditableCell, EditableCellTypeError, EditableWorkbook, EditableWorksheet, EmptyCell, Error, ReadOnlyCell, ReadOnlyWorkbook, ReadOnlyWorksheet, Row, SharedStringsTooLargeError, SheetNotFoundError, UnsizedWorksheetError, UnsupportedFormatError, WorkbookAlreadySavedError, WorkbookFormatError, WorksheetFormatError, WorksheetTooLargeError, WriteOnlyCell, WriteOnlyWorkbook, WriteOnlyWorksheet
Constant Summary collapse
- VERSION =
Gem version string, tracked with semantic versioning.
"1.4.0"
Class Attribute Summary collapse
-
.max_shared_string_bytes ⇒ Integer?
Configured shared-strings byte cap.
-
.max_shared_strings ⇒ Integer?
Configured shared-strings count cap.
-
.max_worksheet_bytes ⇒ Integer?
Per-worksheet streaming byte cap.
Instance Attribute Summary collapse
-
#coordinate ⇒ String
readonly
Excel-style coordinate such as “A1”.
-
#value ⇒ Object?
readonly
Decoded Ruby value (String, Numeric, Boolean, or
nil).
Class Method Summary collapse
-
.new(write_only: true) ⇒ Rbxl::WriteOnlyWorkbook
Creates a new workbook in write-only mode.
-
.open(path, read_only: true, edit: false, streaming: false, date_conversion: false) {|book| ... } ⇒ Rbxl::ReadOnlyWorkbook, ...
Opens an existing workbook.
Class Attribute Details
.max_shared_string_bytes ⇒ Integer?
Returns configured shared-strings byte cap.
92 93 94 |
# File 'lib/rbxl.rb', line 92 def max_shared_string_bytes @max_shared_string_bytes end |
.max_shared_strings ⇒ Integer?
Returns configured shared-strings count cap.
89 90 91 |
# File 'lib/rbxl.rb', line 89 def max_shared_strings @max_shared_strings end |
.max_worksheet_bytes ⇒ Integer?
Returns per-worksheet streaming byte cap.
95 96 97 |
# File 'lib/rbxl.rb', line 95 def max_worksheet_bytes @max_worksheet_bytes end |
Instance Attribute Details
#coordinate ⇒ String (readonly)
Returns Excel-style coordinate such as “A1”.
12 |
# File 'lib/rbxl/read_only_cell.rb', line 12 ReadOnlyCell = Data.define(:coordinate, :value) |
#value ⇒ Object? (readonly)
Returns decoded Ruby value (String, Numeric, Boolean, or nil).
12 |
# File 'lib/rbxl/read_only_cell.rb', line 12 ReadOnlyCell = Data.define(:coordinate, :value) |
Class Method Details
.new(write_only: true) ⇒ Rbxl::WriteOnlyWorkbook
Creates a new workbook in write-only mode.
The write_only keyword defaults to true and exists to mark the save-once, append-only contract explicitly. Passing write_only: false raises NotImplementedError.
188 189 190 191 192 |
# File 'lib/rbxl.rb', line 188 def new(write_only: true) raise NotImplementedError, "read/write mode is not supported; pass write_only: true" unless write_only WriteOnlyWorkbook.new end |
.open(path, read_only: true, edit: false, streaming: false, date_conversion: false) {|book| ... } ⇒ Rbxl::ReadOnlyWorkbook, ...
Opens an existing workbook.
By default opens in read-only row-by-row mode and returns a ReadOnlyWorkbook. Pass edit: true to open in read-modify-save mode and receive a EditableWorkbook instead. The two modes are wired up here at the module level so call sites pick a mode by keyword without juggling backend classes directly.
The read_only keyword defaults to true and exists to mark the intent explicitly at the call site. Passing read_only: false without also passing edit: true raises NotImplementedError — there is no promiscuous read/write mode that mixes streaming reads with surgical writes.
When a block is given, the workbook is yielded and automatically closed when the block returns (or raises), mirroring the File.open and Zip::File.open idiom:
Rbxl.open("report.xlsx") do |book|
book.sheet("Report").each_row(values_only: true) { |row| p row }
end
Rbxl.open("template.xlsx", edit: true) do |book|
book.sheet("Sheet1")["B5"].value = "Acme Inc."
book.save
end
With streaming: true, the native backend (when loaded) feeds worksheet XML to the parser in chunks pulled from the ZIP input stream instead of materializing the entire worksheet as one Ruby string. This keeps peak memory roughly independent of worksheet size and lets max_worksheet_bytes bound how much is inflated. Streaming mode is the same API and output shape — only the inflation strategy differs — and typically pays back a few percent of throughput on small sheets in exchange for the flat memory profile.
With date_conversion: true, numeric cells whose style points at a date/time numFmt (built-in ids 14–22, 27–36, 45–47, 50–58, or any custom format code containing a date/time token) are returned as Date, Time, or DateTime instead of a raw serial Float. The flag is off by default to preserve byte-for-byte behavior and skip the styles.xml parse for workbooks that don’t need it; enabling it disables the native fast path and routes reads through the Ruby worksheet parser.
streaming: and date_conversion: are read-mode options and are rejected when paired with edit: true, since the editable backend does not run worksheets through the streaming parser.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rbxl.rb', line 163 def open(path, read_only: true, edit: false, streaming: false, date_conversion: false, &block) if edit if streaming || date_conversion raise ArgumentError, "edit: true is incompatible with streaming:/date_conversion:; " \ "those options apply to the read-only mode" end return EditableWorkbook.open(path, &block) end raise NotImplementedError, "read/write mode is not supported; pass read_only: true or edit: true" unless read_only ReadOnlyWorkbook.open(path, streaming: streaming, date_conversion: date_conversion, &block) end |