Visual Examples Gallery

This gallery showcases xlsxrb DSL usage side-by-side with the visual rendering in LibreOffice Calc.

◄ Back to README

Capability Overview

Feature Visual Preview Download XLSX Link to Detail
Align Horizontal Align Horizontal Download View Code & Detail
Align Horizontal Fill Align Horizontal Fill Download View Code & Detail
Align Horizontal Justify Align Horizontal Justify Download View Code & Detail
Align Indent Align Indent Download View Code & Detail
Align Text Rotation Align Text Rotation Download View Code & Detail
Align Text Wrap Align Text Wrap Download View Code & Detail
Align Vertical Align Vertical Download View Code & Detail
Basic Data Basic Data Download View Code & Detail
Borders Borders Download View Code & Detail
Cell Booleans Cell Booleans Download View Code & Detail
Cell Dates Cell Dates Download View Code & Detail
Cell Formulas Cell Formulas Download View Code & Detail
Cell Num Currency Jpy Cell Num Currency Jpy Download View Code & Detail
Cell Num Custom Colors Cell Num Custom Colors Download View Code & Detail
Cell Num Fractions Cell Num Fractions Download View Code & Detail
Cell Num Percent Decimals Cell Num Percent Decimals Download View Code & Detail
Cell Num Scientific Cell Num Scientific Download View Code & Detail
Cell Numbers Cell Numbers Download View Code & Detail
Cell Rich Text Cell Rich Text Download View Code & Detail
Cell Times Cell Times Download View Code & Detail
Cf Begins With Cf Begins With Download View Code & Detail
Cf Cell Between Cf Cell Between Download View Code & Detail
Cf Cell Equal To Cf Cell Equal To Download View Code & Detail
Cf Cell Greater Equal Cf Cell Greater Equal Download View Code & Detail
Cf Cell Greater Than Cf Cell Greater Than Download View Code & Detail
Cf Cell Less Than Cf Cell Less Than Download View Code & Detail
Cf Color Scale Cf Color Scale Download View Code & Detail
Cf Contains Text Cf Contains Text Download View Code & Detail
Cf Data Bar Cf Data Bar Download View Code & Detail
Cf Ends With Cf Ends With Download View Code & Detail
Cf Expression Formula Cf Expression Formula Download View Code & Detail
Cf Icon Set Cf Icon Set Download View Code & Detail
Chart Area Chart Area Download View Code & Detail
Chart Area Stacked Chart Area Stacked Download View Code & Detail
Chart Bar Chart Bar Download View Code & Detail
Chart Bar Percent Stacked Chart Bar Percent Stacked Download View Code & Detail
Chart Bar Stacked Chart Bar Stacked Download View Code & Detail
Chart Doughnut Chart Doughnut Download View Code & Detail
Chart Line Chart Line Download View Code & Detail
Chart Line Stacked Chart Line Stacked Download View Code & Detail
Chart Pie Chart Pie Download View Code & Detail
Chart Radar Chart Radar Download View Code & Detail
Chart Scatter Chart Scatter Download View Code & Detail
Col Grouping Col Grouping Download View Code & Detail
Col Width Tall Col Width Tall Download View Code & Detail
Col Widths Col Widths Download View Code & Detail
Conditional Formatting Conditional Formatting Download View Code & Detail
Embedded Images Embedded Images Download View Code & Detail
Fill Gradients Fill Gradients Download View Code & Detail
Fill Patterns Fill Patterns Download View Code & Detail
Fill Solid Colors Fill Solid Colors Download View Code & Detail
Fonts Fonts Download View Code & Detail
Interactive Autofilter Interactive Autofilter Download View Code & Detail
Interactive Comments Interactive Comments Download View Code & Detail
Interactive Validation Custom Interactive Validation Custom Download View Code & Detail
Interactive Validation Date Interactive Validation Date Download View Code & Detail
Interactive Validation List Interactive Validation List Download View Code & Detail
Interactive Validation Range Interactive Validation Range Download View Code & Detail
Interactive Validation Text Length Interactive Validation Text Length Download View Code & Detail
Interactive Validation Time Interactive Validation Time Download View Code & Detail
Japanese Text Japanese Text Download View Code & Detail
Merge Freeze Merge Freeze Download View Code & Detail
Page Grid Lines Print Page Grid Lines Print Download View Code & Detail
Page Header Footer Page Header Footer Download View Code & Detail
Page Headings Print Page Headings Print Download View Code & Detail
Page Margins Narrow Page Margins Narrow Download View Code & Detail
Page Margins Wide Page Margins Wide Download View Code & Detail
Page Orientation Landscape Page Orientation Landscape Download View Code & Detail
Page Paper Size A3 Page Paper Size A3 Download View Code & Detail
Row Grouping Row Grouping Download View Code & Detail
Row Height Tall Row Height Tall Download View Code & Detail
Row Heights Row Heights Download View Code & Detail
Sheet Tab Colors Sheet Tab Colors Download View Code & Detail
Sparkline Column Sparkline Column Download View Code & Detail
Sparkline Line Sparkline Line Download View Code & Detail
Styles Fonts Fills Styles Fonts Fills Download View Code & Detail
View Show Grid Lines View Show Grid Lines Download View Code & Detail
View Zoom Scale View Zoom Scale Download View Code & Detail
Workbook Three Sheets Workbook Three Sheets Download View Code & Detail

Align Horizontal

Download .xlsx

Demonstrates horizontal text alignment (left, center, right).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_horizontal.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("left") { |s| s.align_horizontal("left") }
  w.add_style("center") { |s| s.align_horizontal("center") }
  w.add_style("right") { |s| s.align_horizontal("right") }
  w.add_sheet("Alignment") do |s|
    s.set_print_option(:grid_lines, true)
    s.set_column(0, width: 20)
    s.set_column(1, width: 20)
    s.set_column(2, width: 20)
    s.add_row(["Left", "Center", "Right"], styles: { 0 => "left", 1 => "center", 2 => "right" })
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Alignment (Xlsxrb.read) ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first

row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_horizontal = #{align_h.inspect}"
end

Console Output

=== Read Alignment (Xlsxrb.read) ===
Cell A1 ('Left'): align_horizontal = "left"
Cell B1 ('Center'): align_horizontal = "center"
Cell C1 ('Right'): align_horizontal = "right"

Align Horizontal Fill

Download .xlsx

Demonstrates horizontal fill alignment (repeats value to fill cell width).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_horizontal_fill.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("fill_align") { |s| s.align_horizontal("fill") }
  w.add_sheet("Alignment") do |s|
    s.set_column(0, width: 30)
    s.add_row(["X "], styles: { 0 => "fill_align" })
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('X '): align_h="fill", align_v=nil, wrap=nil, indent=nil, rotation=nil, shrink=nil

Align Horizontal Justify

Download .xlsx

Demonstrates horizontal justify text alignment.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_horizontal_justify.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("justify_align") do |s|
    s.align_horizontal("justify")
    s.wrap_text(true)
  end
  w.add_sheet("Alignment") do |s|
    s.set_column(0, width: 25)
    s.add_row(["Justified alignment wraps and distributes text evenly."], styles: { 0 => "justify_align" })
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Justified alignment wraps and distributes text evenly.'): align_h="justify", align_v=nil, wrap=true, indent=nil, rotation=nil, shrink=nil

Align Indent

Download .xlsx

Demonstrates text indentation inside cells.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_indent.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("indent_1") { |s| s.align_horizontal("left").indent(1) }
  w.add_style("indent_3") { |s| s.align_horizontal("left").indent(3) }
  w.add_sheet("Indent") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)
    s.add_row(["No Indent"])
    s.add_row(["Indent 1"], styles: { 0 => "indent_1" })
    s.add_row(["Indent 3"], styles: { 0 => "indent_3" })
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('No Indent'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=nil, shrink=nil

Align Text Rotation

Download .xlsx

Demonstrates text rotated by specific angles (45, 90 degrees).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_text_rotation.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("rot_45") { |s| s.text_rotation(45) }
  w.add_style("rot_90") { |s| s.text_rotation(90) }
  w.add_sheet("Rotation") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)
    s.add_row(["Rotated 45", "Rotated 90"], styles: { 0 => "rot_45", 1 => "rot_90" }, height: 50)
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Rotated 45'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=45, shrink=nil
Cell B1 ('Rotated 90'): align_h=nil, align_v=nil, wrap=nil, indent=nil, rotation=90, shrink=nil

Align Text Wrap

Download .xlsx

Demonstrates auto-wrapping multi-line text inside narrow cells.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_text_wrap.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("wrap") { |s| s.wrap_text }
  w.add_sheet("Text Wrap") do |s|
    s.set_print_option(:grid_lines, true)
    s.set_column(0, width: 15)
    s.add_row(["This is a long sentence that wraps inside the cell."], styles: { 0 => "wrap" })
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('This is a long sentence that wraps inside the cell.'): align_h=nil, align_v=nil, wrap=true, indent=nil, rotation=nil, shrink=nil

Align Vertical

Download .xlsx

Demonstrates vertical text alignment (top, center, bottom).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "align_vertical.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("top") { |s| s.align_vertical("top") }
  w.add_style("center") { |s| s.align_vertical("center") }
  w.add_style("bottom") { |s| s.align_vertical("bottom") }
  w.add_sheet("Vertical Alignment") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)
    s.add_row(["Top", "Center", "Bottom"], styles: { 0 => "top", 1 => "center", 2 => "bottom" }, height: 40)
  end
end

# 2. Read the generated sheet and print the parsed alignments
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  align_h = xf ? xf.dig(:alignment, :horizontal) : nil
  align_v = xf ? xf.dig(:alignment, :vertical) : nil
  wrap = xf ? xf.dig(:alignment, :wrap_text) : nil
  indent = xf ? xf.dig(:alignment, :indent) : nil
  rot = xf ? xf.dig(:alignment, :text_rotation) : nil
  shrink = xf ? xf.dig(:alignment, :shrink_to_fit) : nil
  puts "Cell #{c.ref} ('#{c.value}'): align_h=#{align_h.inspect}, align_v=#{align_v.inspect}, wrap=#{wrap.inspect}, indent=#{indent.inspect}, rotation=#{rot.inspect}, shrink=#{shrink.inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Top'): align_h=nil, align_v="top", wrap=nil, indent=nil, rotation=nil, shrink=nil
Cell B1 ('Center'): align_h=nil, align_v="center", wrap=nil, indent=nil, rotation=nil, shrink=nil
Cell C1 ('Bottom'): align_h=nil, align_v="bottom", wrap=nil, indent=nil, rotation=nil, shrink=nil

Basic Data

Download .xlsx

Demonstrates simple tabular data writing with basic Ruby types (Strings, Numbers, Dates, Booleans).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"
require "date"

output_path = ARGV[0] || "basic_data.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("currency") { |style| style.number_format("$#,##0.00") }
  w.add_style("date") { |style| style.number_format("yyyy-mm-dd") }
  w.add_sheet("Basic Data") do
    w.set_sheet_property(:fit_to_page, true)
    w.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    w.set_column(0, width: 25)
    w.set_column(1, width: 25)
    w.add_row(["Product", "Qty", "Price", "Date", "Active"])
    w.add_row(["Gadget A", 10, 99.99, Date.new(2026, 1, 15), true], styles: { 2 => "currency", 3 => "date" })
    w.add_row(["Widget B", 5, 49.50, Date.new(2026, 2, 20), false], styles: { 2 => "currency", 3 => "date" })
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Product" (String), B1: "Qty" (String), C1: "Price" (String), D1: "Date" (String), E1: "Active" (String)
Row 1: A2: "Gadget A" (String), B2: 10 (Integer), C2: 99.99 (Float), D2: 46037 (Integer), E2: true (TrueClass)
Row 2: A3: "Widget B" (String), B3: 5 (Integer), C3: 49.5 (Float), D3: 46073 (Integer), E3: false (FalseClass)

Borders

Download .xlsx

Demonstrates border styles (thin, medium, thick, hair, dashed, medium dashed, dotted, double, dash-dot, medium dash-dot, dash-dot-dot, slanted, and diagonal cross borders) applied to cell ranges.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "borders.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("thin") { |s| s.border_all(style: "thin", color: "FF000000") }
  w.add_style("medium") { |s| s.border_all(style: "medium", color: "FF000000") }
  w.add_style("thick") { |s| s.border_all(style: "thick", color: "FF000000") }
  w.add_style("hair") { |s| s.border_all(style: "hair", color: "FF000000") }
  w.add_style("dashed") { |s| s.border_all(style: "dashed", color: "FF000000") }
  w.add_style("medium_dashed") { |s| s.border_all(style: "mediumDashed", color: "FF000000") }
  w.add_style("dotted") { |s| s.border_all(style: "dotted", color: "FF000000") }
  w.add_style("double") { |s| s.border_all(style: "double", color: "FF000000") }
  w.add_style("dash_dot") { |s| s.border_all(style: "dashDot", color: "FF000000") }
  w.add_style("medium_dash_dot") { |s| s.border_all(style: "mediumDashDot", color: "FF000000") }
  w.add_style("dash_dot_dot") { |s| s.border_all(style: "dashDotDot", color: "FF000000") }
  w.add_style("slanted") { |s| s.border_all(style: "slantedDashDot", color: "FF000000") }
  w.add_style("diagonal") { |s| s.border_diagonal(style: "thin", color: "FF000000", up: true, down: true) }

  w.add_sheet("Borders") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)

    s.add_row(["Border Style", "Cell Preview"])
    s.add_row(["Thin", "Thin Border"], styles: { 1 => "thin" })
    s.add_row(["Medium", "Medium Border"], styles: { 1 => "medium" })
    s.add_row(["Thick", "Thick Border"], styles: { 1 => "thick" })
    s.add_row(["Hair", "Hair Border"], styles: { 1 => "hair" })
    s.add_row(["Dashed", "Dashed Border"], styles: { 1 => "dashed" })
    s.add_row(["Medium Dashed", "Medium Dashed"], styles: { 1 => "medium_dashed" })
    s.add_row(["Dotted", "Dotted Border"], styles: { 1 => "dotted" })
    s.add_row(["Double", "Double Border"], styles: { 1 => "double" })
    s.add_row(["Dash-Dot", "Dash-Dot Border"], styles: { 1 => "dash_dot" })
    s.add_row(["Medium Dash-Dot", "Medium Dash-Dot"], styles: { 1 => "medium_dash_dot" })
    s.add_row(["Dash-Dot-Dot", "Dash-Dot-Dot"], styles: { 1 => "dash_dot_dot" })
    s.add_row(["Slanted Dash-Dot", "Slanted Border"], styles: { 1 => "slanted" })
    s.add_row(["Diagonal (Cross)", "Diagonal Border"], styles: { 1 => "diagonal" })
  end
end

# Read check
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    border_id = xf ? xf[:border_id] : 0
    "#{c.ref}: #{c.value.inspect} (border_id: #{border_id})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Border Style" (border_id: 0), B1: "Cell Preview" (border_id: 0)
Row 1: A2: "Thin" (border_id: 0), B2: "Thin Border" (border_id: 1)
Row 2: A3: "Medium" (border_id: 0), B3: "Medium Border" (border_id: 2)
Row 3: A4: "Thick" (border_id: 0), B4: "Thick Border" (border_id: 3)
Row 4: A5: "Hair" (border_id: 0), B5: "Hair Border" (border_id: 4)
Row 5: A6: "Dashed" (border_id: 0), B6: "Dashed Border" (border_id: 5)
Row 6: A7: "Medium Dashed" (border_id: 0), B7: "Medium Dashed" (border_id: 6)
Row 7: A8: "Dotted" (border_id: 0), B8: "Dotted Border" (border_id: 7)
Row 8: A9: "Double" (border_id: 0), B9: "Double Border" (border_id: 8)
Row 9: A10: "Dash-Dot" (border_id: 0), B10: "Dash-Dot Border" (border_id: 9)
Row 10: A11: "Medium Dash-Dot" (border_id: 0), B11: "Medium Dash-Dot" (border_id: 10)
Row 11: A12: "Dash-Dot-Dot" (border_id: 0), B12: "Dash-Dot-Dot" (border_id: 11)
Row 12: A13: "Slanted Dash-Dot" (border_id: 0), B13: "Slanted Border" (border_id: 12)
Row 13: A14: "Diagonal (Cross)" (border_id: 0), B14: "Diagonal Border" (border_id: 13)

Cell Booleans

Download .xlsx

Demonstrates boolean values serialized and rendered.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_booleans.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Booleans") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Label", "Boolean Value"])
    s.add_row(["Is Active", true])
    s.add_row(["Is Pending", false])
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Label" (String), B1: "Boolean Value" (String)
Row 1: A2: "Is Active" (String), B2: true (TrueClass)
Row 2: A3: "Is Pending" (String), B3: false (FalseClass)

Cell Dates

Download .xlsx

Demonstrates dates serialized natively and formatted with standard or custom format strings.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
require "date"
output_path = ARGV[0] || "cell_dates.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("custom_date") { |s| s.num_fmt("yyyy-mm-dd") }
  w.add_sheet("Dates") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Date Value"])
    s.add_row(["Default Date", Date.new(2026, 7, 1)])
    s.add_row(["Formatted Date", Date.new(2026, 12, 25)], styles: { 1 => "custom_date" })
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (String), B1: "Date Value" (String)
Row 1: A2: "Default Date" (String), B2: 46204 (Integer)
Row 2: A3: "Formatted Date" (String), B3: 46381 (Integer)

Cell Formulas

Download .xlsx

Demonstrates standard spreadsheet calculations and formulas (SUM, AVERAGE).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_formulas.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Formulas") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Item", "Value"])
    s.add_row(["A", 10])
    s.add_row(["B", 20])
    s.add_row(["SUM", Xlsxrb::Elements::Formula.new(expression: "SUM(B2:B3)", cached_value: 30)])
    s.add_row(["AVERAGE", Xlsxrb::Elements::Formula.new(expression: "AVERAGE(B2:B3)", cached_value: 15)])
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Item" (String), B1: "Value" (String)
Row 1: A2: "A" (String), B2: 10 (Integer)
Row 2: A3: "B" (String), B3: 20 (Integer)
Row 3: A4: "SUM" (String), B4: 30 (Integer)
Row 4: A5: "AVERAGE" (String), B5: 15 (Integer)

Cell Num Currency Jpy

Download .xlsx

Demonstrates Yen Currency format code formatting.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_num_currency_jpy.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("jpy") { |s| s.num_fmt("¥#,##0;[Red]¥-#,##0") }
  w.add_sheet("JPY Currency") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Positive Yen", 12500], styles: { 1 => "jpy" })
    s.add_row(["Negative Yen", -8000], styles: { 1 => "jpy" })
  end
end

# 2. Read the generated sheet and print parsed cell numbers and format codes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
    "#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
Row 1: A2: "Positive Yen" (Format ID: , Code: nil), B2: 12500 (Format ID: 164, Code: "¥#,##0;[Red]¥-#,##0")
Row 2: A3: "Negative Yen" (Format ID: , Code: nil), B3: -8000 (Format ID: 164, Code: "¥#,##0;[Red]¥-#,##0")

Cell Num Custom Colors

Download .xlsx

Demonstrates custom colored formats for positive and negative numbers.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_num_custom_colors.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("custom_color") { |s| s.num_fmt("[Green]#,##0;[Red]-#,##0") }
  w.add_sheet("Custom Colors") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Positive (Green)", 5000], styles: { 1 => "custom_color" })
    s.add_row(["Negative (Red)", -2500], styles: { 1 => "custom_color" })
  end
end

# 2. Read the generated sheet and print parsed cell numbers and format codes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
    "#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
Row 1: A2: "Positive (Green)" (Format ID: , Code: nil), B2: 5000 (Format ID: 164, Code: "[Green]#,##0;[Red]-#,##0")
Row 2: A3: "Negative (Red)" (Format ID: , Code: nil), B3: -2500 (Format ID: 164, Code: "[Green]#,##0;[Red]-#,##0")

Cell Num Fractions

Download .xlsx

Demonstrates fraction number formats (# ?/?).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_num_fractions.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("frac") { |s| s.num_fmt("# ?/?") }
  w.add_sheet("Fractions") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Half", 0.5], styles: { 1 => "frac" })
    s.add_row(["Third", 0.3333], styles: { 1 => "frac" })
    s.add_row(["Quarter", 0.75], styles: { 1 => "frac" })
  end
end

# 2. Read the generated sheet and print parsed cell numbers and format codes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
    "#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
Row 1: A2: "Half" (Format ID: , Code: nil), B2: 0.5 (Format ID: 164, Code: "# ?/?")
Row 2: A3: "Third" (Format ID: , Code: nil), B3: 0.3333 (Format ID: 164, Code: "# ?/?")
Row 3: A4: "Quarter" (Format ID: , Code: nil), B4: 0.75 (Format ID: 164, Code: "# ?/?")

Cell Num Percent Decimals

Download .xlsx

Demonstrates percentages with two decimal places (0.00%).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_num_percent_decimals.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("pct2") { |s| s.num_fmt("0.00%") }
  w.add_sheet("Percents") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Percent with 2 Decimals", 0.12345], styles: { 1 => "pct2" })
  end
end

# 2. Read the generated sheet and print parsed cell numbers and format codes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
    "#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
Row 1: A2: "Percent with 2 Decimals" (Format ID: , Code: nil), B2: 0.12345 (Format ID: 164, Code: "0.00%")

Cell Num Scientific

Download .xlsx

Demonstrates scientific number formats (0.00E+00).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_num_scientific.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("sci") { |s| s.num_fmt("0.00E+00") }
  w.add_sheet("Scientific") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Scientific", 123456789.0], styles: { 1 => "sci" })
    s.add_row(["Small Scientific", 0.00001234], styles: { 1 => "sci" })
  end
end

# 2. Read the generated sheet and print parsed cell numbers and format codes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    num_fmt = xf ? workbook.styles[:num_fmts][xf[:num_fmt_id]] : nil
    "#{c.ref}: #{c.value.inspect} (Format ID: #{xf&.[](:num_fmt_id)}, Code: #{num_fmt.inspect})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (Format ID: , Code: nil), B1: "Value" (Format ID: , Code: nil)
Row 1: A2: "Scientific" (Format ID: , Code: nil), B2: 123456789.0 (Format ID: 164, Code: "0.00E+00")
Row 2: A3: "Small Scientific" (Format ID: , Code: nil), B3: 1.234e-05 (Format ID: 164, Code: "0.00E+00")

Cell Numbers

Download .xlsx

Demonstrates custom formatting for integers, floating point numbers, currencies, and percentages.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_numbers.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("currency") { |s| s.num_fmt("$#,##0.00") }
  w.add_style("percent") { |s| s.num_fmt("0.0%") }
  w.add_sheet("Numbers") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Integer", 12345])
    s.add_row(["Float", 123.456])
    s.add_row(["Currency", 1234.5], styles: { 1 => "currency" })
    s.add_row(["Percentage", 0.85], styles: { 1 => "percent" })
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (String), B1: "Value" (String)
Row 1: A2: "Integer" (String), B2: 12345 (Integer)
Row 2: A3: "Float" (String), B3: 123.456 (Float)
Row 3: A4: "Currency" (String), B4: 1234.5 (Float)
Row 4: A5: "Percentage" (String), B5: 0.85 (Float)

Cell Rich Text

Download .xlsx

Demonstrates Rich Text cells with multiple font weights, styles, and colors in a single cell.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cell_rich_text.xlsx"
Xlsxrb.generate(output_path) do |w|
  rt = Xlsxrb::Elements::RichText.new(runs: [
    { text: "Normal " },
    { text: "BOLD RED ", font: { bold: true, color: "FFC00000", sz: 16 } },
    { text: "ITALIC BLUE", font: { italic: true, color: "FF0000FF", sz: 20 } }
  ])
  w.add_sheet("Rich Text") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Value"])
    s.add_row(["Rich Text Cell", rt])
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (String), B1: "Value" (String)
Row 1: A2: "Rich Text Cell" (String), B2: "Normal BOLD RED ITALIC BLUE" (String)

Cell Times

Download .xlsx

Demonstrates timestamp values serialized natively and formatted showing hours, minutes, and seconds.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
require "time"
output_path = ARGV[0] || "cell_times.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("time_fmt") { |s| s.num_fmt("hh:mm:ss") }
  w.add_sheet("Times") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Format", "Time Value"])
    s.add_row(["DateTime", Time.new(2026, 7, 1, 12, 34, 56)])
    s.add_row(["Time Only", Time.new(2026, 7, 1, 9, 15, 0)], styles: { 1 => "time_fmt" })
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Format" (String), B1: "Time Value" (String)
Row 1: A2: "DateTime" (String), B2: 46204.52425925926 (Float)
Row 2: A3: "Time Only" (String), B3: 46204.385416666664 (Float)

Cf Begins With

Download .xlsx

Demonstrates conditional formatting highlighting cells starting with specific text.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_begins_with.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("CF Begins") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Code"])
    s.add_row(["A-100"])
    s.add_row(["B-200"])
    s.add_row(["A-300"])
    s.add_conditional_format("A2:A4", type: "beginsWith", operator: "beginsWith", text: "A", formula: 'LEFT(A2,1)="A"', fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Code"
Row 1: A2: "A-100"
Row 2: A3: "B-200"
Row 3: A4: "A-300"

Cf Cell Between

Download .xlsx

Demonstrates conditional formatting highlighting cells within a range.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_cell_between.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Between") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([15], styles: ["center"])
    s.add_row([25], styles: ["center"])
    s.add_row([5], styles: ["center"])
    s.add_conditional_format("A2:A4", type: "cellIs", operator: "between", formulas: ["10", "20"], fill_color: "FF00FF00")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 15
Row 2: A3: 25
Row 3: A4: 5

Cf Cell Equal To

Download .xlsx

Demonstrates conditional formatting highlighting cells equal to a target value.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_cell_equal_to.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Equal") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([10], styles: ["center"])
    s.add_row([20], styles: ["center"])
    s.add_row([10], styles: ["center"])
    s.add_conditional_format("A2:A4", type: "cellIs", operator: "equal", formula: "10", fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 10
Row 2: A3: 20
Row 3: A4: 10

Cf Cell Greater Equal

Download .xlsx

Demonstrates conditional formatting highlighting cells greater than or equal to a threshold.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_cell_greater_equal.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Greater Equal") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([10], styles: ["center"])
    s.add_row([50], styles: ["center"])
    s.add_row([100], styles: ["center"])
    s.add_conditional_format("A2:A4", type: "cellIs", operator: "greaterThanOrEqual", formula: "50", fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 10
Row 2: A3: 50
Row 3: A4: 100

Cf Cell Greater Than

Download .xlsx

Demonstrates conditional formatting highlighting cells greater than a threshold.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_cell_greater_than.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Greater") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([25], styles: ["center"])
    s.add_row([75], styles: ["center"])
    s.add_row([10], styles: ["center"])
    s.add_conditional_format("A2:A4", type: "cellIs", operator: "greaterThan", formula: "50", fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 25
Row 2: A3: 75
Row 3: A4: 10

Cf Cell Less Than

Download .xlsx

Demonstrates conditional formatting highlighting cells less than a threshold.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_cell_less_than.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Less") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([25], styles: ["center"])
    s.add_row([75], styles: ["center"])
    s.add_row([10], styles: ["center"])
    s.add_conditional_format("A2:A4", type: "cellIs", operator: "lessThan", formula: "20", fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 25
Row 2: A3: 75
Row 3: A4: 10

Cf Color Scale

Download .xlsx

Demonstrates color scale/heatmap conditional formatting.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_color_scale.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("Colors") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([10], styles: ["center"])
    s.add_row([50], styles: ["center"])
    s.add_row([90], styles: ["center"])
    s.add_conditional_format("A1:A3", type: :colorScale, priority: 1)
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 10
Row 1: A2: 50
Row 2: A3: 90

Cf Contains Text

Download .xlsx

Demonstrates conditional formatting highlighting cells containing specific text.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_contains_text.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("CF Contains") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Status"])
    s.add_row(["Error"])
    s.add_row(["Success"])
    s.add_row(["Pending"])
    s.add_conditional_format("A2:A4", type: "containsText", operator: "containsText", text: "Error", formula: 'NOT(ISERROR(SEARCH("Error",A2)))', fill_color: "FFFF0000")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Status"
Row 1: A2: "Error"
Row 2: A3: "Success"
Row 3: A4: "Pending"

Cf Data Bar

Download .xlsx

Demonstrates data bar visual conditional formatting indicators.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_data_bar.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("Data Bars") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([20], styles: ["center"])
    s.add_row([60], styles: ["center"])
    s.add_row([100], styles: ["center"])
    s.add_conditional_format("A1:A3", type: :dataBar, priority: 1, color: "FF0070C0")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 20
Row 1: A2: 60
Row 2: A3: 100

Cf Ends With

Download .xlsx

Demonstrates conditional formatting highlighting cells ending with specific text.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_ends_with.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("CF Ends") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Code"])
    s.add_row(["100-Z"])
    s.add_row(["200-Y"])
    s.add_row(["300-Z"])
    s.add_conditional_format("A2:A4", type: "endsWith", operator: "endsWith", text: "Z", formula: 'RIGHT(A2,1)="Z"', fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Code"
Row 1: A2: "100-Z"
Row 2: A3: "200-Y"
Row 3: A4: "300-Z"

Cf Expression Formula

Download .xlsx

Demonstrates conditional formatting using a custom formula expression.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_expression_formula.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("CF Expression") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Values"])
    s.add_row([10], styles: ["center"])
    s.add_row([20], styles: ["center"])
    s.add_row([30], styles: ["center"])
    s.add_row([100], styles: ["center"]) # Average is 40. 100 is above average.
    s.add_conditional_format("A2:A5", type: "expression", formula: "A2>AVERAGE($A$2:$A$5)", fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Values"
Row 1: A2: 10
Row 2: A3: 20
Row 3: A4: 30
Row 4: A5: 100

Cf Icon Set

Download .xlsx

Demonstrates icon set indicators (red/yellow/green arrows).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "cf_icon_set.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("Icons") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([25], styles: ["center"])
    s.add_row([50], styles: ["center"])
    s.add_row([75], styles: ["center"])
    s.add_conditional_format("A1:A3", type: :iconSet, icon_style: "3Arrows", priority: 1)
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 25
Row 1: A2: 50
Row 2: A3: 75

Chart Area

Download .xlsx

Demonstrates embedding a standard 2D Area Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_area.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Day", "Value"])
    s.add_row(["Mon", 10])
    s.add_row(["Tue", 15])
    s.add_chart(
      type: :area,
      title: "Daily Area",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", fill_color: "4F81BD" }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Area Stacked

Download .xlsx

Demonstrates embedding a stacked 2D Area Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_area_stacked.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Year", "Sales A", "Sales B"])
    s.add_row([2024, 100, 150])
    s.add_row([2025, 120, 180])
    s.add_row([2026, 140, 210])
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.add_chart(
      type: :area,
      grouping: :stacked,
      title: "Stacked Area Chart",
      from_col: 0, from_row: 5, to_col: 6, to_row: 17,
      series: [
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
      ]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Bar

Download .xlsx

Demonstrates embedding a standard 2D Bar Chart referencing worksheet cell ranges.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "chart_bar.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Sales Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Month", "Value"])
    s.add_row(["Jan", 100])
    s.add_row(["Feb", 200])

    s.add_chart(
      type: :bar,
      title: "Monthly Sales",
      from_col: 3,
      from_row: 0,
      to_col: 8,
      to_row: 12,
      series: [
        { cat_ref: "'Sales Data'!$A$2:$A$3", val_ref: "'Sales Data'!$B$2:$B$3", fill_color: "4F81BD" }
      ]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Sales Data' has 0 chart(s)

Chart Bar Percent Stacked

Download .xlsx

Demonstrates embedding a 100% stacked 2D Bar Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_bar_percent_stacked.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Year", "Sales A", "Sales B"])
    s.add_row([2024, 100, 150])
    s.add_row([2025, 120, 180])
    s.add_row([2026, 140, 210])
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.add_chart(
      type: :bar,
      grouping: :percentStacked,
      title: "100% Stacked Bar Chart",
      from_col: 0, from_row: 5, to_col: 6, to_row: 17,
      series: [
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
      ]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Bar Stacked

Download .xlsx

Demonstrates embedding a stacked 2D Bar Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_bar_stacked.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Year", "Sales A", "Sales B"])
    s.add_row([2024, 100, 150])
    s.add_row([2025, 120, 180])
    s.add_row([2026, 140, 210])
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.add_chart(
      type: :bar,
      grouping: :stacked,
      title: "Stacked Bar Chart",
      from_col: 0, from_row: 5, to_col: 6, to_row: 17,
      series: [
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", fill_color: "4F81BD" },
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", fill_color: "C0504D" }
      ]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Doughnut

Download .xlsx

Demonstrates embedding a standard 2D Doughnut Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_doughnut.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Label", "Percent"])
    s.add_row(["A", 40])
    s.add_row(["B", 60])
    s.add_chart(
      type: :doughnut,
      title: "Ratio",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{
        cat_ref: "Data!$A$2:$A$3",
        val_ref: "Data!$B$2:$B$3",
        data_points: [
          { idx: 0, fill_color: "4F81BD" },
          { idx: 1, fill_color: "C0504D" }
        ]
      }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Line

Download .xlsx

Demonstrates embedding a standard 2D Line Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_line.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Day", "Value"])
    s.add_row(["Mon", 10])
    s.add_row(["Tue", 15])
    s.add_row(["Wed", 12])
    s.add_chart(
      type: :line,
      title: "Daily Value",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{ cat_ref: "Data!$A$2:$A$4", val_ref: "Data!$B$2:$B$4", line_color: "4F81BD", line_width: 2.0 }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Line Stacked

Download .xlsx

Demonstrates embedding a stacked 2D Line Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_line_stacked.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Year", "Sales A", "Sales B"])
    s.add_row([2024, 100, 150])
    s.add_row([2025, 120, 180])
    s.add_row([2026, 140, 210])
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.add_chart(
      type: :line,
      grouping: :stacked,
      title: "Stacked Line Chart",
      from_col: 0, from_row: 5, to_col: 6, to_row: 17,
      series: [
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$B$2:$B$4", name: "'Data'!$B$1", line_color: "4F81BD", line_width: 2.0 },
        { cat_ref: "'Data'!$A$2:$A$4", val_ref: "'Data'!$C$2:$C$4", name: "'Data'!$C$1", line_color: "C0504D", line_width: 2.0 }
      ]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Pie

Download .xlsx

Demonstrates embedding a standard 2D Pie Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_pie.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Label", "Percent"])
    s.add_row(["Yes", 70])
    s.add_row(["No", 30])
    s.add_chart(
      type: :pie,
      title: "Responses",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{
        cat_ref: "Data!$A$2:$A$3",
        val_ref: "Data!$B$2:$B$3",
        data_points: [
          { idx: 0, fill_color: "4F81BD" },
          { idx: 1, fill_color: "C0504D" }
        ]
      }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Radar

Download .xlsx

Demonstrates embedding a standard 2D Radar Chart.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_radar.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Stat", "Value"])
    s.add_row(["Atk", 80])
    s.add_row(["Def", 60])
    s.add_chart(
      type: :radar,
      title: "Stats",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", line_color: "4F81BD", line_width: 2.0 }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Chart Scatter

Download .xlsx

Demonstrates embedding a standard 2D Scatter Plot.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "chart_scatter.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Data") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["X", "Y"])
    s.add_row([1, 10])
    s.add_row([2, 15])
    s.add_chart(
      type: :scatter,
      title: "Scatter Plot",
      from_col: 3, from_row: 0, to_col: 8, to_row: 12,
      series: [{ cat_ref: "Data!$A$2:$A$3", val_ref: "Data!$B$2:$B$3", line_color: "4F81BD", line_width: 2.0 }]
    )
  end
end

# 2. Read the generated sheet and print the chart count
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
puts "Sheet '#{sheet.name}' has #{sheet.charts.size} chart(s)"

Console Output

=== Read Validation ===
Sheet 'Data' has 0 chart(s)

Col Grouping

Download .xlsx

Demonstrates outline grouping for columns.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "col_grouping.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Col Grouping") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25, outline_level: 0)
    s.set_column(1, width: 25, outline_level: 1)
    s.set_column(2, width: 25, outline_level: 1)
    s.add_row(["Col A", "Col B (Grouped)", "Col C (Grouped)"], styles: ["border", "border", "border"])
  end
end

# 2. Read the generated sheet and print column dimensions
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.columns.each do |col|
  puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
end

Console Output

=== Read Validation ===
Column 0: width=25.0, hidden=false, outline_level=0
Column 1: width=25.0, hidden=false, outline_level=1
Column 2: width=25.0, hidden=false, outline_level=1

Col Width Tall

Download .xlsx

Demonstrates setting very wide column widths.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "col_width_tall.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Col Width") do |s|
    s.set_column(0, width: 50)
    s.set_column(1, width: 10)
    s.add_row(["Very Wide Column (Width 50)", "Normal (10)"], styles: ["border", "border"])
  end
end

# 2. Read the generated sheet and print column dimensions
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.columns.each do |col|
  puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
end

Console Output

=== Read Validation ===
Column 0: width=50.0, hidden=false, outline_level=
Column 1: width=10.0, hidden=false, outline_level=

Col Widths

Download .xlsx

Demonstrates setting custom column widths.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "col_widths.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Widths") do |s|
    s.set_column(0, width: 30)
    s.set_column(1, width: 10)
    s.add_row(["Wide Column A", "Narrow B"], styles: ["border", "border"])
  end
end

# 2. Read the generated sheet and print column dimensions
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.columns.each do |col|
  puts "Column #{col.index}: width=#{col.width}, hidden=#{col.hidden}, outline_level=#{col.outline_level}"
end

Console Output

=== Read Validation ===
Column 0: width=30.0, hidden=false, outline_level=
Column 1: width=10.0, hidden=false, outline_level=

Conditional Formatting

Download .xlsx

Demonstrates adding conditional formatting rules that style cells automatically based on value ranges.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "conditional_formatting.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |style| style.align_horizontal("center") }
  w.add_sheet("Scores") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([90, 45, 72, 88], styles: ["center", "center", "center", "center"])

    s.add_conditional_format("A1:D1",
      type: :cell_is, operator: :greaterThan,
      formula: "80", priority: 1,
      fill_color: "FFFFC7CE")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 90, B1: 45, C1: 72, D1: 88

Embedded Images

Download .xlsx

Demonstrates embedding raster PNG images in cell ranges.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "embedded_images.xlsx"

require "zlib"

def make_png(width, height, red, green, blue)
  png = "\x89PNG\r\n\x1a\n".dup.force_encoding("BINARY")
  ihdr_data = [width, height, 8, 2, 0, 0, 0].pack("N2C5")
  ihdr_chunk = "IHDR".dup.force_encoding("BINARY") + ihdr_data
  ihdr_crc = Zlib.crc32(ihdr_chunk)
  png << [ihdr_data.bytesize].pack("N") << ihdr_chunk << [ihdr_crc].pack("N")
  raw_data = Array.new(height) { "\x00".dup.force_encoding("BINARY") + [red, green, blue].pack("C3") * width }.join
  compressed = Zlib.deflate(raw_data)
  idat_chunk = "IDAT".dup.force_encoding("BINARY") + compressed
  idat_crc = Zlib.crc32(idat_chunk)
  png << [compressed.bytesize].pack("N") << idat_chunk << [idat_crc].pack("N")
  iend_chunk = "IEND".dup.force_encoding("BINARY")
  iend_crc = Zlib.crc32(iend_chunk)
  png << [0].pack("N") << iend_chunk << [iend_crc].pack("N")
  png
end

dummy_png = make_png(100, 100, 255, 0, 0)

Xlsxrb.generate(output_path) do |w|
  w.add_style("center") { |st| st.align_horizontal(:center) }
  w.add_sheet("Images") do |s|
    s.add_row(["Logo Target cell:", "", "", "Boundary"], styles: ["left", "center", "center", "center"])
    s.add_row(["", "", "", ""])
    s.add_row(["", "", "", ""])
    s.add_row(["", "", "", ""])
    s.add_row(["", "", "", "Boundary End"], styles: ["left", "center", "center", "center"])
    s.add_image(dummy_png, ext: "png", from_col: 1, from_row: 1, to_col: 3, to_row: 5)
    s.set_column(0, width: 20)
    s.set_column(1, width: 15)
    s.set_column(2, width: 15)
    s.set_column(3, width: 15)
  end
end

# 2. Read the generated sheet and print cell values + parsed embedded images details
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end
images = reader.images(sheet: sheet.name)
images.each_with_index do |img, idx|
  zip_path = File.expand_path(img[:target], "/xl/drawings").sub(%r{^/}, "")
  img_data = reader.send(:extract_zip_entry, zip_path)
  is_png = img_data && img_data[0..3] == "\x89PNG".b
  puts "Image ##{idx + 1}: name='#{img[:name]}', target='#{img[:target]}' -> ZIP path='#{zip_path}', size=#{img_data&.bytesize} bytes, valid_png=#{is_png}, range=Col #{img[:from_col]} Row #{img[:from_row]} to Col #{img[:to_col]} Row #{img[:to_row]}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Logo Target cell:", B1: "", C1: "", D1: "Boundary"
Row 1: A2: "", B2: "", C2: "", D2: ""
Row 2: A3: "", B3: "", C3: "", D3: ""
Row 3: A4: "", B4: "", C4: "", D4: ""
Row 4: A5: "", B5: "", C5: "", D5: "Boundary End"
Image #1: name='', target='../media/image1.png' -> ZIP path='xl/media/image1.png', size=334 bytes, valid_png=true, range=Col 1 Row 1 to Col 3 Row 5

Fill Gradients

Download .xlsx

Demonstrates linear gradients inside cell backgrounds.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "fill_gradients.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("gradient") do |style|
    style.fill_gradient(type: "linear", degree: 45, stops: [
      { position: 0, color: "FFFFFFFF" },
      { position: 1, color: "FF4F81BD" }
    ])
  end
  w.add_sheet("Gradients") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Normal Cell", "Gradient Cell"], styles: { 1 => "gradient" })
  end
end

# 2. Read the generated sheet and print cell fill properties
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
  puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Normal Cell'): fill pattern = nil, fg_color = nil
Cell B1 ('Gradient Cell'): fill pattern = nil, fg_color = nil

Fill Patterns

Download .xlsx

Demonstrates standard pattern fills (darkGray, darkGrid) in cell backgrounds.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "fill_patterns.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("dark_gray") { |s| s.fill(pattern: "darkGray", fg_color: "FFC0C0C0", bg_color: "FFFFFFFF") }
  w.add_style("grid_fill") { |s| s.fill(pattern: "darkGrid", fg_color: "FFC0C0C0", bg_color: "FFFFFFFF") }
  w.add_sheet("Patterns") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Pattern", "Preview"])
    s.add_row(["Dark Gray", "Pattern Fill"], styles: { 1 => "dark_gray" })
    s.add_row(["Dark Grid", "Grid Fill"], styles: { 1 => "grid_fill" })
  end
end

# 2. Read the generated sheet and print cell fill properties
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
  puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Pattern'): fill pattern = nil, fg_color = nil
Cell B1 ('Preview'): fill pattern = nil, fg_color = nil

Fill Solid Colors

Download .xlsx

Demonstrates solid cell background fill colors.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "fill_solid_colors.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("red_fill") { |s| s.fill_color("FFFFC7CE") }
  w.add_style("green_fill") { |s| s.fill_color("FFC6EFCE") }
  w.add_sheet("Fills") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Color", "Preview"])
    s.add_row(["Red", "Red Fill"], styles: { 1 => "red_fill" })
    s.add_row(["Green", "Green Fill"], styles: { 1 => "green_fill" })
  end
end

# 2. Read the generated sheet and print cell fill properties
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
row = sheet.rows.first
row.cells.each do |c|
  xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
  fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
  puts "Cell #{c.ref} ('#{c.value}'): fill pattern = #{fill&.[](:pattern).inspect}, fg_color = #{fill&.[](:fg_color).inspect}"
end

Console Output

=== Read Validation ===
Cell A1 ('Color'): fill pattern = nil, fg_color = nil
Cell B1 ('Preview'): fill pattern = nil, fg_color = nil

Fonts

Download .xlsx

Demonstrates cell fonts properties (Arial, Georgia, Courier New, Times New Roman, Tahoma, sizes 10pt/16pt/24pt, red/green/blue colors, bold/italic/underline/double underline/strike-through styles, superscript/subscript).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "fonts.xlsx"

Xlsxrb.generate(output_path) do |w|
  # Font Families
  w.add_style("f_arial") { |s| s.font_name("Arial") }
  w.add_style("f_times") { |s| s.font_name("Times New Roman") }
  w.add_style("f_courier") { |s| s.font_name("Courier New") }
  w.add_style("f_georgia") { |s| s.font_name("Georgia") }
  w.add_style("f_tahoma") { |s| s.font_name("Tahoma") }

  # Font Sizes
  w.add_style("sz_10") { |s| s.size(10) }
  w.add_style("sz_16") { |s| s.size(16) }
  w.add_style("sz_24") { |s| s.size(24) }

  # Font Colors
  w.add_style("c_red") { |s| s.font_color("FFC00000") }
  w.add_style("c_green") { |s| s.font_color("FF008000") }
  w.add_style("c_blue") { |s| s.font_color("FF0000FF") }

  # Font Styles
  w.add_style("st_bold") { |s| s.bold }
  w.add_style("st_italic") { |s| s.italic }
  w.add_style("st_underline") { |s| s.underline("single") }
  w.add_style("st_double_u") { |s| s.underline("double") }
  w.add_style("st_strike") { |s| s.strike }

  # Vertical Alignments (Superscript/Subscript)
  w.add_style("v_super") { |s| s.vert_align("superscript") }
  w.add_style("v_sub") { |s| s.vert_align("subscript") }

  w.add_sheet("Fonts") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)

    s.add_row(["Font Feature", "Text Preview"])
    s.add_row(["Family: Arial", "Arial Text"], styles: { 1 => "f_arial" })
    s.add_row(["Family: Times New Roman", "Times New Roman"], styles: { 1 => "f_times" })
    s.add_row(["Family: Courier New", "Courier New Text"], styles: { 1 => "f_courier" })
    s.add_row(["Family: Georgia", "Georgia Text"], styles: { 1 => "f_georgia" })
    s.add_row(["Family: Tahoma", "Tahoma Text"], styles: { 1 => "f_tahoma" })

    s.add_row(["Size: 10pt", "10pt Font Size"], styles: { 1 => "sz_10" })
    s.add_row(["Size: 16pt", "16pt Font Size"], styles: { 1 => "sz_16" })
    s.add_row(["Size: 24pt", "24pt Font Size"], styles: { 1 => "sz_24" })

    s.add_row(["Color: Red", "Red Text"], styles: { 1 => "c_red" })
    s.add_row(["Color: Green", "Green Text"], styles: { 1 => "c_green" })
    s.add_row(["Color: Blue", "Blue Text"], styles: { 1 => "c_blue" })

    s.add_row(["Style: Bold", "Bold Text"], styles: { 1 => "st_bold" })
    s.add_row(["Style: Italic", "Italic Text"], styles: { 1 => "st_italic" })
    s.add_row(["Style: Underline", "Underline Text"], styles: { 1 => "st_underline" })
    s.add_row(["Style: Double Underline", "Double Underline"], styles: { 1 => "st_double_u" })
    s.add_row(["Style: Strike-through", "Strike-through Text"], styles: { 1 => "st_strike" })

    s.add_row(["Align: Superscript", "x2 (2 is super)"], styles: { 1 => "v_super" })
    s.add_row(["Align: Subscript", "H2O (2 is sub)"], styles: { 1 => "v_sub" })
  end
end

# Read check
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    font_id = xf ? xf[:font_id] : 0
    "#{c.ref}: #{c.value.inspect} (font_id: #{font_id})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Font Feature" (font_id: 0), B1: "Text Preview" (font_id: 0)
Row 1: A2: "Family: Arial" (font_id: 0), B2: "Arial Text" (font_id: 1)
Row 2: A3: "Family: Times New Roman" (font_id: 0), B3: "Times New Roman" (font_id: 2)
Row 3: A4: "Family: Courier New" (font_id: 0), B4: "Courier New Text" (font_id: 3)
Row 4: A5: "Family: Georgia" (font_id: 0), B5: "Georgia Text" (font_id: 4)
Row 5: A6: "Family: Tahoma" (font_id: 0), B6: "Tahoma Text" (font_id: 5)
Row 6: A7: "Size: 10pt" (font_id: 0), B7: "10pt Font Size" (font_id: 6)
Row 7: A8: "Size: 16pt" (font_id: 0), B8: "16pt Font Size" (font_id: 7)
Row 8: A9: "Size: 24pt" (font_id: 0), B9: "24pt Font Size" (font_id: 8)
Row 9: A10: "Color: Red" (font_id: 0), B10: "Red Text" (font_id: 9)
Row 10: A11: "Color: Green" (font_id: 0), B11: "Green Text" (font_id: 10)
Row 11: A12: "Color: Blue" (font_id: 0), B12: "Blue Text" (font_id: 11)
Row 12: A13: "Style: Bold" (font_id: 0), B13: "Bold Text" (font_id: 12)
Row 13: A14: "Style: Italic" (font_id: 0), B14: "Italic Text" (font_id: 13)
Row 14: A15: "Style: Underline" (font_id: 0), B15: "Underline Text" (font_id: 14)
Row 15: A16: "Style: Double Underline" (font_id: 0), B16: "Double Underline" (font_id: 15)
Row 16: A17: "Style: Strike-through" (font_id: 0), B17: "Strike-through Text" (font_id: 16)
Row 17: A18: "Align: Superscript" (font_id: 0), B18: "x2 (2 is super)" (font_id: 17)
Row 18: A19: "Align: Subscript" (font_id: 0), B19: "H2O (2 is sub)" (font_id: 18)

Interactive Autofilter

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates enabling auto-filter sorting headers on tables. Download the sheet to interactively filter and sort columns.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_autofilter.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Filter") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Name", "Department"])
    s.add_row(["Alice", "HR"])
    s.add_row(["Bob", "Eng"])
    s.set_auto_filter("A1:B3")
  end
  w.add_defined_name("_xlnm._FilterDatabase", "Filter!$A$1:$B$3", sheet: "Filter", hidden: true)
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Name", B1: "Department"
Row 1: A2: "Alice", B2: "HR"
Row 2: A3: "Bob", B3: "Eng"

Interactive Comments

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates cell pop-up comments. Open the sheet in Excel and hover your mouse over the cell with the red triangle to view the comment.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_comments.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Comments") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Item A", "Item B"])
    s.add_comment("A1", "This is an important comment.", author: "System")
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Item A", B1: "Item B"

Interactive Validation Custom

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates interactive custom formula validation rules.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_custom.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Custom Rule") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Number A", "Number B (Must be larger A)"])
    s.add_row([10, ""])
    s.add_data_validation("B2", type: "custom", formula1: "B2>A2", show_error_message: true, error_title: "Validation Error", error: "Number B must be greater than Number A")
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=custom, formula1=B2>A2, formula2=

Interactive Validation Date

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates interactive date range constraints validation rules.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_date.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Date Validation") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Date Range", "Enter Date (2026):"])
    s.add_data_validation("B2", type: "date", operator: "between", formula1: "Date(2026,1,1)", formula2: "Date(2026,12,31)", show_error_message: true, error_title: "Invalid Date", error: "Must be a date in 2026")
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=date, formula1=Date(2026,1,1), formula2=Date(2026,12,31)

Interactive Validation List

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates dropdown list data validations. Open the sheet in Excel and select cell A1/A2 to see the dropdown list in action.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_list.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("List Validation") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Department", "Select:"])
    s.add_data_validation("B2", type: "list", formula1: '"HR,Sales,Engineering"')
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=list, formula1="HR,Sales,Engineering", formula2=

Interactive Validation Range

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates range constraints for whole number validations. Open the sheet in Excel and try entering a value outside 10-100 to trigger the warning.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_range.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Range Validation") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Age", "Enter (18-99):"])
    s.add_data_validation("B2", type: "whole", operator: "between", formula1: "18", formula2: "99", show_error_message: true, error_title: "Invalid Age", error: "Age must be between 18 and 99!")
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=whole, formula1=18, formula2=99

Interactive Validation Text Length

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates interactive text length validation rules.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_text_length.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Text Length") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Username", "Enter (< 10 chars):"])
    s.add_data_validation("B2", type: "textLength", operator: "lessThan", formula1: "10", show_error_message: true, error_title: "Too Long", error: "Username must be under 10 characters")
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=textLength, formula1=10, formula2=

Interactive Validation Time

Download .xlsx

[!TIP] Interactive Feature: This example uses interactive Excel behaviors (such as validation dropdowns, comments, or autofilters). Since the static visual preview below represents a printed page layout, please Download the .xlsx file and open it in Microsoft Excel, LibreOffice Calc, or Apple Numbers to interact with it!

Demonstrates interactive time validation rules.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "interactive_validation_time.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Time Validation") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Schedule", "Enter Time (after 08:00):"])
    s.add_data_validation("B2", type: "time", operator: "greaterThan", formula1: "0.33333", show_error_message: true, error_title: "Too Early", error: "Time must be after 08:00 AM")
  end
end

# 2. Read the generated sheet and print data validations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
validations = reader.data_validations(sheet: sheet.name)
validations.each do |v|
  puts "Validation range #{v[:sqref]}: type=#{v[:type]}, formula1=#{v[:formula1]}, formula2=#{v[:formula2]}"
end

Console Output

=== Read Validation ===
Validation range B2: type=time, formula1=0.33333, formula2=

Japanese Text

Download .xlsx

Demonstrates writing multi-byte Japanese text and setting appropriate Japanese font names (e.g., Noto Sans CJK JP).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "japanese_text.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("ja_font") do |style|
    style.font_name("Noto Sans CJK JP").size(12)
  end

  w.add_sheet("Japanese") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["日本語ラベル", ""], styles: { 0 => "ja_font", 1 => "ja_font" })
    s.add_row(["売上", 12500], styles: { 0 => "ja_font" })
  end
end

# 2. Read the generated sheet and print parsed cell values and Ruby classes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  row_cells = row.cells.map do |c|
    "#{c.ref}: #{c.value.inspect} (#{c.value.class})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "日本語ラベル" (String), B1: "値" (String)
Row 1: A2: "売上" (String), B2: 12500 (Integer)

Merge Freeze

Download .xlsx

Demonstrates merging a cell range into a single cell, and freezing the top rows of a sheet.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "merge_freeze.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("title") { |style| style.border_all(style: "thin", color: "FF000000").align_horizontal("center") }
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Merge & Freeze") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_column(2, width: 25)
    s.add_row(["Merged Title Row", nil, nil], styles: ["title", "title", "title"])
    s.add_row(["Header A", "Header B", "Header C"], styles: ["border", "border", "border"])
    s.add_row(["Row 1 Col A", "Row 1 Col B", "Row 1 Col C"], styles: ["border", "border", "border"])
    s.add_row(["Row 2 Col A", "Row 2 Col B", "Row 2 Col C"], styles: ["border", "border", "border"])

    s.merge_cells("A1:C1")
    s.set_freeze_pane(row: 2, col: 0)
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(5).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Merged Title Row", B1: nil, C1: nil
Row 1: A2: "Header A", B2: "Header B", C2: "Header C"
Row 2: A3: "Row 1 Col A", B3: "Row 1 Col B", C3: "Row 1 Col C"
Row 3: A4: "Row 2 Col A", B4: "Row 2 Col B", C4: "Row 2 Col C"

Page Grid Lines Print

Download .xlsx

Demonstrates enabling printing of grid lines.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_grid_lines_print.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Print Grid Lines") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:grid_lines, true)
    s.add_row(["Grid Lines Printed sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: nil
Page Setup: {}
Print Options: {grid_lines: true}

Download .xlsx

Demonstrates setting odd page headers and footers.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_header_footer.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Header Footer") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_header_footer(odd_header: "&LMy Company&RPage &P", odd_footer: "&CConfidential")
    s.add_row(["Header Footer sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: nil
Page Setup: {}
Print Options: {}

Page Headings Print

Download .xlsx

Demonstrates enabling printing of row and column headings.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_headings_print.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Print Headings") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_print_option(:headings, true)
    s.add_row(["Row/Col Headings Printed sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: nil
Page Setup: {}
Print Options: {headings: true}

Page Margins Narrow

Download .xlsx

Demonstrates setting narrow page margins.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_margins_narrow.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Narrow Margins") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_page_margins(top: 0.25, bottom: 0.25, left: 0.25, right: 0.25, header: 0.1, footer: 0.1)
    s.add_row(["Narrow Margins sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: {left: 0.25, right: 0.25, top: 0.25, bottom: 0.25, header: 0.1, footer: 0.1}
Page Setup: {}
Print Options: {}

Page Margins Wide

Download .xlsx

Demonstrates setting wide page margins.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_margins_wide.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Wide Margins") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_page_margins(top: 1.0, bottom: 1.0, left: 1.0, right: 1.0, header: 0.5, footer: 0.5)
    s.add_row(["Wide Margins sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: {left: 1.0, right: 1.0, top: 1.0, bottom: 1.0, header: 0.5, footer: 0.5}
Page Setup: {}
Print Options: {}

Page Orientation Landscape

Download .xlsx

Demonstrates landscape page setup for printing.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_orientation_landscape.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Landscape") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_page_setup(orientation: :landscape)
    s.add_row(["Landscape Orientation sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: nil
Page Setup: {orientation: "landscape"}
Print Options: {}

Page Paper Size A3

Download .xlsx

Demonstrates setting paper size to A3 (paper size 8).

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "page_paper_size_a3.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("A3 Sheet") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_page_setup(paper_size: 8) # ISO A3 is paperSize="8"
    s.add_row(["ISO A3 Paper Size sheet"])
  end
end

# 2. Read the generated sheet and print page setup properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
margins = reader.page_margins(sheet: sheet.name)
setup = reader.page_setup(sheet: sheet.name)
opts = reader.print_options(sheet: sheet.name)
puts "Page Margins: #{margins.inspect}"
puts "Page Setup: #{setup.inspect}"
puts "Print Options: #{opts.inspect}"

Console Output

=== Read Validation ===
Page Margins: nil
Page Setup: {paper_size: 8}
Print Options: {}

Row Grouping

Download .xlsx

Demonstrates outline grouping for rows.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "row_grouping.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("parent") { |style| style.border_all(style: "thin", color: "FF000000").bold }
  w.add_style("child") { |style| style.border_all(style: "thin", color: "FF000000").align_horizontal("left").indent(2) }
  w.add_sheet("Row Grouping") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Parent Row 1", ""], styles: ["parent", "parent"])
    s.add_row(["Child Row 1.1", ""], outline_level: 1, styles: ["child", "child"])
    s.add_row(["Child Row 1.2", ""], outline_level: 1, styles: ["child", "child"])
  end
end

# 2. Read the generated sheet and print row attributes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
end

Console Output

=== Read Validation ===
Row 0: height=, hidden=false, outline_level=
Row 1: height=, hidden=false, outline_level=1
Row 2: height=, hidden=false, outline_level=1

Row Height Tall

Download .xlsx

Demonstrates setting very tall row heights.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "row_height_tall.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Row Height") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Very Tall Row (Height 60)", ""], height: 60, styles: ["border", "border"])
    s.add_row(["Normal Row", ""], styles: ["border", "border"])
  end
end

# 2. Read the generated sheet and print row attributes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
end

Console Output

=== Read Validation ===
Row 0: height=60.0, hidden=false, outline_level=
Row 1: height=, hidden=false, outline_level=

Row Heights

Download .xlsx

Demonstrates setting custom row heights.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "row_heights.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_style("border") { |style| style.border_all(style: "thin", color: "FF000000") }
  w.add_sheet("Heights") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row(["Normal Row", ""], styles: ["border", "border"])
    s.add_row(["Tall Row", ""], height: 40, styles: ["border", "border"])
  end
end

# 2. Read the generated sheet and print row attributes
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.each do |row|
  puts "Row #{row.index}: height=#{row.height}, hidden=#{row.hidden}, outline_level=#{row.outline_level}"
end

Console Output

=== Read Validation ===
Row 0: height=, hidden=false, outline_level=
Row 1: height=40.0, hidden=false, outline_level=

Sheet Tab Colors

Download .xlsx

Demonstrates customizing tab colors of individual worksheets.

Rendered Output (LibreOffice Calc)

Preview
Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "sheet_tab_colors.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Red Tab") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_sheet_property(:tab_color, "FFFF0000")
    s.add_row(["Red tab sheet"])
  end
  w.add_sheet("Green Tab") do |s|
    s.set_sheet_property(:tab_color, "FF00FF00")
    s.add_row(["Green tab sheet"])
  end
end

# 2. Read the generated sheet and print sheet properties
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
workbook.sheet_names.each do |s_name|
  props = reader.sheet_properties(sheet: s_name)
  puts "Sheet: #{s_name}, tab color: #{props[:tab_color].inspect}"
end

Console Output

=== Read Validation ===
Sheet: Red Tab, tab color: "FFFF0000"
Sheet: Green Tab, tab color: "FF00FF00"

Sparkline Column

Download .xlsx

Demonstrates embedded column sparklines in cell ranges.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "sparkline_column.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Sparkline") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([5, 12, 8, 15, nil])
    s.add_sparkline_group(
      type: :column,
      sparklines: [{ location_ref: "E1", data_ref: "Sparkline!A1:D1" }]
    )
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(3).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 5, B1: 12, C1: 8, D1: 15

Sparkline Line

Download .xlsx

Demonstrates embedded line sparklines in cell ranges.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "sparkline_line.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Sparkline") do |s|
    s.set_sheet_property(:fit_to_page, true)
    s.set_page_setup(fit_to_width: 1, fit_to_height: 1)
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.add_row([10, 20, 15, 30, nil])
    s.add_sparkline_group(
      type: :line,
      markers: true,
      color_series: "FF000000",
      color_markers: "FFFF0000",
      sparklines: [{ location_ref: "E1", data_ref: "Sparkline!A1:D1" }]
    )
  end
end

# 2. Read the generated sheet and print cell values
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(3).each do |row|
  row_cells = row.cells.map { |c| "#{c.ref}: #{c.value.inspect}" }
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: 10, B1: 20, C1: 15, D1: 30

Styles Fonts Fills

Download .xlsx

Demonstrates cell formatting, including custom font sizing, bold/italic text, custom text colors, and background fill colors.

Rendered Output (LibreOffice Calc)

Preview

DSL Code

# frozen_string_literal: true

require "xlsxrb"

output_path = ARGV[0] || "styles_fonts_fills.xlsx"

Xlsxrb.generate(output_path) do |w|
  w.add_style("header") do |style|
    style.bold.size(14).font_color("FFFFFFFF").fill_color("FF4F81BD")
  end

  w.add_style("highlight") do |style|
    style.italic.font_color("FFC00000").fill_color("FFFFFF00")
  end

  w.add_sheet("Styles") do
    w.set_column(0, width: 25)
    w.set_column(1, width: 25)
    w.add_row(["Header 1", "Header 2"], styles: { 0 => "header", 1 => "header" })
    w.add_row(["Normal Text", "Highlighted Text"], styles: { 1 => "highlight" })
  end
end

# 2. Read the generated sheet and print styling details
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
sheet = workbook.sheets.first
sheet.rows.first(4).each do |row|
  row_cells = row.cells.map do |c|
    xf = workbook.styles[:cell_xfs][c.style_index] if c.style_index
    font = xf ? workbook.styles[:fonts][xf[:font_id]] : nil
    fill = xf ? workbook.styles[:fills][xf[:fill_id]] : nil
    "#{c.ref}: #{c.value.inspect} (font=#{font&.[](:name)}, fill=#{fill&.[](:fg_color)&.[](:rgb)})"
  end
  puts "Row #{row.index}: #{row_cells.join(', ')}"
end

Console Output

=== Read Validation ===
Row 0: A1: "Header 1" (font=Calibri, fill=FF4F81BD), B1: "Header 2" (font=Calibri, fill=FF4F81BD)
Row 1: A2: "Normal Text" (font=, fill=), B2: "Highlighted Text" (font=Calibri, fill=FFFFFF00)

View Show Grid Lines

Download .xlsx

Demonstrates disabling visible grid lines in spreadsheet view.

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "view_show_grid_lines.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Hide Grid Lines") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_sheet_view(:show_grid_lines, false)
    s.add_row(["No Grid Lines displayed"])
  end
end

# 2. Read the generated sheet and print view configurations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
workbook.sheet_names.each do |s_name|
  view = reader.sheet_view(sheet: s_name)
  puts "Sheet '#{s_name}' views zoom scale: #{view[:zoom_scale]}%, show grid lines: #{view[:show_grid_lines]}"
end

Console Output

=== Read Validation ===
Sheet 'Hide Grid Lines' views zoom scale: %, show grid lines: false

View Zoom Scale

Download .xlsx

Demonstrates setting custom zoom scale in sheet view (e.g. 150%).

Rendered Output (LibreOffice Calc)

Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "view_zoom_scale.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("Zoom 150") do |s|
    s.set_column(0, width: 25)
    s.set_column(1, width: 25)
    s.set_sheet_view(:zoom_scale, 150)
    s.add_row(["Zoom scale is set to 150%"])
  end
end

# 2. Read the generated sheet and print view configurations
puts "=== Read Validation ==="
reader = Xlsxrb::Ooxml::Reader.new(output_path)
workbook = Xlsxrb.read(output_path)
workbook.sheet_names.each do |s_name|
  view = reader.sheet_view(sheet: s_name)
  puts "Sheet '#{s_name}' views zoom scale: #{view[:zoom_scale]}%, show grid lines: #{view[:show_grid_lines]}"
end

Console Output

=== Read Validation ===
Sheet 'Zoom 150' views zoom scale: 150%, show grid lines:

Workbook Three Sheets

Download .xlsx

Demonstrates creating workbooks with multiple worksheets.

Rendered Output (LibreOffice Calc)

Preview
Preview
Preview

DSL Code

# frozen_string_literal: true
require "xlsxrb"
output_path = ARGV[0] || "workbook_three_sheets.xlsx"
Xlsxrb.generate(output_path) do |w|
  w.add_sheet("First Sheet") { |s| s.add_row(["First Sheet Data"]) }
  w.add_sheet("Second Sheet") { |s| s.add_row(["Second Sheet Data"]) }
  w.add_sheet("Third Sheet") { |s| s.add_row(["Third Sheet Data"]) }
end

# 2. Read the generated sheet and print the sheets structure
puts "=== Read Validation ==="
workbook = Xlsxrb.read(output_path)
puts "Workbook sheets: #{workbook.sheet_names.join(', ')}"

Console Output

=== Read Validation ===
Workbook sheets: First Sheet, Second Sheet, Third Sheet