fast_xlsx 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c78ccbcfe82884370ef3e64e4613812a91c521f479495184bd99df1cb7f1d36c
4
- data.tar.gz: 86702f59f3c33c490ef3879e0178a7bcc9650fdba612bd1cd17ba24662b0392d
3
+ metadata.gz: eddcb1a0c063b94222c0a83e15b7a855a83b26674390ee87f59f1938d7007c9f
4
+ data.tar.gz: 5aa9b9a7b6dbfb70bb53364b16fa31bb2c745534aefc9f0631367ed6cf658043
5
5
  SHA512:
6
- metadata.gz: 629352aa7bf14685eef2d940f78b23e142f66b946b6d8f2eb36db0bd004574aefb2e04fd29fe2fc42e9684ac5d125725cfea5384d7a439b8f5d361411f68149c
7
- data.tar.gz: f8755a00230b81f405339f9d123344bf827c3010d80f159c0b5408e2fbcc984d3fd94758fd65e7fa5562d0e8b23825cb0d0b791bf97057db013259afd49c3c96
6
+ metadata.gz: d854850a2dd9d9b82d8bbbe4568f41336b3e4a89b977ddfcffb8e08a083305222111dded66d33e8f999dfbfae4d1da319e16f40835e83962bb7ac6081686b333
7
+ data.tar.gz: 973794fd6d14e139f8173e0726f0938f61022f5b503d5b761b4abaf089b9e0dd3debec9083248859f9380a64fd6ead89ec2efc8af64296338960b6caed1269df
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.0] - 2026-10-02
4
+
5
+ ### Added
6
+
7
+ - A Hash of options works wherever a format goes (`write(0, 0, "x", { bold: true })`, `append(row, format: { bold: true })`, table columns, conditional formats, rich strings); equal Hashes share one format.
8
+ - `ws["B2"] = value` and `ws[row, col] = value` write a cell.
9
+ - `Format#to_h` (its options) and `Format#merge` (a new format with more options, from keywords, a Hash or another Format).
10
+ - Formats with the same options are `==`; `eql?` and `hash` follow `Hash#eql?` (so `10` and `10.0` differ there), letting formats serve as Hash keys. Options may have String keys (e.g. parsed from JSON or YAML); the same option as a String and a Symbol raises `ArgumentError`.
11
+ - `Workbook.new` and `Workbook#add_worksheet` yield the new object to a block.
12
+
13
+ ### Changed
14
+
15
+ - A `Format` is frozen, and keeps frozen copies of its option values: one is shared wherever the same options are used.
16
+
17
+ ### Fixed
18
+
19
+ - `Workbook.new { |wb| ... }` ignored its block.
20
+
3
21
  ## [0.6.0] - 2026-10-02
4
22
 
5
23
  ### Added
data/README.md CHANGED
@@ -19,11 +19,36 @@ ws << ["id", "name", "created_at"] # append a row
19
19
  ws.concat(records.map { |r| [r.id, r.name, r.created_at] }) # append many rows in one call
20
20
  ws.write(0, 5, 42) # write a single cell (row, col, value)
21
21
  ws.write("F1", 42) # or by its Excel reference
22
+ ws["F1"] = 42 # the same (ws[0, 5] = 42 too)
22
23
 
23
24
  wb.properties(title: "Q3 report", author: "Zac", keywords: "Confidential") # File > Info in Excel
24
25
  wb.save("report.xlsx") # or wb.to_xlsx => binary String
25
26
  ```
26
27
 
28
+ `Workbook.new` and `add_worksheet` also take a block, which gets the new object:
29
+
30
+ ```ruby
31
+ wb = FastXlsx::Workbook.new do |wb|
32
+ wb.add_worksheet("Users") do |ws|
33
+ ws.append(%w[id name email], format: { bold: true })
34
+ User.find_each { |u| ws << u.attributes.values_at("id", "name", "email") } # a Hash's values in column order
35
+ end
36
+ end
37
+ ```
38
+
39
+ ### Rails
40
+
41
+ ```ruby
42
+ def export
43
+ wb = FastXlsx::Workbook.new(memory: :constant) # large exports: memory stays flat
44
+ ws = wb.add_worksheet("Orders")
45
+ ws.append(["Order", "Customer", "Total", "Placed at"], format: { bold: true })
46
+ Order.includes(:customer).find_each { |o| ws << [o.number, o.customer.name, o.total, o.created_at] }
47
+ send_data wb.to_xlsx, filename: "orders.xlsx",
48
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
49
+ end
50
+ ```
51
+
27
52
  ### Memory modes
28
53
 
29
54
  By default every cell stays in memory until the file is saved. For large exports, two modes write each finished row to a temp file instead:
@@ -80,6 +105,15 @@ ws.write(1, 2, Date.today, date) # format one cell
80
105
  | `locked` | `false` keeps the cell editable on a protected sheet (default `true`) |
81
106
  | `hidden` | `true` hides the cell's formula on a protected sheet |
82
107
 
108
+ A Hash of options works wherever a format goes (equal Hashes share one format), and a format can be extended:
109
+
110
+ ```ruby
111
+ ws.append(["Total", 1_234], format: { bold: true })
112
+ title = header.merge(font_size: 16) # header's options plus font_size; header.to_h lists them
113
+ ```
114
+
115
+ In a loop over many cells, create the `Format` once: building one from a Hash on every call is slower.
116
+
83
117
  Per-side borders override `border`. Unknown options and invalid values raise `ArgumentError`.
84
118
 
85
119
  Dates and times are shown as `yyyy-mm-dd` or `yyyy-mm-dd hh:mm:ss`. A format without a `num_format` (yours, a table column's or `column_format`'s) keeps its look and gets that date format added, so `append(row, format: bold)` gives bold dates; a format with a `num_format` is used as is.
data/bench/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- fast_xlsx (0.6.0)
4
+ fast_xlsx (0.7.0)
5
5
  rb_sys (~> 0.9.130)
6
6
 
7
7
  GEM
@@ -77,7 +77,7 @@ DEPENDENCIES
77
77
  CHECKSUMS
78
78
  caxlsx (4.5.0) sha256=e3d98d859f148df05d5462086b5079b523f29c1766b569535f1d68629ce743ff
79
79
  fast_excel (0.5.0) sha256=59c418bdcf586a6030798d4e3a9f575742badaceaf7bb90f38eee5feb5bdc478
80
- fast_xlsx (0.6.0)
80
+ fast_xlsx (0.7.0)
81
81
  ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
82
82
  ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39
83
83
  ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564
@@ -33,6 +33,7 @@ static ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| fast_xlsx_const(ruby, "Err
33
33
  static FORMULA: Lazy<RClass> = Lazy::new(|ruby| fast_xlsx_const(ruby, "Formula"));
34
34
  static URL: Lazy<RClass> = Lazy::new(|ruby| fast_xlsx_const(ruby, "URL"));
35
35
  static RICH_STRING: Lazy<RClass> = Lazy::new(|ruby| fast_xlsx_const(ruby, "RichString"));
36
+ static FORMAT: Lazy<RClass> = Lazy::new(|ruby| fast_xlsx_const(ruby, "Format"));
36
37
 
37
38
  // A row or column outside the sheet is a RangeError, like a negative one
38
39
  // (which fails converting to an unsigned number before reaching the writer).
@@ -1172,8 +1173,16 @@ impl Worksheet {
1172
1173
  fn write_any(ruby: &Ruby, rb_self: Obj<Self>, args: &[Value]) -> Result<Obj<Self>, Error> {
1173
1174
  let index = |i: usize| args.get(i).and_then(|v| Integer::from_value(*v));
1174
1175
  if let (3 | 4, Some(row), Some(col)) = (args.len(), index(0), index(1)) {
1175
- let format = match args.get(3) {
1176
- Some(f) => Option::<&Format>::try_convert(*f)?,
1176
+ // A Hash of options becomes a (cached) Format, as in Ruby.
1177
+ let format_arg = match args.get(3) {
1178
+ Some(f) if RHash::from_value(*f).is_some() => Some(
1179
+ ruby.get_inner(&FORMAT)
1180
+ .funcall::<_, _, Value>("_coerce", (*f,))?,
1181
+ ),
1182
+ f => f.copied(),
1183
+ };
1184
+ let format = match format_arg {
1185
+ Some(f) => Option::<&Format>::try_convert(f)?,
1177
1186
  None => None,
1178
1187
  };
1179
1188
  Self::write(
@@ -2,5 +2,5 @@
2
2
 
3
3
  module FastXlsx
4
4
  # The gem version.
5
- VERSION = "0.6.0"
5
+ VERSION = "0.7.0"
6
6
  end
data/lib/fast_xlsx.rb CHANGED
@@ -74,7 +74,9 @@ module FastXlsx
74
74
  def initialize(*parts)
75
75
  raise ArgumentError, "RichString needs at least one segment" if parts.empty?
76
76
 
77
- @segments = parts.map { |part| part.is_a?(Array) ? [part[0].to_s, part[1]] : [part.to_s, nil] }.freeze
77
+ @segments = parts.map do |part|
78
+ part.is_a?(Array) ? [part[0].to_s, Format._coerce(part[1])] : [part.to_s, nil]
79
+ end.freeze
78
80
  end
79
81
  end
80
82
 
@@ -111,21 +113,33 @@ module FastXlsx
111
113
  # must be filled top to bottom: :constant stores strings inline (memory
112
114
  # stays flat), :low keeps Excel's shared string table (memory grows with
113
115
  # the number of unique strings).
116
+ # @yieldparam workbook [Workbook] when a block is given
117
+ # @return [Workbook]
114
118
  # @raise [ArgumentError] for an unknown mode
119
+ # @example
120
+ # wb = FastXlsx::Workbook.new do |wb|
121
+ # wb.add_worksheet("Report") { |ws| ws << %w[id name] }
122
+ # end
115
123
  def self.new(memory: :standard)
116
124
  unless MEMORY_MODES.include?(memory)
117
125
  raise ArgumentError, "unknown memory mode #{memory.inspect} (expected one of #{MEMORY_MODES.join(", ")})"
118
126
  end
119
127
 
120
- _new(memory == :constant, memory == :low)
128
+ workbook = _new(memory == :constant, memory == :low)
129
+ yield workbook if block_given?
130
+ workbook
121
131
  end
122
132
 
123
133
  # @param name [String, nil] nil takes the first free "SheetN"
134
+ # @yieldparam worksheet [Worksheet] when a block is given
124
135
  # @return [Worksheet]
125
136
  # @raise [FastXlsx::Error] for an invalid name or one already used
126
137
  # (names ignore case)
127
138
  def add_worksheet(name = nil)
128
- _add_worksheet(name).tap { |ws| worksheets << ws }
139
+ worksheet = _add_worksheet(name)
140
+ worksheets << worksheet
141
+ yield worksheet if block_given?
142
+ worksheet
129
143
  end
130
144
 
131
145
  # The same Worksheet objects add_worksheet returned, so their append
@@ -175,7 +189,7 @@ module FastXlsx
175
189
  # @param value [Numeric, String, Time, Date, DateTime, true, false, nil,
176
190
  # Formula, URL, RichString, #to_s] dates get yyyy-mm-dd (hh:mm:ss) unless
177
191
  # the format has a num_format
178
- # @param format [Format, nil]
192
+ # @param format [Format, Hash, nil] a Hash of options works too
179
193
  # @return [self]
180
194
  #
181
195
  # @!method <<(values)
@@ -243,18 +257,28 @@ module FastXlsx
243
257
  # wrapper. Other forms come here.
244
258
  def _write_ref(*args)
245
259
  row, col, (value, format) = CellRange.cell(args, 1..2)
246
- _write(row, col, value, format)
260
+ _write(row, col, value, Format._coerce(format))
247
261
  self
248
262
  end
249
263
  private :_write_ref
250
264
 
265
+ # Writes one cell: ws["B2"] = 42 or ws[1, 1] = 42. Use {#write} to give
266
+ # it a format.
267
+ # @overload []=(ref, value)
268
+ # @overload []=(row, col, value)
269
+ def []=(*cell, value)
270
+ row, col = CellRange.cell(cell)
271
+ write(row, col, value)
272
+ value
273
+ end
274
+
251
275
  # Appends a row after the last row written.
252
276
  # @param values [Array] cell values, as for {#write}
253
- # @param format [Format, Array<Format, nil>, nil] one for every cell, or
277
+ # @param format [Format, Hash, Array<Format, Hash, nil>, nil] one for every cell, or
254
278
  # one per cell
255
279
  # @return [self]
256
280
  def append(values, format: nil)
257
- _append(values, format)
281
+ _append(values, format.is_a?(Array) ? format.map { |f| Format._coerce(f) } : Format._coerce(format))
258
282
  end
259
283
 
260
284
  # @param columns [Integer, Range<Integer>]
@@ -291,7 +315,7 @@ module FastXlsx
291
315
  # @raise [FastXlsx::Error] when it overlaps an earlier merge
292
316
  def merge_range(*args)
293
317
  range, (value, format) = CellRange.split(args, 1..2)
294
- _merge_range(*range, value, format)
318
+ _merge_range(*range, value, Format._coerce(format))
295
319
  end
296
320
 
297
321
  # Highlights cells in the range by rule; see the README for each type's
@@ -300,11 +324,12 @@ module FastXlsx
300
324
  # @param type [Symbol] :cell, :text, :formula, :data_bar or :color_scale
301
325
  # @option options [Symbol] :criteria e.g. :>, :between, :contains
302
326
  # @option options [Numeric, String, Array] :value
303
- # @option options [Format] :format
327
+ # @option options [Format, Hash] :format
304
328
  # @option options [Integer] :colors 2 or 3 (:color_scale)
305
329
  # @return [self]
306
- def conditional_format(*range, type:, **)
307
- _conditional_format(*CellRange.split(range).first, { type: type, ** })
330
+ def conditional_format(*range, type:, **options)
331
+ options[:format] = Format._coerce(options[:format]) if options.key?(:format)
332
+ _conditional_format(*CellRange.split(range).first, { type: type, **options })
308
333
  end
309
334
 
310
335
  # Restricts what can be entered in the range; see the README.
@@ -364,8 +389,13 @@ module FastXlsx
364
389
  # @option options [String] :name
365
390
  # @option options [Boolean] :total_row, :banded_rows, :autofilter
366
391
  # @return [self]
367
- def add_table(*range, **)
368
- _add_table(*CellRange.split(range).first, { ** })
392
+ def add_table(*range, **options)
393
+ if options[:columns].is_a?(Array)
394
+ options[:columns] = options[:columns].map do |column|
395
+ column.is_a?(Hash) && column.key?(:format) ? column.merge(format: Format._coerce(column[:format])) : column
396
+ end
397
+ end
398
+ _add_table(*CellRange.split(range).first, options)
369
399
  end
370
400
 
371
401
  # Printed page header, using Excel codes such as "&CPage &P of &N".
@@ -506,20 +536,20 @@ module FastXlsx
506
536
  # may combine them or show the row's. Each row is kept (about 1 KB) until
507
537
  # saving, so style a whole sheet with {#column_format}.
508
538
  # @param rows [Integer, Range<Integer>]
509
- # @param format [Format]
539
+ # @param format [Format, Hash]
510
540
  # @return [self]
511
541
  # @raise [FastXlsx::Error] in :constant / :low mode, for rows already on disk
512
542
  def row_format(rows, format)
513
- _row_format(*CellRange.bounds(rows), format)
543
+ _row_format(*CellRange.bounds(rows), Format._coerce(format))
514
544
  self
515
545
  end
516
546
 
517
547
  # Default format for cells in these columns that are written without one.
518
548
  # @param columns [Integer, Range<Integer>]
519
- # @param format [Format]
549
+ # @param format [Format, Hash]
520
550
  # @return [self]
521
551
  def column_format(columns, format)
522
- _column_format(*CellRange.bounds(columns), format)
552
+ _column_format(*CellRange.bounds(columns), Format._coerce(format))
523
553
  self
524
554
  end
525
555
  end
@@ -633,9 +663,88 @@ module FastXlsx
633
663
  # border_color:, locked:, hidden:
634
664
  # @raise [ArgumentError] for an unknown option or an invalid value
635
665
  def self.new(**options)
666
+ options = _options(options)
636
667
  # Apply border: first so border_left: etc. override it whatever the order.
637
- options = { border: options[:border], **options.except(:border) } if options.key?(:border)
638
- _new(options)
668
+ ordered = options.key?(:border) ? { border: options[:border], **options.except(:border) } : options
669
+ format = _new(ordered)
670
+ format.instance_variable_set(:@options, options)
671
+ format.freeze
672
+ end
673
+
674
+ # Options with Symbol keys (String ones come from JSON or YAML) and frozen
675
+ # copies of the values, so the format can't change behind the file's back.
676
+ # @api private
677
+ def self._options(given)
678
+ options = given.to_h { |key, value| [key.to_sym, _frozen(value)] }.freeze
679
+ return options if options.size == given.size
680
+
681
+ twice = given.keys.map(&:to_sym).tally.select { |_, count| count > 1 }.keys
682
+ raise ArgumentError, "format option given twice (as a String and a Symbol): #{twice.join(", ")}"
683
+ end
684
+
685
+ # @api private
686
+ def self._frozen(value)
687
+ value.frozen? ? value : value.dup.freeze
688
+ end
689
+
690
+ # The options this format was created with.
691
+ # @return [Hash{Symbol => Object}] frozen
692
+ def to_h
693
+ @options
694
+ end
695
+
696
+ # Formats with the same options are equal; 10 and 10.0 count as the same.
697
+ # @return [Boolean]
698
+ def ==(other)
699
+ other.is_a?(Format) && to_h == other.to_h
700
+ end
701
+
702
+ # Equal as Hash keys: like Hash#eql?, 10 and 10.0 differ, matching {#hash}.
703
+ # @return [Boolean]
704
+ def eql?(other)
705
+ other.is_a?(Format) && to_h.eql?(other.to_h)
706
+ end
707
+
708
+ # @return [Integer]
709
+ def hash
710
+ [Format, to_h].hash
711
+ end
712
+
713
+ # A new format with these options added to (or replacing) this one's.
714
+ # @param other [Format, Hash, nil] options to add, like Hash#merge
715
+ # @example
716
+ # title = header.merge(font_size: 16)
717
+ # bold_money = bold.merge(money)
718
+ # @return [Format]
719
+ # @raise [TypeError] when other has no #to_h
720
+ def merge(other = nil, **)
721
+ unless other.respond_to?(:to_h)
722
+ raise TypeError,
723
+ "can't merge #{other.class} into a Format: use a Hash or a Format"
724
+ end
725
+
726
+ Format.new(**to_h, **other.to_h, **)
727
+ end
728
+
729
+ # Distinct Hashes kept by {._coerce}; past this, the oldest is dropped.
730
+ CACHE_SIZE = 1_024
731
+
732
+ # A Format for a Hash of options; equal Hashes share one, so a Hash written
733
+ # with every row costs about as much as a Format made once. Other values
734
+ # are returned as they are. An invalid Hash raises and isn't kept.
735
+ # @api private
736
+ def self._coerce(format)
737
+ return format unless format.is_a?(Hash)
738
+
739
+ # ponytail: evicts the oldest entry, not the least used one, since
740
+ # moving each hit costs every write; a Hash still in use is rebuilt at
741
+ # worst once per CACHE_SIZE new Hashes.
742
+ cache = (@cache ||= {})
743
+ cache.fetch(format) do
744
+ coerced = new(**format)
745
+ cache.shift if cache.size >= CACHE_SIZE
746
+ cache[format.dup.freeze] = coerced
747
+ end
639
748
  end
640
749
  end
641
750
  end
data/sig/fast_xlsx.rbs CHANGED
@@ -8,11 +8,14 @@ module FastXlsx
8
8
  def read: () -> String
9
9
  end
10
10
 
11
+ # A Format, or a Hash of its options.
12
+ type format = Format | Hash[Symbol | String, untyped]
13
+
11
14
  type cell = Numeric | String | Time | Date | Formula | URL | RichString | bool | nil | _ToS
12
15
 
13
16
  class RichString
14
17
  attr_reader segments: Array[[String, Format?]]
15
- def initialize: (*(_ToS | [_ToS, Format?]) parts) -> void
18
+ def initialize: (*(_ToS | [_ToS, format?]) parts) -> void
16
19
  end
17
20
 
18
21
  class Formula
@@ -28,8 +31,8 @@ module FastXlsx
28
31
 
29
32
  class Workbook
30
33
  MEMORY_MODES: Array[Symbol]
31
- def self.new: (?memory: :standard | :constant | :low) -> Workbook
32
- def add_worksheet: (?String? name) -> Worksheet
34
+ def self.new: (?memory: :standard | :constant | :low) ?{ (Workbook) -> void } -> Workbook
35
+ def add_worksheet: (?String? name) ?{ (Worksheet) -> void } -> Worksheet
33
36
  def worksheets: () -> Array[Worksheet]
34
37
  def worksheet: (String name) -> Worksheet?
35
38
  def properties: (?title: String, ?subject: String, ?author: String, ?manager: String,
@@ -53,18 +56,25 @@ module FastXlsx
53
56
  ?rotation: Integer, ?indent: Integer,
54
57
  ?border: border, ?border_left: border, ?border_right: border,
55
58
  ?border_top: border, ?border_bottom: border, ?border_color: color) -> Format
59
+ def to_h: () -> Hash[Symbol, untyped]
60
+ def merge: (?format? other, **untyped options) -> Format
61
+ def ==: (untyped other) -> bool
62
+ def eql?: (untyped other) -> bool
63
+ def hash: () -> Integer
56
64
  end
57
65
 
58
66
  class Worksheet
59
- def write: (Integer row, Integer col, cell value, ?Format? format) -> self
60
- | (String cell, cell value, ?Format? format) -> self
61
- def append: (Array[cell] values, ?format: Format? | Array[Format?]) -> self
67
+ def []=: (String cell, cell value) -> cell
68
+ | (Integer row, Integer col, cell value) -> cell
69
+ def write: (Integer row, Integer col, cell value, ?format? format) -> self
70
+ | (String cell, cell value, ?format? format) -> self
71
+ def append: (Array[cell] values, ?format: format? | Array[format?]) -> self
62
72
  def <<: (Array[cell] row) -> self
63
73
  def concat: (Array[Array[cell]] rows) -> self
64
74
  def column_width: (Integer | Range[Integer] columns, Numeric width) -> self
65
75
  def hide_rows: (Integer | Range[Integer] rows) -> self
66
76
  def hide_columns: (Integer | Range[Integer] columns) -> self
67
- def row_format: (Integer | Range[Integer] rows, Format format) -> self
77
+ def row_format: (Integer | Range[Integer] rows, format format) -> self
68
78
  def default_row_height: (Numeric height) -> self
69
79
  def selection: (*cell_range range) -> self
70
80
  def top_left_cell: (Integer row, Integer col) -> self
@@ -74,7 +84,7 @@ module FastXlsx
74
84
  | :inconsistent_column_formula
75
85
  def ignore_error: (*cell_range | ignorable_error args) -> self
76
86
  def unprotect_range: (*cell_range range, ?name: String?, ?password: String?) -> self
77
- def column_format: (Integer | Range[Integer] columns, Format format) -> self
87
+ def column_format: (Integer | Range[Integer] columns, format format) -> self
78
88
  def autofit: () -> self
79
89
  # A cell range: four 0-based numbers, an Excel reference ("A1:D10"), or
80
90
  # rows and columns as Integers or Ranges. Methods with options take it as
@@ -107,13 +117,13 @@ module FastXlsx
107
117
  def group_rows: (Integer | Range[Integer] rows, ?collapsed: bool) -> self
108
118
  def group_columns: (Integer | Range[Integer] columns, ?collapsed: bool) -> self
109
119
  def protect: (?password: String?, ?allow: protect_action | Array[protect_action] | nil) -> self
110
- def merge_range: (Integer first_row, Integer first_col, Integer last_row, Integer last_col, cell value, ?Format? format) -> self
111
- | (String range, cell value, ?Format? format) -> self
112
- | (indexes rows, indexes cols, cell value, ?Format? format) -> self
120
+ def merge_range: (Integer first_row, Integer first_col, Integer last_row, Integer last_col, cell value, ?format? format) -> self
121
+ | (String range, cell value, ?format? format) -> self
122
+ | (indexes rows, indexes cols, cell value, ?format? format) -> self
113
123
  def conditional_format: (*cell_range range,
114
124
  type: :cell | :text | :formula | :data_bar | :color_scale,
115
125
  ?criteria: Symbol, ?value: Numeric | String | Array[Numeric | String],
116
- ?format: Format, ?colors: 2 | 3) -> self
126
+ ?format: format, ?colors: 2 | 3) -> self
117
127
  def data_validation: (*cell_range range,
118
128
  type: :list | :whole_number | :decimal | :text_length,
119
129
  ?criteria: Symbol, ?value: Numeric | String | Array[Numeric | String],
@@ -133,7 +143,7 @@ module FastXlsx
133
143
  | (String cell, type: Symbol, series: Array[chart_series],
134
144
  ?title: String, ?x_axis: String, ?y_axis: String,
135
145
  ?width: Integer, ?height: Integer) -> self
136
- type table_column = String | { header: String, ?total: Symbol, ?total_label: String, ?format: Format }
146
+ type table_column = String | { header: String, ?total: Symbol, ?total_label: String, ?format: format }
137
147
 
138
148
  def add_table: (*cell_range range,
139
149
  ?columns: Array[table_column], ?style: Symbol, ?name: String,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_xlsx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac