xlsxrb 0.1.13 → 0.1.14
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 +4 -4
- data/CHANGELOG.md +57 -0
- data/README.md +2 -0
- data/lib/xlsxrb/colors.rb +118 -0
- data/lib/xlsxrb/elements/cell.rb +205 -16
- data/lib/xlsxrb/elements/column.rb +6 -4
- data/lib/xlsxrb/elements/coordinate_access.rb +32 -0
- data/lib/xlsxrb/elements/image.rb +128 -0
- data/lib/xlsxrb/elements/row.rb +206 -9
- data/lib/xlsxrb/elements/styles.rb +157 -0
- data/lib/xlsxrb/elements/types.rb +95 -1
- data/lib/xlsxrb/elements/workbook.rb +85 -4
- data/lib/xlsxrb/elements/worksheet.rb +424 -29
- data/lib/xlsxrb/elements.rb +2 -0
- data/lib/xlsxrb/number_formatter.rb +429 -0
- data/lib/xlsxrb/ooxml/cfb.rb +1 -1
- data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +7 -5
- data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +11 -4
- data/lib/xlsxrb/ooxml/reader.rb +12 -14
- data/lib/xlsxrb/ooxml/shared_strings_parser.rb +7 -1
- data/lib/xlsxrb/ooxml/styles_parser.rb +39 -9
- data/lib/xlsxrb/ooxml/utils.rb +34 -18
- data/lib/xlsxrb/ooxml/workbook_parser.rb +53 -15
- data/lib/xlsxrb/ooxml/workbook_writer.rb +65 -14
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +319 -79
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +206 -61
- data/lib/xlsxrb/ooxml/writer/features_xml.rb +4 -2
- data/lib/xlsxrb/ooxml/writer.rb +14 -0
- data/lib/xlsxrb/ooxml/zip_reader.rb +109 -25
- data/lib/xlsxrb/stream_row.rb +243 -16
- data/lib/xlsxrb/stream_sheet.rb +414 -15
- data/lib/xlsxrb/stream_writer.rb +213 -17
- data/lib/xlsxrb/style_builder.rb +308 -22
- data/lib/xlsxrb/utils.rb +158 -0
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb/workbook_builder.rb +73 -3
- data/lib/xlsxrb/worksheet_builder.rb +227 -16
- data/lib/xlsxrb.rb +578 -79
- data/sig/generated/xlsxrb/colors.rbs +40 -0
- data/sig/generated/xlsxrb/elements/cell.rbs +113 -8
- data/sig/generated/xlsxrb/elements/column.rbs +3 -2
- data/sig/generated/xlsxrb/elements/coordinate_access.rbs +18 -0
- data/sig/generated/xlsxrb/elements/image.rbs +82 -0
- data/sig/generated/xlsxrb/elements/row.rbs +83 -4
- data/sig/generated/xlsxrb/elements/styles.rbs +79 -0
- data/sig/generated/xlsxrb/elements/types.rbs +43 -0
- data/sig/generated/xlsxrb/elements/workbook.rbs +51 -2
- data/sig/generated/xlsxrb/elements/worksheet.rbs +231 -18
- data/sig/generated/xlsxrb/number_formatter.rbs +132 -0
- data/sig/generated/xlsxrb/ooxml/reader.rbs +6 -0
- data/sig/generated/xlsxrb/ooxml/shared_strings_parser.rbs +2 -0
- data/sig/generated/xlsxrb/ooxml/styles_parser.rbs +5 -2
- data/sig/generated/xlsxrb/ooxml/utils.rbs +17 -8
- data/sig/generated/xlsxrb/ooxml/workbook_parser.rbs +9 -3
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +28 -6
- data/sig/generated/xlsxrb/ooxml/worksheet_writer.rbs +3 -1
- data/sig/generated/xlsxrb/ooxml/writer.rbs +2 -0
- data/sig/generated/xlsxrb/ooxml/zip_reader.rbs +10 -0
- data/sig/generated/xlsxrb/stream_row.rbs +100 -6
- data/sig/generated/xlsxrb/stream_sheet.rbs +247 -13
- data/sig/generated/xlsxrb/stream_writer.rbs +120 -14
- data/sig/generated/xlsxrb/style_builder.rbs +55 -18
- data/sig/generated/xlsxrb/utils.rbs +119 -0
- data/sig/generated/xlsxrb/workbook_builder.rbs +26 -0
- data/sig/generated/xlsxrb/worksheet_builder.rbs +107 -11
- data/sig/generated/xlsxrb.rbs +186 -27
- metadata +11 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 476e6f6e689eb65fecbbda4b81592c124b50f16fff0bbc9fec027a1f55ed4454
|
|
4
|
+
data.tar.gz: 8364dc6bff9b5f9601dc4cb375ef27b0456b7f88e721b2b52d1db7ba342c7de5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31f365a17ad3f5976033ddc7a9220c5606c6d8f6acfca356ef1b3404cd1ed6d1f86d2c86d57a5e27daf15a46bea3d1c193f4fb60662b2eccbc7078fe41777bbb
|
|
7
|
+
data.tar.gz: 67fe19a961f2bb204d19e5b9a49ade2c01e48de7d6a09ac1c87f7c591b570c0ba64494b43ce59d3ea492a70e18cf967d775af4fb55623287ab6b7b648bb0843c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.1.14] - 2026-10-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Non-self-closing `<sheet>` and `<xf>` tag compatibility: Verify and support spreadsheet XML where `<sheet>...</sheet>` in `workbook.xml` or `<xf>...</xf>` in `styles.xml` are serialized with explicit closing tags rather than self-closing syntax.
|
|
7
|
+
- Namespace prefix resilience for relationship and embed attributes: Match relationship and embed attributes by local name or any namespace prefix (`r:id`, `d3p1:id`, `rel:id`, `id`, `r:embed`, `embed`) across `WorkbookListener`, `HyperlinksListener`, `DrawingListener`, and `WorksheetParser`, ensuring reliable sheet, hyperlink, and media resolution for non-standard XML generators.
|
|
8
|
+
- UTF-16LE, UTF-16BE, and UTF-8 BOM encoding normalization in `ZipReader`: Automatically detect and transcode Byte Order Mark (BOM) encoded XML streams (`\xFF\xFE`, `\xFE\xFF`, and `\xEF\xBB\xBF`) to UTF-8 in `ZipReader#read_entry` and `EntryStreamIO`, enabling seamless parsing of workbooks generated on Windows Phone and legacy platforms.
|
|
9
|
+
- XML 1.0 line ending normalization (`\r\n` and `\r` to `\n`): Normalize line breaks in shared strings, inline strings, and cell text values per W3C XML 1.0 §2.11 across `SharedStringsParser` and `WorksheetParser`.
|
|
10
|
+
- Whitespace and newline tolerance in cell regex scanning: Allow whitespace and newline sequences between `<c>` child tags (`<f>`, `<v>`, `<is>`) and strip whitespace on extracted values in `WorksheetParser`, ensuring reliable parsing of pretty-printed or formatted worksheet XML.
|
|
11
|
+
- Sequential row index fallback for omitted `r` attributes: Track previous row index and fall back to sequential 1-based indexing when `<row>` elements omit the `r` attribute per ECMA-376 Part 1 §18.3.1.73 across direct string scanning, chunked stream scanning, and event scanning in `WorksheetParser`.
|
|
12
|
+
- Case-insensitive part name lookup in `ZipReader`: Fall back to case-insensitive lookup for package part entries per ECMA-376 Part 2 §8.1.1, allowing workbooks with case-varying part names (such as lower-case `xl/sharedstrings.xml` or `xl/styles.xml`) to resolve transparently.
|
|
13
|
+
- Windows backslash path separator normalization in `ZipReader`: Normalize Windows backslash separators (`\`) in ZIP central directory and local headers to standard forward slashes (`/`), enabling transparent extraction and catalog lookup for XLSX archives generated on Windows.
|
|
14
|
+
- First-class sparkline groups on worksheet and `add_sparkline` helper: Expose `sparkline_groups` reader and keyword argument on `Elements::Worksheet`, propagate `ws.sparkline_groups` during `Xlsxrb.write` DOM serialization, and add `add_sparkline(location:, range:, type:, **opts)` helper to `WorksheetBuilder`, `StreamWriter`, and `StreamWriter::SheetContext` supporting `:win_loss` mapping to `"stacked"`.
|
|
15
|
+
- High-level print area and print titles DSL: Add `print_area`, `print_titles`, `repeat_rows`, and `repeat_columns` to `WorksheetBuilder`, `StreamWriter::SheetContext`, and `StreamWriter`, expose `print_area` and `print_titles` on `Elements::Worksheet`, and auto-generate `_xlnm.Print_Area` and `_xlnm.Print_Titles` defined names in `WorkbookBuilder#build` and `Xlsxrb.write` DOM export.
|
|
16
|
+
- ECMA-376 indexed color palette and `Xlsxrb::Colors`: Add `Xlsxrb::Colors` providing `INDEXED_COLORS` (indices 0..63 per ECMA-376 Part 4 §18.8.27), `palette_color`, and `to_hex` utilities, expose `Xlsxrb.palette_color` and `Xlsxrb.to_hex_color` facade methods, and resolve integer palette indices 0..63 automatically in `StyleBuilder.resolve_color`.
|
|
17
|
+
- Flexible rich text run input in `Xlsxrb.rich_text`: Support `[text, font_hash]` pair arrays, alternating varargs of plain strings and format hashes or objects responding to `to_font_hash`, and mixed `Elements::RichTextRun` instances.
|
|
18
|
+
- First-class `Elements::Hyperlink`, `Xlsxrb.hyperlink`, and `Cell#tooltip`: Add `Elements::Hyperlink` data class and `Xlsxrb.hyperlink` factory helper with `tooltip:` support, expose `Cell#tooltip` and `:tooltip`, `:url` symbol key access on `Elements::Cell`, and support `Elements::Hyperlink` instances in `WorksheetBuilder#hyperlink`, `StreamWriter#hyperlink`, and `Ooxml::Writer#hyperlink`.
|
|
19
|
+
- Array and dynamic array formula serialization and `Xlsxrb.array_formula`: Add `Xlsxrb.array_formula(expression, ref, cached_value:)` factory method, extend `Xlsxrb.formula` with optional `type:` and `ref:` keywords, and serialize `<f t="array" ref="...">` and shared formula attributes across all `WorksheetWriter` serialization paths.
|
|
20
|
+
- First-class `style_index:` keyword on `Elements::Column`: Add `style_index:` keyword argument directly to `Elements::Column.new`, storing it in `Data.define` attributes and populating it from `rc[:style_index]` during worksheet parsing and DSL column definitions.
|
|
21
|
+
- In-memory streaming write and row append chaining: Support `Xlsxrb.write` with omitted target in block mode to return an in-memory binary String, support self-returning `<<` row appending for chaining across `StreamWriter`, `SheetContext`, and `WorksheetBuilder`, and add `add_row` aliases.
|
|
22
|
+
- Unified color and border style normalizers in `StyleBuilder`: Add `StyleBuilder.normalize_color` (supporting 140+ CSS named colors, `#RGB`, `#RRGGBB`, `#AARRGGBB` hex strings, numeric RGB integers, and optional alpha channel) and `StyleBuilder.normalize_border_style` (supporting border style symbols, aliases, strings, and 0..13 numeric border indices).
|
|
23
|
+
- Public date and time serial conversion utilities: Expose `date_to_serial`, `serial_to_date`, `datetime_to_serial`, and `serial_to_time` (aliased `serial_to_datetime`) on `Xlsxrb` and `Xlsxrb::Utils` for converting Ruby `Date` and `Time` instances to and from Excel 1900 and 1904 serial numbers.
|
|
24
|
+
- Cascade style inheritance and column styles: Support cascade style inheritance (Cell Style > Row Style > Column Style) in `WorksheetWriter`, and add `style:` parameter to `StreamWriter#column` and `WorksheetBuilder#column`.
|
|
25
|
+
- Embedded drawing and image extraction: Add `Elements::Image` representing anchored embedded images, expose `images`, `images_at`, and `with_images` across `StreamSheet` and `Elements::Worksheet`, and expose `images` and `images_at` across `Elements::Workbook`.
|
|
26
|
+
- Configurable sparse vs padded row and cell iteration: Add `pad_empty_rows` and `pad_empty_cells` options to `Xlsxrb.read`, `Xlsxrb.build_worksheet`, `StreamSheet`, `WorksheetParser.each_row`, and `Elements::Worksheet` to pad skipped rows or missing cells up to the maximum column, and add `StreamRow#to_h` and `Elements::Row#cells_hash` for coordinate-keyed row maps.
|
|
27
|
+
- Row XML metadata accessors and serialization: Expose row XML metadata (`collapsed`, `collapsed?`, `hidden?`, `custom_height?`, `attributes`) on `StreamRow` and `Elements::Row`, support `collapsed:` in `StreamWriter#row` and `WorksheetBuilder#row`, and serialize `collapsed="1"` in `WorksheetWriter`.
|
|
28
|
+
- Format classification helpers: Add `Elements::Styles#format_code_for` and `#classification_for` aliases, allow `NumberFormatter` format predicates (`date_format?`, `time_format?`, etc.) to resolve built-in formats by `num_fmt_id`, and expose `format_type`, `date_format?`, and `time_format?` on `Elements::Cell`.
|
|
29
|
+
- Date1904 accessor: Expose `Ooxml::Reader#date1904?` and add `date1904:` keyword argument to `Elements::Workbook#initialize`.
|
|
30
|
+
- Coordinate utilities module: Add `Xlsxrb::Utils` exposing public coordinate helpers (`ref_to_row_col`, `row_col_to_ref`, `col_name_to_index`, `col_index_to_name`, `split_coordinate`).
|
|
31
|
+
- Configurable trailing empty row trimming: Add `trim_empty_rows` option across `Xlsxrb.read`, `Xlsxrb.build_worksheet`, `WorksheetParser.each_row`, `StreamSheet#initialize`, `StreamSheet#each_row`, `StreamSheet#each_row_values`, `StreamSheet#each`, `Elements::Worksheet#initialize`, `Elements::Worksheet#each_row`, and `Elements::Worksheet#each_row_values` to omit trailing empty rows, and add `empty?` predicate to `StreamRow` and `Elements::Row`.
|
|
32
|
+
- Direct typed values streaming iterator: Add `StreamSheet#each_row_values` and `Elements::Worksheet#each_row_values` to stream row values directly as Arrays without allocating `Elements::Cell` objects, and add `type_cast: true` support across `StreamSheet#each_row_values`, `Elements::Worksheet#each_row_values`, `StreamRow#values`, and `Elements::Row#values` to coerce date/time serial numbers into `Date` and `Time` instances.
|
|
33
|
+
- Precomputed number format classifications in Styles: Add `Xlsxrb::Elements::Styles` (subclass of `Hash`) with precomputed $O(1)$ format classification lookups (`number_format`, `format_type`, `date_format?`, `datetime_format?`, `time_format?`, `date_only_format?`), update `StylesParser.parse` to return `Elements::Styles`, and add classification helper methods to `Xlsxrb::NumberFormatter`.
|
|
34
|
+
- Worksheet dimension and coordinate bounds: Expose `dimension`, `first_row`, `first_column` (aliased `first_col`), `last_row`, and `last_column` (aliased `last_col`) on `StreamSheet` and `Elements::Worksheet` (and `Elements::CoordinateAccess`), lazily extracting `<dimension ref="..."/>` in $O(1)$ memory without scanning the full sheet.
|
|
35
|
+
- Date1904 propagation to streaming sheets and rows: Propagate the workbook's 1904 date system flag to `StreamSheet` and `StreamRow`, expose `date1904?` on `StreamSheet`, `StreamRow`, `Elements::Worksheet`, and `Elements::Cell`, and default `Cell#to_date` and `Cell#to_time` to the cell's `date1904` setting.
|
|
36
|
+
- `Elements::RichTextRun`: Add `RichTextRun` data class representing formatted text runs within `RichText`, supporting hash-like bracket access and seamless integration with `Xlsxrb.rich_text`.
|
|
37
|
+
- First-class conditional formatting and data validation on `Elements::Worksheet`: Expose `conditional_formatting` (and alias `conditional_formats`) and `data_validations` as first-class fields on `Elements::Worksheet`, populate them during round-trip parsing in `Xlsxrb.build_worksheet`, and serialize them in in-memory workbook serialization.
|
|
38
|
+
- Date1904 calendar system arithmetic: Support the 1904 date system (1904-01-01 base epoch) across serial date conversions, `Cell#to_date`, `Cell#to_time`, `Elements::Workbook#date1904?`, `Ooxml::Reader`, `Ooxml::WorksheetWriter`, `Ooxml::WorkbookWriter`, and `StreamWriter`.
|
|
39
|
+
- Row and column styles persistence: Expose `style_index` on `Row`, `Column`, and `StreamRow`, and persist row and column styles (`<row s="..." customFormat="1">` and `<col style="..."/>`) during serialization and round-trip parsing.
|
|
40
|
+
- Styles metadata persistence: Support border colors, cell alignment, and protection attributes in stylesheet generation and round-trip parsing.
|
|
41
|
+
- Dual format support for `num_fmts`: Support both `Hash` (`{ 164 => "format" }`) and `Array` (`[{ num_fmt_id: 164, format_code: "format" }]`) structures for custom number formats in `WorkbookWriter`.
|
|
42
|
+
- Initial shared strings table seeding: Support pre-seeding `sst` in `Xlsxrb.write` when `workbook.shared_strings` is provided.
|
|
43
|
+
- Sheet visibility state: Support worksheet visibility state (`state`, `hidden?`, `visible?`) across `StreamSheet`, `Elements::Worksheet`, `WorkbookParser`, `WorkbookBuilder`, and `WorkbookWriter`, preserving `:visible`, `:hidden`, and `:very_hidden` visibility in streaming read, in-memory representations, and XML serialization.
|
|
44
|
+
- Workbook defined names: Parse `<definedNames>` in `WorkbookParser` and expose `defined_names` array and `defined_name(name, sheet: nil)` lookup on `Elements::Workbook`, supporting global and sheet-scoped named ranges and formula constants.
|
|
45
|
+
- Cell formula query and expression methods: Expose `formula?` predicate and `formula_expression` string accessor on `Elements::Cell`, and normalize empty formula expressions to `nil` in streaming and DOM cell parsing.
|
|
46
|
+
- Worksheet and cell hyperlinks: Parse and expose hyperlink metadata across `StreamSheet#hyperlinks`, `Elements::Worksheet#hyperlinks`, and `Elements::Cell#hyperlink`, `#link?`, and `#url`, supporting external targets and internal sheet references in streaming read, DOM models, and builders.
|
|
47
|
+
- Worksheet and cell comments: Parse and expose comment and note metadata across `StreamSheet#comments`, `StreamSheet#comment`, `Elements::Worksheet#comments`, and `Elements::Cell#comment`, `#comment?`, and `#comment_text`, supporting comment annotations and coordinate lookups in streaming read, DOM models, and builders.
|
|
48
|
+
- Number formatting engine and extended cell metadata: Add `Xlsxrb::NumberFormatter` supporting standard and custom OpenXML format codes (currencies, percentages, date/time, fixed-point padding, accounting patterns, scientific notation, and text), expose `formatted_value`, `raw_value`, and `format_code` on `Elements::Cell`, add `formatted_value` coordinate lookups on `Elements::Worksheet`, `StreamSheet`, and `Elements::Workbook`, and expose `raw_values`, `formatted_values`, and `formulas` metadata on `Elements::Row` and `StreamRow`.
|
|
49
|
+
- Fallback serialization for DOM model attributes: Support serializing first-class `ws.state`, `ws.comments`, `ws.hyperlinks`, and `workbook.defined_names` in `Xlsxrb.write(workbook)` when not explicitly packaged inside `unmapped_data[:facade]` metadata.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
- Optimize chunked streaming read performance: Hoist `</sheetData>` tag lookup outside row iteration, eliminate byte delimiter array allocations, and terminate entry inflation early once worksheet rows are fully parsed, restoring streaming read throughput faster than in-memory read while preserving $O(1)$ memory consumption.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
- Fallback cached value for formula cells: Emit `<v>0</v>` instead of omitting `<v>` when a formula cell does not specify a cached value, ensuring compatibility with OpenXML parsers (such as Roo and LibreOffice) that discard formula cells lacking `<v>` elements.
|
|
56
|
+
- Shared formula cell parsing: Support self-closing formula tags (e.g. `<f t="shared" si="0"/>`) in `WorksheetParser` regex scanners, preventing cells containing shared formulas from being silently omitted.
|
|
57
|
+
- Fixed missing `dcterms:created` and `dcterms:modified` serialization in `WorkbookWriter` core properties (`docProps/core.xml`).
|
|
58
|
+
- Prevent `Encoding::CompatibilityError` in `Xlsxrb.read` and `Cfb::Reader.cfb?` when inspecting raw string buffers in UTF-8 encoding.
|
|
59
|
+
|
|
3
60
|
## [0.1.13] - 2026-09-25
|
|
4
61
|
|
|
5
62
|
### Added
|
data/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A Ruby library for reading and writing XLSX files with streaming support.
|
|
4
4
|
|
|
5
|
+
Drop-in compatibility adapters for peer Ruby XLSX libraries are available at [xlsxrb-adapters](https://github.com/niku/xlsxrb-adapters).
|
|
6
|
+
|
|
5
7
|
## Motivation
|
|
6
8
|
|
|
7
9
|
The Ruby ecosystem has several XLSX libraries designed for specific tradeoffs:
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rbs_inline: enabled
|
|
4
|
+
|
|
5
|
+
module Xlsxrb
|
|
6
|
+
# ECMA-376 Part 4 §18.8.27 Standard Indexed Color Palette and utilities.
|
|
7
|
+
module Colors
|
|
8
|
+
# Standard ECMA-376 indexed colors (indices 0 through 63 as 6-character RRGGBB hex strings).
|
|
9
|
+
# Indices 8 through 63 represent the classic 56-color palette.
|
|
10
|
+
INDEXED_COLORS = [
|
|
11
|
+
"000000", # 0
|
|
12
|
+
"FFFFFF", # 1
|
|
13
|
+
"FF0000", # 2
|
|
14
|
+
"00FF00", # 3
|
|
15
|
+
"0000FF", # 4
|
|
16
|
+
"FFFF00", # 5
|
|
17
|
+
"FF00FF", # 6
|
|
18
|
+
"00FFFF", # 7
|
|
19
|
+
"000000", # 8: Black
|
|
20
|
+
"FFFFFF", # 9: White
|
|
21
|
+
"FF0000", # 10: Red
|
|
22
|
+
"00FF00", # 11: Green
|
|
23
|
+
"0000FF", # 12: Blue
|
|
24
|
+
"FFFF00", # 13: Yellow
|
|
25
|
+
"FF00FF", # 14: Magenta
|
|
26
|
+
"00FFFF", # 15: Cyan
|
|
27
|
+
"800000", # 16: Brown / Dark Red
|
|
28
|
+
"008000", # 17: Olive / Dark Green
|
|
29
|
+
"000080", # 18: Navy / Dark Blue
|
|
30
|
+
"808000", # 19: Dark Yellow
|
|
31
|
+
"800080", # 20: Purple
|
|
32
|
+
"008080", # 21: Teal
|
|
33
|
+
"C0C0C0", # 22: Silver / Light Gray
|
|
34
|
+
"808080", # 23: Gray
|
|
35
|
+
"9999FF", # 24
|
|
36
|
+
"993366", # 25
|
|
37
|
+
"FFFFCC", # 26
|
|
38
|
+
"CCFFFF", # 27
|
|
39
|
+
"660066", # 28
|
|
40
|
+
"FF8080", # 29
|
|
41
|
+
"0066CC", # 30
|
|
42
|
+
"CCCCFF", # 31
|
|
43
|
+
"000080", # 32
|
|
44
|
+
"FF00FF", # 33
|
|
45
|
+
"FFFF00", # 34
|
|
46
|
+
"00FFFF", # 35
|
|
47
|
+
"800080", # 36
|
|
48
|
+
"800000", # 37
|
|
49
|
+
"008080", # 38
|
|
50
|
+
"0000FF", # 39
|
|
51
|
+
"00CCFF", # 40
|
|
52
|
+
"CCFFFF", # 41
|
|
53
|
+
"CCFFCC", # 42
|
|
54
|
+
"FFFFC0", # 43
|
|
55
|
+
"CCE5FF", # 44
|
|
56
|
+
"99CCFF", # 45
|
|
57
|
+
"FF99CC", # 46
|
|
58
|
+
"CC99FF", # 47
|
|
59
|
+
"FFCC99", # 48
|
|
60
|
+
"3366FF", # 49
|
|
61
|
+
"33CCCC", # 50
|
|
62
|
+
"99CC00", # 51
|
|
63
|
+
"FFCC00", # 52
|
|
64
|
+
"FF9900", # 53
|
|
65
|
+
"FF6600", # 54
|
|
66
|
+
"666699", # 55
|
|
67
|
+
"969696", # 56
|
|
68
|
+
"003366", # 57
|
|
69
|
+
"339966", # 58
|
|
70
|
+
"003300", # 59
|
|
71
|
+
"333300", # 60
|
|
72
|
+
"993300", # 61
|
|
73
|
+
"993366", # 62
|
|
74
|
+
"333333" # 63
|
|
75
|
+
].freeze
|
|
76
|
+
|
|
77
|
+
# Resolves a palette index (0..63) to an RRGGBB hex string (or AARRGGBB if alpha: true).
|
|
78
|
+
#
|
|
79
|
+
# @example
|
|
80
|
+
# Xlsxrb::Colors.palette_color(12) #=> "0000FF"
|
|
81
|
+
# Xlsxrb::Colors.palette_color(12, alpha: true) #=> "FF0000FF"
|
|
82
|
+
#
|
|
83
|
+
# @param index [Object, nil] Palette index (0..63).
|
|
84
|
+
# @param alpha [Boolean] Whether to prefix "FF" alpha channel.
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
# @api public
|
|
87
|
+
#: (untyped index, ?alpha: bool) -> String?
|
|
88
|
+
def self.palette_color(index, alpha: false)
|
|
89
|
+
return nil unless index.is_a?(Integer) && index >= 0 && index < INDEXED_COLORS.size
|
|
90
|
+
|
|
91
|
+
hex = INDEXED_COLORS[index]
|
|
92
|
+
alpha ? "FF#{hex}" : hex
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Converts any supported color representation (palette index 0..63, CSS name, #RGB, #RRGGBB, #AARRGGBB, integer RGB)
|
|
96
|
+
# to a normalized hex string.
|
|
97
|
+
#
|
|
98
|
+
# @example
|
|
99
|
+
# Xlsxrb::Colors.to_hex(12) #=> "0000FF"
|
|
100
|
+
# Xlsxrb::Colors.to_hex(12, alpha: true) #=> "FF0000FF"
|
|
101
|
+
# Xlsxrb::Colors.to_hex(:navy) #=> "000080"
|
|
102
|
+
# Xlsxrb::Colors.to_hex("#FF0000") #=> "FF0000"
|
|
103
|
+
# Xlsxrb::Colors.to_hex(0xFF0000) #=> "FF0000"
|
|
104
|
+
#
|
|
105
|
+
# @param color [Integer, String, Symbol, nil]
|
|
106
|
+
# @param alpha [Boolean] Whether to include the alpha channel (default false -> "RRGGBB").
|
|
107
|
+
# @return [String, nil]
|
|
108
|
+
# @api public
|
|
109
|
+
#: (Integer | String | Symbol | nil color, ?alpha: bool) -> String?
|
|
110
|
+
def self.to_hex(color, alpha: false)
|
|
111
|
+
return nil if color.nil?
|
|
112
|
+
|
|
113
|
+
return palette_color(color, alpha: alpha) if color.is_a?(Integer) && color >= 0 && color < INDEXED_COLORS.size
|
|
114
|
+
|
|
115
|
+
StyleBuilder.normalize_color(color, alpha: alpha)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
data/lib/xlsxrb/elements/cell.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Xlsxrb
|
|
|
16
16
|
#
|
|
17
17
|
# @api public
|
|
18
18
|
class Cell
|
|
19
|
-
attr_reader :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors
|
|
19
|
+
attr_reader :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors, :hyperlink, :comment, :raw_value, :format_code, :date1904
|
|
20
20
|
|
|
21
21
|
# @param row_index [Integer] 0-based row index.
|
|
22
22
|
# @param column_index [Integer] 0-based column index.
|
|
@@ -25,8 +25,13 @@ module Xlsxrb
|
|
|
25
25
|
# @param style_index [Integer, String, nil] Style identifier.
|
|
26
26
|
# @param unmapped_data [Hash] Additional metadata.
|
|
27
27
|
# @param errors [Array<String>, nil] Validation errors.
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
# @param hyperlink [Hash, String, Elements::Hyperlink, nil] Optional hyperlink metadata or URL.
|
|
29
|
+
# @param comment [Hash, String, nil] Optional cell comment or note.
|
|
30
|
+
# @param raw_value [String, nil] Optional unparsed raw string value.
|
|
31
|
+
# @param format_code [String, nil] Optional OpenXML number/date format code.
|
|
32
|
+
# @param date1904 [Boolean] Whether the cell belongs to a 1904 date system workbook.
|
|
33
|
+
#: (row_index: untyped, column_index: untyped, ?value: untyped, ?formula: (Elements::Formula | String)?, ?style_index: (Integer | String)?, ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?, ?hyperlink: (Hash[Symbol, untyped] | String | Elements::Hyperlink)?, ?comment: (Hash[Symbol, untyped] | String)?, ?raw_value: String?, ?format_code: String?, ?date1904: bool) -> void
|
|
34
|
+
def initialize(row_index:, column_index:, value: nil, formula: nil, style_index: nil, unmapped_data: EMPTY_HASH, errors: nil, hyperlink: nil, comment: nil, raw_value: nil, format_code: nil, date1904: false)
|
|
30
35
|
@row_index = row_index
|
|
31
36
|
@column_index = column_index
|
|
32
37
|
@value = value
|
|
@@ -35,9 +40,15 @@ module Xlsxrb
|
|
|
35
40
|
@unmapped_data = unmapped_data || EMPTY_HASH
|
|
36
41
|
computed_errors = errors || self.class.validate(row_index, column_index, value)
|
|
37
42
|
@errors = computed_errors.frozen? ? computed_errors : computed_errors.freeze
|
|
43
|
+
@hyperlink = hyperlink
|
|
44
|
+
@comment = comment
|
|
45
|
+
@raw_value = raw_value
|
|
46
|
+
@format_code = format_code
|
|
47
|
+
@date1904 = date1904 ? true : false
|
|
38
48
|
end
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
|
51
|
+
def self.fast_create(row_index, column_index, value, style_index = nil, formula = nil, raw_value = nil, format_code = nil, date1904 = false)
|
|
41
52
|
inst = allocate
|
|
42
53
|
inst.instance_variable_set(:@row_index, row_index)
|
|
43
54
|
inst.instance_variable_set(:@column_index, column_index)
|
|
@@ -46,8 +57,14 @@ module Xlsxrb
|
|
|
46
57
|
inst.instance_variable_set(:@style_index, style_index)
|
|
47
58
|
inst.instance_variable_set(:@unmapped_data, EMPTY_HASH)
|
|
48
59
|
inst.instance_variable_set(:@errors, EMPTY_ERRORS)
|
|
60
|
+
inst.instance_variable_set(:@hyperlink, nil)
|
|
61
|
+
inst.instance_variable_set(:@comment, nil)
|
|
62
|
+
inst.instance_variable_set(:@raw_value, raw_value)
|
|
63
|
+
inst.instance_variable_set(:@format_code, format_code)
|
|
64
|
+
inst.instance_variable_set(:@date1904, date1904 ? true : false)
|
|
49
65
|
inst
|
|
50
66
|
end
|
|
67
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
|
51
68
|
|
|
52
69
|
def ==(other)
|
|
53
70
|
other.is_a?(Cell) &&
|
|
@@ -57,21 +74,26 @@ module Xlsxrb
|
|
|
57
74
|
formula == other.formula &&
|
|
58
75
|
style_index == other.style_index &&
|
|
59
76
|
unmapped_data == other.unmapped_data &&
|
|
60
|
-
errors == other.errors
|
|
77
|
+
errors == other.errors &&
|
|
78
|
+
hyperlink == other.hyperlink &&
|
|
79
|
+
comment == other.comment &&
|
|
80
|
+
raw_value == other.raw_value &&
|
|
81
|
+
format_code == other.format_code
|
|
61
82
|
end
|
|
62
83
|
alias eql? ==
|
|
63
84
|
|
|
64
85
|
def hash
|
|
65
|
-
[row_index, column_index, value, formula, style_index, unmapped_data, errors].hash
|
|
86
|
+
[row_index, column_index, value, formula, style_index, unmapped_data, errors, hyperlink, comment, raw_value, format_code].hash
|
|
66
87
|
end
|
|
67
88
|
|
|
68
89
|
def deconstruct
|
|
69
|
-
[row_index, column_index, value, formula, style_index, unmapped_data, errors]
|
|
90
|
+
[row_index, column_index, value, formula, style_index, unmapped_data, errors, hyperlink, comment, raw_value, format_code]
|
|
70
91
|
end
|
|
71
92
|
|
|
72
93
|
def deconstruct_keys(keys)
|
|
73
94
|
h = { row_index: row_index, column_index: column_index, value: value, formula: formula,
|
|
74
|
-
style_index: style_index, unmapped_data: unmapped_data, errors: errors
|
|
95
|
+
style_index: style_index, unmapped_data: unmapped_data, errors: errors, hyperlink: hyperlink,
|
|
96
|
+
comment: comment, raw_value: raw_value, format_code: format_code }
|
|
75
97
|
keys ? h.slice(*keys) : h
|
|
76
98
|
end
|
|
77
99
|
|
|
@@ -83,7 +105,12 @@ module Xlsxrb
|
|
|
83
105
|
formula: changes.fetch(:formula, formula),
|
|
84
106
|
style_index: changes.fetch(:style_index, style_index),
|
|
85
107
|
unmapped_data: changes.fetch(:unmapped_data, unmapped_data),
|
|
86
|
-
errors: changes.fetch(:errors, errors)
|
|
108
|
+
errors: changes.fetch(:errors, errors),
|
|
109
|
+
hyperlink: changes.fetch(:hyperlink, hyperlink),
|
|
110
|
+
comment: changes.fetch(:comment, comment),
|
|
111
|
+
raw_value: changes.fetch(:raw_value, raw_value),
|
|
112
|
+
format_code: changes.fetch(:format_code, format_code),
|
|
113
|
+
date1904: changes.fetch(:date1904, @date1904 || false)
|
|
87
114
|
)
|
|
88
115
|
end
|
|
89
116
|
|
|
@@ -104,9 +131,120 @@ module Xlsxrb
|
|
|
104
131
|
"#{self.class.column_letter(column_index)}#{row_index + 1}"
|
|
105
132
|
end
|
|
106
133
|
|
|
134
|
+
# Returns whether the cell contains a formula.
|
|
135
|
+
#
|
|
136
|
+
# @return [Boolean]
|
|
137
|
+
# @api public
|
|
138
|
+
#: () -> bool
|
|
139
|
+
def formula?
|
|
140
|
+
if formula.is_a?(Formula)
|
|
141
|
+
!formula.expression.nil? && !formula.expression.empty?
|
|
142
|
+
else
|
|
143
|
+
!formula.nil? && !formula.to_s.empty?
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Returns the formula expression string without leading '=', or nil.
|
|
148
|
+
#
|
|
149
|
+
# @return [String, nil]
|
|
150
|
+
# @api public
|
|
151
|
+
#: () -> String?
|
|
152
|
+
def formula_expression
|
|
153
|
+
expr = formula.is_a?(Formula) ? formula.expression : formula
|
|
154
|
+
return nil if expr.nil?
|
|
155
|
+
|
|
156
|
+
str = expr.to_s
|
|
157
|
+
str.empty? ? nil : str
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Returns whether the cell contains a hyperlink.
|
|
161
|
+
#
|
|
162
|
+
# @return [Boolean]
|
|
163
|
+
# @api public
|
|
164
|
+
#: () -> bool
|
|
165
|
+
def link?
|
|
166
|
+
case hyperlink
|
|
167
|
+
when nil then false
|
|
168
|
+
when Hash, String then !hyperlink.empty?
|
|
169
|
+
else true
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
alias hyperlink? link?
|
|
173
|
+
|
|
174
|
+
# Returns the hyperlink target URL or location string, or nil.
|
|
175
|
+
#
|
|
176
|
+
# @return [String, nil]
|
|
177
|
+
# @api public
|
|
178
|
+
#: () -> String?
|
|
179
|
+
def url
|
|
180
|
+
case hyperlink
|
|
181
|
+
when Hash
|
|
182
|
+
u = hyperlink[:url] || hyperlink[:location]
|
|
183
|
+
u&.to_s
|
|
184
|
+
when String
|
|
185
|
+
hyperlink.empty? ? nil : hyperlink
|
|
186
|
+
when Elements::Hyperlink
|
|
187
|
+
(hyperlink.url || hyperlink.location)&.to_s
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Returns the hyperlink tooltip (ScreenTip) text, or nil.
|
|
192
|
+
#
|
|
193
|
+
# @return [String, nil]
|
|
194
|
+
# @api public
|
|
195
|
+
#: () -> String?
|
|
196
|
+
def tooltip
|
|
197
|
+
case hyperlink
|
|
198
|
+
when Hash
|
|
199
|
+
hyperlink[:tooltip]&.to_s
|
|
200
|
+
when Elements::Hyperlink
|
|
201
|
+
hyperlink.tooltip&.to_s
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Returns whether the cell contains a comment or note.
|
|
206
|
+
#
|
|
207
|
+
# @return [Boolean]
|
|
208
|
+
# @api public
|
|
209
|
+
#: () -> bool
|
|
210
|
+
def comment?
|
|
211
|
+
case comment
|
|
212
|
+
when nil then false
|
|
213
|
+
when Hash, String then !comment.empty?
|
|
214
|
+
else true
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Returns the plain text of the cell comment or note, or nil.
|
|
219
|
+
#
|
|
220
|
+
# @return [String, nil]
|
|
221
|
+
# @api public
|
|
222
|
+
#: () -> String?
|
|
223
|
+
def comment_text
|
|
224
|
+
case comment
|
|
225
|
+
when Hash
|
|
226
|
+
txt = comment[:text]
|
|
227
|
+
txt&.to_s
|
|
228
|
+
when String
|
|
229
|
+
comment.empty? ? nil : comment
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Returns the formatted string representation of the cell value according to its format code.
|
|
234
|
+
#
|
|
235
|
+
# @param custom_format_code [String, nil] Optional format code override.
|
|
236
|
+
# @return [String, nil]
|
|
237
|
+
# @api public
|
|
238
|
+
#: (?String? custom_format_code) -> String?
|
|
239
|
+
def formatted_value(custom_format_code = nil)
|
|
240
|
+
return nil if value.nil?
|
|
241
|
+
|
|
242
|
+
NumberFormatter.format(value, custom_format_code || format_code)
|
|
243
|
+
end
|
|
244
|
+
|
|
107
245
|
# Access cell attributes by Symbol key.
|
|
108
246
|
#
|
|
109
|
-
# @param key [Symbol] Attribute key (:value, :formula, :style_index, :ref, :column_index, :row_index, :type).
|
|
247
|
+
# @param key [Symbol] Attribute key (:value, :formula, :style_index, :ref, :column_index, :row_index, :type, :raw_value, :format_code, :formatted_value).
|
|
110
248
|
# @return [Object, nil]
|
|
111
249
|
# @api public
|
|
112
250
|
#: (Symbol key) -> untyped
|
|
@@ -119,6 +257,17 @@ module Xlsxrb
|
|
|
119
257
|
when :ref then ref
|
|
120
258
|
when :column_index then column_index
|
|
121
259
|
when :row_index then row_index
|
|
260
|
+
when :hyperlink then hyperlink
|
|
261
|
+
when :url then url
|
|
262
|
+
when :tooltip then tooltip
|
|
263
|
+
when :comment then comment
|
|
264
|
+
when :raw_value then raw_value
|
|
265
|
+
when :format_code then format_code
|
|
266
|
+
when :formatted_value then formatted_value
|
|
267
|
+
when :format_type then format_type
|
|
268
|
+
when :date_format then date_format?
|
|
269
|
+
when :time_format then time_format?
|
|
270
|
+
when :date1904 then date1904?
|
|
122
271
|
when :type
|
|
123
272
|
case value
|
|
124
273
|
when String then "s"
|
|
@@ -127,6 +276,42 @@ module Xlsxrb
|
|
|
127
276
|
end
|
|
128
277
|
end
|
|
129
278
|
|
|
279
|
+
# Returns the classified format category for this cell (:date, :datetime, :time, :number, :text, :general, or nil).
|
|
280
|
+
#
|
|
281
|
+
# @return [Symbol, nil]
|
|
282
|
+
# @api public
|
|
283
|
+
#: () -> Symbol?
|
|
284
|
+
def format_type
|
|
285
|
+
format_code ? NumberFormatter.format_type(format_code) : nil
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Returns whether the cell has a date, datetime, or time format.
|
|
289
|
+
#
|
|
290
|
+
# @return [Boolean]
|
|
291
|
+
# @api public
|
|
292
|
+
#: () -> bool
|
|
293
|
+
def date_format?
|
|
294
|
+
format_code ? NumberFormatter.date_format?(format_code) : false
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Returns whether the cell has a time-only format.
|
|
298
|
+
#
|
|
299
|
+
# @return [Boolean]
|
|
300
|
+
# @api public
|
|
301
|
+
#: () -> bool
|
|
302
|
+
def time_format?
|
|
303
|
+
format_code ? NumberFormatter.time_format?(format_code) : false
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Returns whether the cell's workbook uses the 1904 date system.
|
|
307
|
+
#
|
|
308
|
+
# @return [Boolean]
|
|
309
|
+
# @api public
|
|
310
|
+
#: () -> bool
|
|
311
|
+
def date1904?
|
|
312
|
+
@date1904 ? true : false
|
|
313
|
+
end
|
|
314
|
+
|
|
130
315
|
# Returns the cell value.
|
|
131
316
|
#
|
|
132
317
|
# @return [Object, nil]
|
|
@@ -165,14 +350,16 @@ module Xlsxrb
|
|
|
165
350
|
|
|
166
351
|
# Converts the cell value (numeric serial date or date string) to Date.
|
|
167
352
|
#
|
|
353
|
+
# @param date1904 [Boolean, nil] Whether to use the 1904 date system (defaults to cell's date1904 setting).
|
|
168
354
|
# @return [Date, nil]
|
|
169
355
|
# @api public
|
|
170
|
-
#: () -> Date?
|
|
171
|
-
def to_date
|
|
356
|
+
#: (?date1904: bool?) -> Date?
|
|
357
|
+
def to_date(date1904: nil)
|
|
172
358
|
return value if value.is_a?(Date)
|
|
173
359
|
|
|
360
|
+
d1904 = date1904.nil? ? date1904? : date1904
|
|
174
361
|
if value.is_a?(Numeric)
|
|
175
|
-
Ooxml::Utils.serial_to_date(value)
|
|
362
|
+
Ooxml::Utils.serial_to_date(value, date1904: d1904)
|
|
176
363
|
else
|
|
177
364
|
begin
|
|
178
365
|
Date.parse(value.to_s)
|
|
@@ -184,14 +371,16 @@ module Xlsxrb
|
|
|
184
371
|
|
|
185
372
|
# Converts the cell value (numeric serial datetime or datetime string) to Time.
|
|
186
373
|
#
|
|
374
|
+
# @param date1904 [Boolean, nil] Whether to use the 1904 date system (defaults to cell's date1904 setting).
|
|
187
375
|
# @return [Time, nil]
|
|
188
376
|
# @api public
|
|
189
|
-
#: () -> Time?
|
|
190
|
-
def to_time
|
|
377
|
+
#: (?date1904: bool?) -> Time?
|
|
378
|
+
def to_time(date1904: nil)
|
|
191
379
|
return value if value.is_a?(Time)
|
|
192
380
|
|
|
381
|
+
d1904 = date1904.nil? ? date1904? : date1904
|
|
193
382
|
if value.is_a?(Numeric)
|
|
194
|
-
Ooxml::Utils.serial_to_datetime(value)
|
|
383
|
+
Ooxml::Utils.serial_to_datetime(value, date1904: d1904)
|
|
195
384
|
else
|
|
196
385
|
begin
|
|
197
386
|
Time.parse(value.to_s)
|
|
@@ -12,21 +12,23 @@ module Xlsxrb
|
|
|
12
12
|
#
|
|
13
13
|
# @api public
|
|
14
14
|
# rubocop:disable Style/DataInheritance -- Required as class syntax for mutant subject matcher
|
|
15
|
-
class Column < Data.define(:index, :width, :hidden, :custom_width, :outline_level, :unmapped_data, :errors)
|
|
15
|
+
class Column < Data.define(:index, :width, :hidden, :custom_width, :outline_level, :style_index, :unmapped_data, :errors)
|
|
16
16
|
# rubocop:enable Style/DataInheritance
|
|
17
17
|
# @param index [Integer] 0-based column index.
|
|
18
18
|
# @param width [Float, Integer, nil] Column width in characters.
|
|
19
19
|
# @param hidden [Boolean] Whether the column is hidden.
|
|
20
20
|
# @param custom_width [Boolean] Whether custom width flag is set.
|
|
21
21
|
# @param outline_level [Integer, nil] Grouping/outline level.
|
|
22
|
+
# @param style_index [Integer, String, nil] Optional style identifier.
|
|
22
23
|
# @param unmapped_data [Hash] Additional metadata.
|
|
23
24
|
# @param errors [Array<String>, nil] Validation errors.
|
|
24
|
-
#: (index: Integer, ?width: Float | Integer | nil, ?hidden: bool, ?custom_width: bool, ?outline_level: Integer | nil, ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void
|
|
25
|
+
#: (index: Integer, ?width: Float | Integer | nil, ?hidden: bool, ?custom_width: bool, ?outline_level: Integer | nil, ?style_index: (Integer | String)?, ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void
|
|
25
26
|
def initialize(index:, width: nil, hidden: false, custom_width: false, outline_level: nil,
|
|
26
|
-
unmapped_data: {}, errors: nil)
|
|
27
|
+
style_index: nil, unmapped_data: {}, errors: nil)
|
|
28
|
+
style_idx = style_index || unmapped_data[:style_index] || unmapped_data[:style]
|
|
27
29
|
computed_errors = errors || self.class.validate(index)
|
|
28
30
|
super(index: index, width: width, hidden: hidden, custom_width: custom_width,
|
|
29
|
-
outline_level: outline_level, unmapped_data: unmapped_data,
|
|
31
|
+
outline_level: outline_level, style_index: style_idx, unmapped_data: unmapped_data,
|
|
30
32
|
errors: computed_errors.freeze)
|
|
31
33
|
end
|
|
32
34
|
|
|
@@ -76,6 +76,38 @@ module Xlsxrb
|
|
|
76
76
|
rows.max_by(&:index)
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
+
# Returns the 1-based index of the first column containing data, or nil.
|
|
80
|
+
#
|
|
81
|
+
# @return [Integer, nil]
|
|
82
|
+
# @api public
|
|
83
|
+
#: () -> Integer?
|
|
84
|
+
def first_column
|
|
85
|
+
min_c = nil
|
|
86
|
+
rows.each do |r|
|
|
87
|
+
r.cells.each do |c|
|
|
88
|
+
min_c = c.column_index if min_c.nil? || c.column_index < min_c
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
min_c ? min_c + 1 : nil
|
|
92
|
+
end
|
|
93
|
+
alias first_col first_column
|
|
94
|
+
|
|
95
|
+
# Returns the 1-based index of the last column containing data, or nil.
|
|
96
|
+
#
|
|
97
|
+
# @return [Integer, nil]
|
|
98
|
+
# @api public
|
|
99
|
+
#: () -> Integer?
|
|
100
|
+
def last_column
|
|
101
|
+
max_c = nil
|
|
102
|
+
rows.each do |r|
|
|
103
|
+
r.cells.each do |c|
|
|
104
|
+
max_c = c.column_index if max_c.nil? || c.column_index > max_c
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
max_c ? max_c + 1 : nil
|
|
108
|
+
end
|
|
109
|
+
alias last_col last_column
|
|
110
|
+
|
|
79
111
|
# Returns the raw cell value at the given Excel-style reference (e.g. "A1").
|
|
80
112
|
#
|
|
81
113
|
# @example
|