xlsxrb 0.1.16 → 0.1.17
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 +64 -0
- data/README.md +2 -2
- data/lib/xlsxrb/chart_builder.rb +41 -2
- data/lib/xlsxrb/dsl_helpers.rb +522 -6
- data/lib/xlsxrb/elements/cell.rb +34 -9
- data/lib/xlsxrb/elements/column.rb +2 -2
- data/lib/xlsxrb/elements/types.rb +1 -0
- data/lib/xlsxrb/elements/workbook.rb +48 -0
- data/lib/xlsxrb/elements/worksheet.rb +158 -11
- data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +22 -1
- data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +187 -24
- data/lib/xlsxrb/ooxml/reader/listeners/feature_listeners.rb +108 -1
- data/lib/xlsxrb/ooxml/reader/listeners/style_listeners.rb +16 -11
- data/lib/xlsxrb/ooxml/reader.rb +88 -0
- data/lib/xlsxrb/ooxml/styles_parser.rb +19 -11
- data/lib/xlsxrb/ooxml/workbook_parser.rb +18 -3
- data/lib/xlsxrb/ooxml/workbook_writer.rb +266 -46
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +18 -4
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +289 -88
- data/lib/xlsxrb/ooxml/writer/drawing_xml.rb +579 -441
- data/lib/xlsxrb/ooxml/writer/features_xml.rb +26 -9
- data/lib/xlsxrb/ooxml/writer/styles_xml.rb +23 -9
- data/lib/xlsxrb/ooxml/writer.rb +268 -31
- data/lib/xlsxrb/ooxml/zip_writer.rb +15 -5
- data/lib/xlsxrb/stream_sheet.rb +157 -3
- data/lib/xlsxrb/stream_writer.rb +946 -74
- data/lib/xlsxrb/style_builder.rb +59 -6
- data/lib/xlsxrb/utils.rb +65 -0
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb/workbook_builder.rb +197 -14
- data/lib/xlsxrb/worksheet_builder.rb +1137 -44
- data/lib/xlsxrb.rb +302 -47
- data/sig/generated/xlsxrb/chart_builder.rbs +31 -3
- data/sig/generated/xlsxrb/dsl_helpers.rbs +119 -4
- data/sig/generated/xlsxrb/elements/cell.rbs +20 -3
- data/sig/generated/xlsxrb/elements/column.rbs +3 -3
- data/sig/generated/xlsxrb/elements/types.rbs +2 -0
- data/sig/generated/xlsxrb/elements/workbook.rbs +37 -0
- data/sig/generated/xlsxrb/elements/worksheet.rbs +82 -2
- data/sig/generated/xlsxrb/ooxml/reader/listeners/core_listeners.rbs +2 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/drawing_listeners.rbs +74 -2
- data/sig/generated/xlsxrb/ooxml/reader/listeners/feature_listeners.rbs +36 -0
- data/sig/generated/xlsxrb/ooxml/reader/listeners/style_listeners.rbs +3 -0
- data/sig/generated/xlsxrb/ooxml/reader.rbs +17 -0
- data/sig/generated/xlsxrb/ooxml/styles_parser.rbs +3 -0
- data/sig/generated/xlsxrb/ooxml/workbook_parser.rbs +8 -0
- data/sig/generated/xlsxrb/ooxml/workbook_writer.rbs +8 -4
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +1 -1
- data/sig/generated/xlsxrb/ooxml/worksheet_writer.rbs +12 -1
- data/sig/generated/xlsxrb/ooxml/writer/drawing_xml.rbs +16 -0
- data/sig/generated/xlsxrb/ooxml/writer.rbs +42 -8
- data/sig/generated/xlsxrb/ooxml/zip_writer.rbs +8 -2
- data/sig/generated/xlsxrb/stream_sheet.rbs +101 -1
- data/sig/generated/xlsxrb/stream_writer.rbs +592 -23
- data/sig/generated/xlsxrb/style_builder.rbs +24 -6
- data/sig/generated/xlsxrb/utils.rbs +20 -0
- data/sig/generated/xlsxrb/workbook_builder.rbs +87 -5
- data/sig/generated/xlsxrb/worksheet_builder.rbs +554 -10
- data/sig/generated/xlsxrb.rbs +77 -16
- metadata +1 -1
|
@@ -80,6 +80,15 @@ module Xlsxrb
|
|
|
80
80
|
workbook_properties[:date1904] ? true : false
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# Returns the internal VBA or application code name of the workbook, or nil if not specified.
|
|
84
|
+
#
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
# @api public
|
|
87
|
+
#: () -> String?
|
|
88
|
+
def code_name
|
|
89
|
+
workbook_properties[:code_name]
|
|
90
|
+
end
|
|
91
|
+
|
|
83
92
|
# Returns the 0-based active worksheet tab index from workbookView, or nil if not set.
|
|
84
93
|
#
|
|
85
94
|
# @return [Integer, nil]
|
|
@@ -89,6 +98,45 @@ module Xlsxrb
|
|
|
89
98
|
workbook_properties[:active_tab]
|
|
90
99
|
end
|
|
91
100
|
|
|
101
|
+
# Returns the active worksheet in the workbook, or the first worksheet if not set.
|
|
102
|
+
#
|
|
103
|
+
# @return [Elements::Worksheet, StreamSheet, nil]
|
|
104
|
+
# @api public
|
|
105
|
+
#: () -> (Elements::Worksheet | StreamSheet)?
|
|
106
|
+
def active_sheet
|
|
107
|
+
idx = active_tab
|
|
108
|
+
idx ? sheets[idx] : sheets.first
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Returns the index of the first sheet tab visible in the sheet tab scroll area.
|
|
112
|
+
#
|
|
113
|
+
# @return [Integer, nil]
|
|
114
|
+
# @api public
|
|
115
|
+
#: () -> Integer?
|
|
116
|
+
def first_sheet
|
|
117
|
+
workbook_properties[:first_sheet]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Returns whether sheet tabs are displayed in the workbook window.
|
|
121
|
+
#
|
|
122
|
+
# @return [Boolean]
|
|
123
|
+
# @api public
|
|
124
|
+
#: () -> bool
|
|
125
|
+
def show_sheet_tabs?
|
|
126
|
+
val = workbook_properties[:show_sheet_tabs]
|
|
127
|
+
val != false
|
|
128
|
+
end
|
|
129
|
+
alias show_sheet_tabs show_sheet_tabs?
|
|
130
|
+
|
|
131
|
+
# Returns the ratio between the sheet tabs bar and the horizontal scroll bar (0-1000).
|
|
132
|
+
#
|
|
133
|
+
# @return [Integer, nil]
|
|
134
|
+
# @api public
|
|
135
|
+
#: () -> Integer?
|
|
136
|
+
def tab_ratio
|
|
137
|
+
workbook_properties[:tab_ratio]
|
|
138
|
+
end
|
|
139
|
+
|
|
92
140
|
# Returns whether Excel is instructed to perform a full recalculation when loading the workbook.
|
|
93
141
|
#
|
|
94
142
|
# @return [Boolean]
|
|
@@ -17,9 +17,13 @@ module Xlsxrb
|
|
|
17
17
|
class Worksheet
|
|
18
18
|
[Enumerable, CoordinateAccess].each { |m| include m }
|
|
19
19
|
|
|
20
|
-
attr_reader :name, :rows, :columns, :charts, :conditional_formatting, :data_validations, :unmapped_data, :errors, :state, :hyperlinks, :comments, :images, :styles, :date1904, :print_area, :print_titles, :sparkline_groups, :merged_cells, :auto_filter, :tables, :shapes, :freeze_pane, :page_setup, :page_margins, :header_footer, :print_options, :sheet_protection, :sheet_view, :sheet_properties, :sheet_format, :row_breaks, :col_breaks, :protected_ranges, :cell_watches, :selection
|
|
20
|
+
attr_reader :name, :rows, :columns, :charts, :conditional_formatting, :data_validations, :unmapped_data, :errors, :state, :hyperlinks, :comments, :images, :styles, :date1904, :print_area, :print_titles, :sparkline_groups, :merged_cells, :auto_filter, :tables, :shapes, :freeze_pane, :page_setup, :page_margins, :header_footer, :print_options, :sheet_protection, :sheet_view, :sheet_properties, :sheet_format, :row_breaks, :col_breaks, :protected_ranges, :cell_watches, :ignored_errors, :phonetic_properties, :selection, :sheet_calc_pr, :background_image, :threaded_comments
|
|
21
21
|
attr_writer :dimension
|
|
22
22
|
alias conditional_formats conditional_formatting
|
|
23
|
+
alias phonetic_pr phonetic_properties
|
|
24
|
+
alias calc_pr sheet_calc_pr
|
|
25
|
+
alias background_picture background_image
|
|
26
|
+
alias picture background_image
|
|
23
27
|
|
|
24
28
|
# @param name [String] The worksheet name (max 31 characters).
|
|
25
29
|
# @param rows [Array<Elements::Row>] Rows in the sheet.
|
|
@@ -59,9 +63,14 @@ module Xlsxrb
|
|
|
59
63
|
# @param col_breaks [Array<Integer | Hash>] Explicit page column breaks.
|
|
60
64
|
# @param protected_ranges [Array<Hash>] Protected range definitions.
|
|
61
65
|
# @param cell_watches [Array<String>] Watched cell references.
|
|
66
|
+
# @param ignored_errors [Array<Hash>] Ignored error rules.
|
|
67
|
+
# @param phonetic_properties [Hash, nil] Phonetic text properties.
|
|
62
68
|
# @param selection [Hash, Array<Hash>, nil] Active cell and selection settings.
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
# @param sheet_calc_pr [Hash, nil] Worksheet calculation properties.
|
|
70
|
+
# @param background_image [Hash, nil] Worksheet background image specification.
|
|
71
|
+
# @param threaded_comments [Array<Hash>] Threaded comments in the sheet.
|
|
72
|
+
#: (name: String?, ?rows: Array[Elements::Row], ?columns: Array[Elements::Column], ?charts: Array[Hash[Symbol, untyped]], ?conditional_formatting: Array[Hash[Symbol, untyped]]?, ?data_validations: Array[Hash[Symbol, untyped]], ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?, ?conditional_formats: Array[Hash[Symbol, untyped]]?, ?state: Symbol, ?hyperlinks: Hash[String, untyped], ?comments: Array[Hash[Symbol, untyped]], ?images: Array[Elements::Image], ?styles: (Elements::Styles | Hash[untyped, untyped])?, ?date1904: bool, ?dimension: String?, ?trim_empty_rows: bool, ?pad_empty_rows: bool, ?pad_empty_cells: bool, ?print_area: String?, ?print_titles: Hash[Symbol, untyped]?, ?sparkline_groups: Array[Hash[Symbol, untyped]], ?merged_cells: Array[String], ?auto_filter: String?, ?tables: Array[Hash[Symbol, untyped]], ?shapes: Array[Hash[Symbol, untyped]], ?freeze_pane: Hash[Symbol, untyped]?, ?page_setup: Hash[Symbol, untyped], ?page_margins: Hash[Symbol, untyped]?, ?header_footer: Hash[Symbol, untyped], ?print_options: Hash[Symbol, untyped], ?sheet_protection: Hash[Symbol, untyped]?, ?sheet_view: Hash[Symbol, untyped], ?sheet_properties: Hash[Symbol, untyped], ?sheet_format: Hash[Symbol, untyped], ?row_breaks: Array[untyped], ?col_breaks: Array[untyped], ?protected_ranges: Array[Hash[Symbol, untyped]], ?cell_watches: Array[String], ?ignored_errors: Array[Hash[Symbol, untyped]], ?phonetic_properties: Hash[Symbol, untyped]?, ?selection: (Hash[Symbol, untyped] | Array[Hash[Symbol, untyped]])?, ?sheet_calc_pr: Hash[Symbol, untyped]?, ?background_image: Hash[Symbol, untyped]?, ?threaded_comments: Array[Hash[Symbol, untyped]]) -> void
|
|
73
|
+
def initialize(name:, rows: [], columns: [], charts: [], conditional_formatting: nil, data_validations: [], unmapped_data: {}, errors: nil, conditional_formats: nil, state: :visible, hyperlinks: {}, comments: [], images: [], styles: nil, date1904: false, dimension: nil, trim_empty_rows: false, pad_empty_rows: false, pad_empty_cells: false, print_area: nil, print_titles: nil, sparkline_groups: [], merged_cells: [], auto_filter: nil, tables: [], shapes: [], freeze_pane: nil, page_setup: {}, page_margins: nil, header_footer: {}, print_options: {}, sheet_protection: nil, sheet_view: {}, sheet_properties: {}, sheet_format: {}, row_breaks: [], col_breaks: [], protected_ranges: [], cell_watches: [], ignored_errors: [], phonetic_properties: nil, selection: nil, sheet_calc_pr: nil, background_image: nil, threaded_comments: [])
|
|
65
74
|
@name = name
|
|
66
75
|
@rows = (rows || []).freeze
|
|
67
76
|
@columns = (columns || []).freeze
|
|
@@ -85,6 +94,7 @@ module Xlsxrb
|
|
|
85
94
|
@trim_empty_rows = trim_empty_rows ? true : false
|
|
86
95
|
@pad_empty_rows = pad_empty_rows ? true : false
|
|
87
96
|
@pad_empty_cells = pad_empty_cells ? true : false
|
|
97
|
+
@threaded_comments = (threaded_comments || []).freeze
|
|
88
98
|
@merged_cells = (merged_cells || []).freeze
|
|
89
99
|
@auto_filter = auto_filter
|
|
90
100
|
@tables = (tables || []).freeze
|
|
@@ -102,7 +112,11 @@ module Xlsxrb
|
|
|
102
112
|
@col_breaks = (col_breaks || []).freeze
|
|
103
113
|
@protected_ranges = (protected_ranges || unmapped_data[:protected_ranges] || unmapped_data.dig(:facade, :protected_ranges) || []).freeze
|
|
104
114
|
@cell_watches = (cell_watches || unmapped_data[:cell_watches] || unmapped_data.dig(:facade, :cell_watches) || []).freeze
|
|
115
|
+
@ignored_errors = (ignored_errors || unmapped_data[:ignored_errors] || unmapped_data.dig(:facade, :ignored_errors) || []).freeze
|
|
116
|
+
@phonetic_properties = (phonetic_properties || unmapped_data[:phonetic_properties] || unmapped_data.dig(:facade, :phonetic_properties))&.freeze
|
|
105
117
|
@selection = selection&.freeze
|
|
118
|
+
@sheet_calc_pr = (sheet_calc_pr || unmapped_data[:sheet_calc_pr] || unmapped_data.dig(:facade, :sheet_calc_pr) || (@sheet_properties[:full_calc_on_load] ? { full_calc_on_load: true } : nil))&.freeze
|
|
119
|
+
@background_image = (background_image || unmapped_data[:background_image] || unmapped_data.dig(:facade, :background_image))&.freeze
|
|
106
120
|
end
|
|
107
121
|
|
|
108
122
|
# Returns whether trailing empty rows are omitted during iteration.
|
|
@@ -154,6 +168,68 @@ module Xlsxrb
|
|
|
154
168
|
@dimension ||= compute_dimension
|
|
155
169
|
end
|
|
156
170
|
|
|
171
|
+
# Returns the worksheet tab color specification, or nil if not set.
|
|
172
|
+
#
|
|
173
|
+
# @return [String, Hash, nil] RGB hex string (e.g. "FFFF0000") or color hash (e.g. { theme: 3, tint: -0.5 }).
|
|
174
|
+
# @api public
|
|
175
|
+
#: () -> (String | Hash[Symbol, untyped])?
|
|
176
|
+
def tab_color
|
|
177
|
+
props = sheet_properties
|
|
178
|
+
return props[:tab_color] if props[:tab_color]
|
|
179
|
+
return { theme: props[:tab_color_theme], tint: props[:tab_color_tint] } if props[:tab_color_theme]
|
|
180
|
+
return { indexed: props[:tab_color_indexed] } if props[:tab_color_indexed]
|
|
181
|
+
return { auto: true } if props[:tab_color_auto]
|
|
182
|
+
|
|
183
|
+
nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Returns the internal VBA or application code name of the worksheet, or nil if not specified.
|
|
187
|
+
#
|
|
188
|
+
# @return [String, nil]
|
|
189
|
+
# @api public
|
|
190
|
+
#: () -> String?
|
|
191
|
+
def code_name
|
|
192
|
+
sheet_properties[:code_name]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Returns whether fit-to-page is enabled for page setup on this worksheet.
|
|
196
|
+
#
|
|
197
|
+
# @return [Boolean]
|
|
198
|
+
# @api public
|
|
199
|
+
#: () -> bool
|
|
200
|
+
def fit_to_page?
|
|
201
|
+
sheet_properties[:fit_to_page] ? true : false
|
|
202
|
+
end
|
|
203
|
+
alias fit_to_page fit_to_page?
|
|
204
|
+
|
|
205
|
+
# Returns whether full calculation on load is enabled on this worksheet.
|
|
206
|
+
#
|
|
207
|
+
# @return [Boolean]
|
|
208
|
+
# @api public
|
|
209
|
+
#: () -> bool
|
|
210
|
+
def full_calc_on_load?
|
|
211
|
+
(@sheet_calc_pr && @sheet_calc_pr[:full_calc_on_load]) || sheet_properties[:full_calc_on_load] ? true : false
|
|
212
|
+
end
|
|
213
|
+
alias full_calc_on_load full_calc_on_load?
|
|
214
|
+
|
|
215
|
+
# Returns the outline and grouping properties of the worksheet, or an empty hash if none configured.
|
|
216
|
+
#
|
|
217
|
+
# @return [Hash]
|
|
218
|
+
# @api public
|
|
219
|
+
#: () -> Hash[Symbol, untyped]
|
|
220
|
+
def outline_properties
|
|
221
|
+
props = sheet_properties
|
|
222
|
+
return props[:outline_properties] if props[:outline_properties]
|
|
223
|
+
|
|
224
|
+
res = {}
|
|
225
|
+
res[:summary_below] = props[:summary_below] unless props[:summary_below].nil?
|
|
226
|
+
res[:summary_right] = props[:summary_right] unless props[:summary_right].nil?
|
|
227
|
+
res[:show_outline_symbols] = props[:show_outline_symbols] unless props[:show_outline_symbols].nil?
|
|
228
|
+
res[:apply_styles] = props[:apply_styles] unless props[:apply_styles].nil?
|
|
229
|
+
res
|
|
230
|
+
end
|
|
231
|
+
alias outline_pr outline_properties
|
|
232
|
+
|
|
157
233
|
# Iterate over rows in the worksheet.
|
|
158
234
|
#
|
|
159
235
|
# @example
|
|
@@ -417,6 +493,34 @@ module Xlsxrb
|
|
|
417
493
|
end
|
|
418
494
|
end
|
|
419
495
|
|
|
496
|
+
# Returns threaded comments for the given cell reference, or empty array.
|
|
497
|
+
#
|
|
498
|
+
# @param ref_or_row [String, Symbol, Integer] Cell reference (e.g. "A1") or 0-based row index.
|
|
499
|
+
# @param col [Integer, nil] Optional 0-based column index.
|
|
500
|
+
# @return [Array<Hash[Symbol, untyped]>]
|
|
501
|
+
# @api public
|
|
502
|
+
#: (String | Symbol | Integer ref_or_row, ?Integer? col) -> Array[Hash[Symbol, untyped]]
|
|
503
|
+
def threaded_comment(ref_or_row, col = nil)
|
|
504
|
+
ref = if col
|
|
505
|
+
"#{Cell.column_letter(col)}#{ref_or_row.to_i + 1}"
|
|
506
|
+
else
|
|
507
|
+
ref_or_row.to_s.upcase
|
|
508
|
+
end
|
|
509
|
+
threaded_comments_by_ref[ref] || []
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
# Returns threaded comments indexed by cell reference.
|
|
513
|
+
#
|
|
514
|
+
# @return [Hash<String, Array<Hash[Symbol, untyped]>>]
|
|
515
|
+
# @api public
|
|
516
|
+
#: () -> Hash[String, Array[Hash[Symbol, untyped]]]
|
|
517
|
+
def threaded_comments_by_ref
|
|
518
|
+
@threaded_comments_by_ref ||= @threaded_comments.each_with_object({}) do |c, acc|
|
|
519
|
+
r = c[:ref] || c[:cell]
|
|
520
|
+
(acc[r.to_s.upcase] ||= []) << c if r
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
420
524
|
# Access a cell by reference or 0-based coordinates.
|
|
421
525
|
#
|
|
422
526
|
# @param ref_or_row [String, Symbol, Integer] Cell reference (e.g. "A1") or 0-based row index.
|
|
@@ -550,7 +654,26 @@ module Xlsxrb
|
|
|
550
654
|
new_col_breaks = changes.key?(:col_breaks) ? changes[:col_breaks] : col_breaks
|
|
551
655
|
new_protected_ranges = changes.key?(:protected_ranges) ? changes[:protected_ranges] : protected_ranges
|
|
552
656
|
new_cell_watches = changes.key?(:cell_watches) ? changes[:cell_watches] : cell_watches
|
|
657
|
+
new_ignored_errors = changes.key?(:ignored_errors) ? changes[:ignored_errors] : ignored_errors
|
|
658
|
+
new_phonetic_properties = if changes.key?(:phonetic_properties)
|
|
659
|
+
changes[:phonetic_properties]
|
|
660
|
+
elsif changes.key?(:phonetic_pr)
|
|
661
|
+
changes[:phonetic_pr]
|
|
662
|
+
else
|
|
663
|
+
phonetic_properties
|
|
664
|
+
end
|
|
553
665
|
new_selection = changes.key?(:selection) ? changes[:selection] : selection
|
|
666
|
+
new_sheet_calc_pr = changes.key?(:sheet_calc_pr) ? changes[:sheet_calc_pr] : sheet_calc_pr
|
|
667
|
+
new_background_image = if changes.key?(:background_image)
|
|
668
|
+
changes[:background_image]
|
|
669
|
+
elsif changes.key?(:background_picture)
|
|
670
|
+
changes[:background_picture]
|
|
671
|
+
elsif changes.key?(:picture)
|
|
672
|
+
changes[:picture]
|
|
673
|
+
else
|
|
674
|
+
background_image
|
|
675
|
+
end
|
|
676
|
+
new_threaded_comments = changes.key?(:threaded_comments) ? changes[:threaded_comments] : threaded_comments
|
|
554
677
|
|
|
555
678
|
self.class.new(
|
|
556
679
|
name: new_name,
|
|
@@ -588,7 +711,12 @@ module Xlsxrb
|
|
|
588
711
|
col_breaks: new_col_breaks,
|
|
589
712
|
protected_ranges: new_protected_ranges,
|
|
590
713
|
cell_watches: new_cell_watches,
|
|
591
|
-
|
|
714
|
+
ignored_errors: new_ignored_errors,
|
|
715
|
+
phonetic_properties: new_phonetic_properties,
|
|
716
|
+
selection: new_selection,
|
|
717
|
+
sheet_calc_pr: new_sheet_calc_pr,
|
|
718
|
+
background_image: new_background_image,
|
|
719
|
+
threaded_comments: new_threaded_comments
|
|
592
720
|
)
|
|
593
721
|
end
|
|
594
722
|
|
|
@@ -608,6 +736,7 @@ module Xlsxrb
|
|
|
608
736
|
state: state,
|
|
609
737
|
hyperlinks: hyperlinks,
|
|
610
738
|
comments: comments,
|
|
739
|
+
threaded_comments: threaded_comments,
|
|
611
740
|
styles: styles,
|
|
612
741
|
date1904: date1904,
|
|
613
742
|
dimension: dimension,
|
|
@@ -630,7 +759,18 @@ module Xlsxrb
|
|
|
630
759
|
sheet_format: sheet_format,
|
|
631
760
|
row_breaks: row_breaks,
|
|
632
761
|
col_breaks: col_breaks,
|
|
633
|
-
|
|
762
|
+
protected_ranges: protected_ranges,
|
|
763
|
+
cell_watches: cell_watches,
|
|
764
|
+
ignored_errors: ignored_errors,
|
|
765
|
+
phonetic_properties: phonetic_properties,
|
|
766
|
+
phonetic_pr: phonetic_properties,
|
|
767
|
+
selection: selection,
|
|
768
|
+
sheet_calc_pr: sheet_calc_pr,
|
|
769
|
+
calc_pr: sheet_calc_pr,
|
|
770
|
+
code_name: code_name,
|
|
771
|
+
background_image: background_image,
|
|
772
|
+
background_picture: background_image,
|
|
773
|
+
picture: background_image
|
|
634
774
|
}
|
|
635
775
|
end
|
|
636
776
|
|
|
@@ -642,6 +782,7 @@ module Xlsxrb
|
|
|
642
782
|
name == other.name && rows == other.rows && columns == other.columns && charts == other.charts &&
|
|
643
783
|
conditional_formatting == other.conditional_formatting && data_validations == other.data_validations &&
|
|
644
784
|
state == other.state && hyperlinks == other.hyperlinks && comments == other.comments &&
|
|
785
|
+
threaded_comments == other.threaded_comments &&
|
|
645
786
|
merged_cells == other.merged_cells && auto_filter == other.auto_filter &&
|
|
646
787
|
tables == other.tables && shapes == other.shapes && freeze_pane == other.freeze_pane &&
|
|
647
788
|
page_setup == other.page_setup && page_margins == other.page_margins &&
|
|
@@ -649,7 +790,10 @@ module Xlsxrb
|
|
|
649
790
|
sheet_protection == other.sheet_protection && sheet_view == other.sheet_view &&
|
|
650
791
|
sheet_properties == other.sheet_properties && sheet_format == other.sheet_format &&
|
|
651
792
|
row_breaks == other.row_breaks && col_breaks == other.col_breaks &&
|
|
652
|
-
|
|
793
|
+
protected_ranges == other.protected_ranges && cell_watches == other.cell_watches &&
|
|
794
|
+
ignored_errors == other.ignored_errors && phonetic_properties == other.phonetic_properties &&
|
|
795
|
+
selection == other.selection && sheet_calc_pr == other.sheet_calc_pr &&
|
|
796
|
+
background_image == other.background_image
|
|
653
797
|
end
|
|
654
798
|
alias eql? ==
|
|
655
799
|
|
|
@@ -657,9 +801,10 @@ module Xlsxrb
|
|
|
657
801
|
def hash
|
|
658
802
|
[
|
|
659
803
|
self.class, name, rows, columns, charts, conditional_formatting, data_validations,
|
|
660
|
-
state, hyperlinks, comments, merged_cells, auto_filter, tables, shapes, freeze_pane,
|
|
804
|
+
state, hyperlinks, comments, threaded_comments, merged_cells, auto_filter, tables, shapes, freeze_pane,
|
|
661
805
|
page_setup, page_margins, header_footer, print_options, sheet_protection, sheet_view,
|
|
662
|
-
sheet_properties, sheet_format, row_breaks, col_breaks,
|
|
806
|
+
sheet_properties, sheet_format, row_breaks, col_breaks, protected_ranges,
|
|
807
|
+
cell_watches, ignored_errors, phonetic_properties, selection, sheet_calc_pr, background_image
|
|
663
808
|
].hash
|
|
664
809
|
end
|
|
665
810
|
|
|
@@ -673,7 +818,7 @@ module Xlsxrb
|
|
|
673
818
|
end
|
|
674
819
|
alias to_worksheet load
|
|
675
820
|
|
|
676
|
-
FORBIDDEN_NAME_CHARS = %r{[\\/?*\[\]]}
|
|
821
|
+
FORBIDDEN_NAME_CHARS = %r{[\\/?*\[\]:]|[\x00-\x08\x0B\x0C\x0E-\x1F]}
|
|
677
822
|
|
|
678
823
|
# Returns whether the worksheet name is valid according to OOXML specifications (1..31 chars, no forbidden chars).
|
|
679
824
|
#
|
|
@@ -683,7 +828,7 @@ module Xlsxrb
|
|
|
683
828
|
def self.valid_name?(name)
|
|
684
829
|
case name
|
|
685
830
|
when String
|
|
686
|
-
!name.empty? && name.size <= 31 && !name.match?(FORBIDDEN_NAME_CHARS)
|
|
831
|
+
!name.empty? && name.size <= 31 && !name.match?(FORBIDDEN_NAME_CHARS) && !name.start_with?("'") && !name.end_with?("'") && !name.casecmp?("History")
|
|
687
832
|
else
|
|
688
833
|
false
|
|
689
834
|
end
|
|
@@ -701,7 +846,9 @@ module Xlsxrb
|
|
|
701
846
|
errs << "worksheet name must be a non-empty String (got #{name.inspect})"
|
|
702
847
|
else
|
|
703
848
|
errs << "worksheet name cannot exceed 31 characters (got #{name.size})" if name.size > 31
|
|
704
|
-
errs << "worksheet name cannot contain \\, /, ?, *, [, or
|
|
849
|
+
errs << "worksheet name cannot contain \\, /, ?, *, [, ], or :" if name.match?(FORBIDDEN_NAME_CHARS)
|
|
850
|
+
errs << "worksheet name cannot start or end with an apostrophe" if name.start_with?("'") || name.end_with?("'")
|
|
851
|
+
errs << "worksheet name 'History' is reserved by Excel" if name.casecmp?("History")
|
|
705
852
|
end
|
|
706
853
|
errs << "rows must be an Array (got #{rows.class})" unless rows.is_a?(Array)
|
|
707
854
|
if rows.is_a?(Array)
|
|
@@ -150,6 +150,7 @@ module Xlsxrb
|
|
|
150
150
|
@value_buffer = +""
|
|
151
151
|
@inline_text_buffer = +""
|
|
152
152
|
@formula_buffer = +""
|
|
153
|
+
@shared_formula_masters = {}
|
|
153
154
|
@is_runs = []
|
|
154
155
|
@is_has_runs = false
|
|
155
156
|
@is_current_font = {}
|
|
@@ -302,6 +303,8 @@ module Xlsxrb
|
|
|
302
303
|
@value_buffer = +""
|
|
303
304
|
@inline_text_buffer = +""
|
|
304
305
|
@formula_buffer = +""
|
|
306
|
+
when "worksheet"
|
|
307
|
+
expand_shared_formulas!
|
|
305
308
|
end
|
|
306
309
|
end
|
|
307
310
|
|
|
@@ -339,8 +342,16 @@ module Xlsxrb
|
|
|
339
342
|
@value_buffer.dup
|
|
340
343
|
end
|
|
341
344
|
f_type = { "shared" => :shared, "array" => :array, "dataTable" => :data_table }[@formula_type]
|
|
345
|
+
expr = @formula_buffer.dup
|
|
346
|
+
if f_type == :shared && @formula_si
|
|
347
|
+
if !expr.empty?
|
|
348
|
+
@shared_formula_masters[@formula_si] = { cell: @current_cell_ref, expression: expr }
|
|
349
|
+
elsif (master = @shared_formula_masters[@formula_si])
|
|
350
|
+
expr = Xlsxrb::Utils.expand_formula(master[:expression], from_ref: master[:cell], to_ref: @current_cell_ref)
|
|
351
|
+
end
|
|
352
|
+
end
|
|
342
353
|
@cells[@current_cell_ref] = Xlsxrb::Elements::Formula.new(
|
|
343
|
-
expression:
|
|
354
|
+
expression: expr,
|
|
344
355
|
cached_value: cached,
|
|
345
356
|
type: f_type,
|
|
346
357
|
ref: @formula_ref,
|
|
@@ -377,6 +388,16 @@ module Xlsxrb
|
|
|
377
388
|
end
|
|
378
389
|
end
|
|
379
390
|
|
|
391
|
+
def expand_shared_formulas!
|
|
392
|
+
@cells.each do |ref, val|
|
|
393
|
+
next unless val.is_a?(Xlsxrb::Elements::Formula) && val.type == :shared && (val.expression.nil? || val.expression.empty?)
|
|
394
|
+
next unless val.shared_index && (master = @shared_formula_masters[val.shared_index])
|
|
395
|
+
|
|
396
|
+
expanded = Xlsxrb::Utils.expand_formula(master[:expression], from_ref: master[:cell], to_ref: ref)
|
|
397
|
+
@cells[ref] = val.with(expression: expanded)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
380
401
|
def numeric_value(raw)
|
|
381
402
|
Xlsxrb::Ooxml::WorksheetParser.numeric_cell_value(raw)
|
|
382
403
|
end
|