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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/README.md +2 -0
  4. data/lib/xlsxrb/colors.rb +118 -0
  5. data/lib/xlsxrb/elements/cell.rb +205 -16
  6. data/lib/xlsxrb/elements/column.rb +6 -4
  7. data/lib/xlsxrb/elements/coordinate_access.rb +32 -0
  8. data/lib/xlsxrb/elements/image.rb +128 -0
  9. data/lib/xlsxrb/elements/row.rb +206 -9
  10. data/lib/xlsxrb/elements/styles.rb +157 -0
  11. data/lib/xlsxrb/elements/types.rb +95 -1
  12. data/lib/xlsxrb/elements/workbook.rb +85 -4
  13. data/lib/xlsxrb/elements/worksheet.rb +424 -29
  14. data/lib/xlsxrb/elements.rb +2 -0
  15. data/lib/xlsxrb/number_formatter.rb +429 -0
  16. data/lib/xlsxrb/ooxml/cfb.rb +1 -1
  17. data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +7 -5
  18. data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +11 -4
  19. data/lib/xlsxrb/ooxml/reader.rb +12 -14
  20. data/lib/xlsxrb/ooxml/shared_strings_parser.rb +7 -1
  21. data/lib/xlsxrb/ooxml/styles_parser.rb +39 -9
  22. data/lib/xlsxrb/ooxml/utils.rb +34 -18
  23. data/lib/xlsxrb/ooxml/workbook_parser.rb +53 -15
  24. data/lib/xlsxrb/ooxml/workbook_writer.rb +65 -14
  25. data/lib/xlsxrb/ooxml/worksheet_parser.rb +319 -79
  26. data/lib/xlsxrb/ooxml/worksheet_writer.rb +206 -61
  27. data/lib/xlsxrb/ooxml/writer/features_xml.rb +4 -2
  28. data/lib/xlsxrb/ooxml/writer.rb +14 -0
  29. data/lib/xlsxrb/ooxml/zip_reader.rb +109 -25
  30. data/lib/xlsxrb/stream_row.rb +243 -16
  31. data/lib/xlsxrb/stream_sheet.rb +414 -15
  32. data/lib/xlsxrb/stream_writer.rb +213 -17
  33. data/lib/xlsxrb/style_builder.rb +308 -22
  34. data/lib/xlsxrb/utils.rb +158 -0
  35. data/lib/xlsxrb/version.rb +1 -1
  36. data/lib/xlsxrb/workbook_builder.rb +73 -3
  37. data/lib/xlsxrb/worksheet_builder.rb +227 -16
  38. data/lib/xlsxrb.rb +578 -79
  39. data/sig/generated/xlsxrb/colors.rbs +40 -0
  40. data/sig/generated/xlsxrb/elements/cell.rbs +113 -8
  41. data/sig/generated/xlsxrb/elements/column.rbs +3 -2
  42. data/sig/generated/xlsxrb/elements/coordinate_access.rbs +18 -0
  43. data/sig/generated/xlsxrb/elements/image.rbs +82 -0
  44. data/sig/generated/xlsxrb/elements/row.rbs +83 -4
  45. data/sig/generated/xlsxrb/elements/styles.rbs +79 -0
  46. data/sig/generated/xlsxrb/elements/types.rbs +43 -0
  47. data/sig/generated/xlsxrb/elements/workbook.rbs +51 -2
  48. data/sig/generated/xlsxrb/elements/worksheet.rbs +231 -18
  49. data/sig/generated/xlsxrb/number_formatter.rbs +132 -0
  50. data/sig/generated/xlsxrb/ooxml/reader.rbs +6 -0
  51. data/sig/generated/xlsxrb/ooxml/shared_strings_parser.rbs +2 -0
  52. data/sig/generated/xlsxrb/ooxml/styles_parser.rbs +5 -2
  53. data/sig/generated/xlsxrb/ooxml/utils.rbs +17 -8
  54. data/sig/generated/xlsxrb/ooxml/workbook_parser.rbs +9 -3
  55. data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +28 -6
  56. data/sig/generated/xlsxrb/ooxml/worksheet_writer.rbs +3 -1
  57. data/sig/generated/xlsxrb/ooxml/writer.rbs +2 -0
  58. data/sig/generated/xlsxrb/ooxml/zip_reader.rbs +10 -0
  59. data/sig/generated/xlsxrb/stream_row.rbs +100 -6
  60. data/sig/generated/xlsxrb/stream_sheet.rbs +247 -13
  61. data/sig/generated/xlsxrb/stream_writer.rbs +120 -14
  62. data/sig/generated/xlsxrb/style_builder.rbs +55 -18
  63. data/sig/generated/xlsxrb/utils.rbs +119 -0
  64. data/sig/generated/xlsxrb/workbook_builder.rbs +26 -0
  65. data/sig/generated/xlsxrb/worksheet_builder.rbs +107 -11
  66. data/sig/generated/xlsxrb.rbs +186 -27
  67. metadata +11 -1
@@ -13,7 +13,7 @@ module Xlsxrb
13
13
  #
14
14
  # @api public
15
15
  # rubocop:disable Style/DataInheritance -- Required as class syntax for mutant subject matcher
16
- class Workbook < Data.define(:sheets, :shared_strings, :styles, :unmapped_data, :errors)
16
+ class Workbook < Data.define(:sheets, :shared_strings, :styles, :unmapped_data, :errors, :defined_names)
17
17
  # rubocop:enable Style/DataInheritance
18
18
  [Enumerable].each { |m| include m }
19
19
 
@@ -22,11 +22,19 @@ module Xlsxrb
22
22
  # @param styles [Hash] Styles definition.
23
23
  # @param unmapped_data [Hash] Additional metadata for round-tripping.
24
24
  # @param errors [Array<String>, nil] Validation errors.
25
- #: (?sheets: Array[Elements::Worksheet | StreamSheet], ?shared_strings: Array[String], ?styles: Hash[untyped, untyped], ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void
26
- def initialize(sheets: [], shared_strings: [], styles: {}, unmapped_data: {}, errors: nil)
25
+ # @param defined_names [Array<Hash>, nil] Defined names list.
26
+ # @param date1904 [Boolean] Whether the workbook uses the 1904 date system.
27
+ #: (?sheets: Array[Elements::Worksheet | StreamSheet], ?shared_strings: Array[String], ?styles: Hash[untyped, untyped], ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?, ?defined_names: Array[Hash[Symbol, untyped]]?, ?date1904: bool) -> void
28
+ def initialize(sheets: [], shared_strings: [], styles: {}, unmapped_data: {}, errors: nil, defined_names: nil, date1904: false)
29
+ dns = defined_names || unmapped_data[:defined_names] || unmapped_data.dig(:facade, :defined_names) || []
27
30
  computed_errors = errors || self.class.validate(sheets)
31
+ unmapped = unmapped_data
32
+ if date1904 && !unmapped.dig(:workbook_properties, :date1904) && !unmapped.dig(:facade, :workbook_properties, :date1904)
33
+ unmapped = unmapped.dup
34
+ unmapped[:workbook_properties] = (unmapped[:workbook_properties] || {}).merge(date1904: true)
35
+ end
28
36
  super(sheets: sheets.freeze, shared_strings: shared_strings.freeze, styles: styles,
29
- unmapped_data: unmapped_data, errors: computed_errors.freeze)
37
+ unmapped_data: unmapped, errors: computed_errors.freeze, defined_names: dns.freeze)
30
38
  end
31
39
 
32
40
  # Iterate over worksheets.
@@ -54,6 +62,41 @@ module Xlsxrb
54
62
  errors.empty?
55
63
  end
56
64
 
65
+ # Returns whether the workbook uses the 1904 date system.
66
+ #
67
+ # @return [Boolean]
68
+ # @api public
69
+ #: () -> bool
70
+ def date1904?
71
+ props = unmapped_data[:workbook_properties] || unmapped_data.dig(:facade, :workbook_properties)
72
+ props&.[](:date1904) ? true : false
73
+ end
74
+
75
+ # Returns the defined name matching name (and optionally sheet), or nil.
76
+ #
77
+ # @example
78
+ # wb.defined_name("SalesTotal")
79
+ # wb.defined_name("Print_Area", sheet: "Sheet1")
80
+ #
81
+ # @param name [String] The defined name.
82
+ # @param sheet [String, Integer, nil] Optional sheet name or 0-based index.
83
+ # @return [Hash[Symbol, untyped], nil]
84
+ # @api public
85
+ #: (String name, ?sheet: (String | Integer)?) -> Hash[Symbol, untyped]?
86
+ def defined_name(name, sheet: nil)
87
+ sheet_idx = case sheet
88
+ when Integer then sheet
89
+ when String then sheets.find_index { |s| s.name == sheet }
90
+ end
91
+
92
+ if sheet_idx
93
+ defined_names.find { |dn| dn[:name] == name && dn[:local_sheet_id] == sheet_idx }
94
+ else
95
+ defined_names.find { |dn| dn[:name] == name && dn[:local_sheet_id].nil? } ||
96
+ defined_names.find { |dn| dn[:name] == name }
97
+ end
98
+ end
99
+
57
100
  # Returns the worksheet at the given 0-based index or by name.
58
101
  #
59
102
  # @example
@@ -74,6 +117,44 @@ module Xlsxrb
74
117
  end
75
118
  alias [] sheet
76
119
 
120
+ # Returns the formatted string representation of a cell's value in the specified sheet.
121
+ #
122
+ # @param sheet_identifier [Integer, String, untyped] 0-based index or sheet name.
123
+ # @param ref_or_row [String, Symbol, Integer] Cell reference (e.g. "A1") or 0-based row index.
124
+ # @param col [Integer, nil] Optional 0-based column index.
125
+ # @return [String, nil]
126
+ # @api public
127
+ #: (Integer | String | untyped sheet_identifier, String | Symbol | Integer ref_or_row, ?Integer? col) -> String?
128
+ def formatted_value(sheet_identifier, ref_or_row, col = nil)
129
+ target_sheet = sheet(sheet_identifier)
130
+ target_sheet&.formatted_value(ref_or_row, col)
131
+ end
132
+
133
+ # Returns all embedded images across all worksheets.
134
+ #
135
+ # @return [Array<Elements::Image>]
136
+ # @api public
137
+ #: () -> Array[Elements::Image]
138
+ def images
139
+ sheets.flat_map(&:images)
140
+ end
141
+
142
+ # Returns all images anchored at a specific cell in the given worksheet.
143
+ #
144
+ # @param sheet_identifier [Integer, String, untyped] Sheet index or sheet name.
145
+ # @param ref_or_row [String, Symbol, Integer] Cell reference (e.g. "A1") or 0-based row index.
146
+ # @param col [Integer, nil] Optional 0-based column index.
147
+ # @return [Array<Elements::Image>]
148
+ # @api public
149
+ #: (Integer | String | untyped sheet_identifier, String | Symbol | Integer ref_or_row, ?Integer? col) -> Array[Elements::Image]
150
+ def images_at(sheet_identifier, ref_or_row, col = nil)
151
+ ident = sheet_identifier.is_a?(Symbol) ? sheet_identifier.to_s : sheet_identifier
152
+ target_sheet = sheet(ident)
153
+ return [] unless target_sheet
154
+
155
+ target_sheet.images_at(ref_or_row, col)
156
+ end
157
+
77
158
  # Loads all sheets into memory, returning an Elements::Workbook where every
78
159
  # worksheet is a fully-parsed Elements::Worksheet supporting coordinate random access.
79
160
  #