caxlsx 4.0.0 → 4.4.1
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 +48 -12
- data/README.md +18 -9
- data/Rakefile +2 -9
- data/examples/generate.rb +3 -1
- data/lib/axlsx/content_type/abstract_content_type.rb +6 -3
- data/lib/axlsx/content_type/content_type.rb +4 -4
- data/lib/axlsx/content_type/default.rb +4 -1
- data/lib/axlsx/content_type/override.rb +4 -1
- data/lib/axlsx/doc_props/app.rb +91 -24
- data/lib/axlsx/drawing/area_chart.rb +3 -3
- data/lib/axlsx/drawing/area_series.rb +10 -4
- data/lib/axlsx/drawing/ax_data_source.rb +1 -1
- data/lib/axlsx/drawing/axes.rb +1 -1
- data/lib/axlsx/drawing/axis.rb +25 -7
- data/lib/axlsx/drawing/bar_3D_chart.rb +14 -4
- data/lib/axlsx/drawing/bar_chart.rb +14 -4
- data/lib/axlsx/drawing/bar_series.rb +14 -5
- data/lib/axlsx/drawing/bubble_chart.rb +2 -2
- data/lib/axlsx/drawing/bubble_series.rb +2 -2
- data/lib/axlsx/drawing/cat_axis.rb +23 -8
- data/lib/axlsx/drawing/chart.rb +33 -8
- data/lib/axlsx/drawing/d_lbls.rb +9 -8
- data/lib/axlsx/drawing/drawing.rb +50 -49
- data/lib/axlsx/drawing/hyperlink.rb +13 -4
- data/lib/axlsx/drawing/line_3D_chart.rb +3 -3
- data/lib/axlsx/drawing/line_chart.rb +3 -3
- data/lib/axlsx/drawing/line_series.rb +10 -4
- data/lib/axlsx/drawing/marker.rb +19 -4
- data/lib/axlsx/drawing/num_val.rb +1 -1
- data/lib/axlsx/drawing/one_cell_anchor.rb +8 -2
- data/lib/axlsx/drawing/pic.rb +17 -8
- data/lib/axlsx/drawing/pie_3D_chart.rb +3 -3
- data/lib/axlsx/drawing/pie_chart.rb +36 -0
- data/lib/axlsx/drawing/pie_series.rb +18 -6
- data/lib/axlsx/drawing/scaling.rb +18 -4
- data/lib/axlsx/drawing/scatter_chart.rb +2 -2
- data/lib/axlsx/drawing/scatter_series.rb +2 -2
- data/lib/axlsx/drawing/ser_axis.rb +11 -5
- data/lib/axlsx/drawing/series.rb +8 -2
- data/lib/axlsx/drawing/two_cell_anchor.rb +1 -1
- data/lib/axlsx/drawing/val_axis.rb +2 -2
- data/lib/axlsx/drawing/view_3D.rb +8 -2
- data/lib/axlsx/drawing/vml_shape.rb +1 -1
- data/lib/axlsx/package.rb +54 -21
- data/lib/axlsx/rels/relationship.rb +15 -5
- data/lib/axlsx/rels/relationships.rb +3 -3
- data/lib/axlsx/stylesheet/border.rb +12 -3
- data/lib/axlsx/stylesheet/border_pr.rb +16 -4
- data/lib/axlsx/stylesheet/cell_alignment.rb +39 -10
- data/lib/axlsx/stylesheet/cell_protection.rb +9 -2
- data/lib/axlsx/stylesheet/cell_style.rb +30 -7
- data/lib/axlsx/stylesheet/color.rb +10 -4
- data/lib/axlsx/stylesheet/dxf.rb +29 -6
- data/lib/axlsx/stylesheet/fill.rb +4 -1
- data/lib/axlsx/stylesheet/font.rb +59 -13
- data/lib/axlsx/stylesheet/gradient_fill.rb +9 -3
- data/lib/axlsx/stylesheet/gradient_stop.rb +9 -2
- data/lib/axlsx/stylesheet/num_fmt.rb +8 -2
- data/lib/axlsx/stylesheet/pattern_fill.rb +15 -3
- data/lib/axlsx/stylesheet/styles.rb +84 -43
- data/lib/axlsx/stylesheet/table_style.rb +15 -4
- data/lib/axlsx/stylesheet/table_style_element.rb +12 -3
- data/lib/axlsx/stylesheet/table_styles.rb +10 -3
- data/lib/axlsx/stylesheet/theme.rb +163 -0
- data/lib/axlsx/stylesheet/xf.rb +70 -16
- data/lib/axlsx/util/accessors.rb +9 -7
- data/lib/axlsx/util/buffered_zip_output_stream.rb +6 -2
- data/lib/axlsx/util/constants.rb +14 -2
- data/lib/axlsx/util/mime_type_utils.rb +72 -13
- data/lib/axlsx/util/serialized_attributes.rb +2 -2
- data/lib/axlsx/util/simple_typed_list.rb +26 -14
- data/lib/axlsx/util/storage.rb +4 -4
- data/lib/axlsx/util/uri_utils.rb +70 -0
- data/lib/axlsx/util/validators.rb +6 -6
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +2 -1
- data/lib/axlsx/workbook/defined_names.rb +1 -1
- data/lib/axlsx/workbook/shared_strings_table.rb +3 -3
- data/lib/axlsx/workbook/workbook.rb +87 -67
- data/lib/axlsx/workbook/workbook_view.rb +1 -1
- data/lib/axlsx/workbook/workbook_views.rb +1 -1
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +4 -4
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +5 -3
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +4 -4
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_condition.rb +1 -1
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_state.rb +2 -2
- data/lib/axlsx/workbook/worksheet/border_creator.rb +4 -4
- data/lib/axlsx/workbook/worksheet/cell.rb +40 -20
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +1 -1
- data/lib/axlsx/workbook/worksheet/cfvo.rb +8 -2
- data/lib/axlsx/workbook/worksheet/col.rb +23 -9
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +1 -1
- data/lib/axlsx/workbook/worksheet/cols.rb +1 -1
- data/lib/axlsx/workbook/worksheet/comment.rb +2 -2
- data/lib/axlsx/workbook/worksheet/comments.rb +1 -1
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +9 -3
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +70 -15
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +3 -3
- data/lib/axlsx/workbook/worksheet/data_validation.rb +53 -14
- data/lib/axlsx/workbook/worksheet/data_validations.rb +3 -3
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +2 -2
- data/lib/axlsx/workbook/worksheet/dimension.rb +1 -1
- data/lib/axlsx/workbook/worksheet/header_footer.rb +1 -1
- data/lib/axlsx/workbook/worksheet/icon_set.rb +17 -5
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +1 -1
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_margins.rb +30 -7
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -2
- data/lib/axlsx/workbook/worksheet/page_setup.rb +32 -9
- data/lib/axlsx/workbook/worksheet/pane.rb +9 -2
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +30 -6
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/print_options.rb +1 -0
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +1 -1
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +31 -11
- data/lib/axlsx/workbook/worksheet/row.rb +5 -2
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +1 -1
- data/lib/axlsx/workbook/worksheet/selection.rb +8 -2
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +1 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -1
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +30 -9
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +3 -2
- data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +28 -14
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +4 -4
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +3 -2
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +2 -2
- data/lib/axlsx.rb +46 -30
- data/lib/caxlsx.rb +1 -1
- metadata +13 -52
|
@@ -11,8 +11,8 @@ module Axlsx
|
|
|
11
11
|
# @param [Hash] options
|
|
12
12
|
# @option [String] author the author of the comment
|
|
13
13
|
# @option [String] text The text for the comment
|
|
14
|
-
# @option [String] ref The
|
|
15
|
-
# @option [Boolean] visible This controls the
|
|
14
|
+
# @option [String] ref The reference (e.g. 'A3' where this comment will be anchored.
|
|
15
|
+
# @option [Boolean] visible This controls the visibility of the associated vml_shape.
|
|
16
16
|
def initialize(comments, options = {})
|
|
17
17
|
raise ArgumentError, "A comment needs a parent comments object" unless comments.is_a?(Comments)
|
|
18
18
|
|
|
@@ -37,7 +37,7 @@ module Axlsx
|
|
|
37
37
|
# @note the author, text and ref options are required
|
|
38
38
|
# @option options [String] author The name of the author for this comment
|
|
39
39
|
# @option options [String] text The text for this comment
|
|
40
|
-
# @option options [
|
|
40
|
+
# @option options [String|Cell] ref The cell that this comment is attached to.
|
|
41
41
|
def add_comment(options = {})
|
|
42
42
|
raise ArgumentError, "Comment require an author" unless options[:author]
|
|
43
43
|
raise ArgumentError, "Comment requires text" unless options[:text]
|
|
@@ -61,9 +61,15 @@ module Axlsx
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
# @see rules
|
|
64
|
-
def rules=(v)
|
|
64
|
+
def rules=(v)
|
|
65
|
+
@rules = v
|
|
66
|
+
end
|
|
67
|
+
|
|
65
68
|
# @see sqref
|
|
66
|
-
def sqref=(v)
|
|
69
|
+
def sqref=(v)
|
|
70
|
+
Axlsx.validate_string(v)
|
|
71
|
+
@sqref = v
|
|
72
|
+
end
|
|
67
73
|
|
|
68
74
|
# Serializes the conditional formatting element
|
|
69
75
|
# @example Conditional Formatting XML looks like:
|
|
@@ -77,7 +83,7 @@ module Axlsx
|
|
|
77
83
|
def to_xml_string(str = +'')
|
|
78
84
|
str << '<conditionalFormatting sqref="' << sqref << '">'
|
|
79
85
|
rules.each_with_index do |rule, index|
|
|
80
|
-
str << ' ' unless index
|
|
86
|
+
str << ' ' unless index == 0
|
|
81
87
|
rule.to_xml_string(str)
|
|
82
88
|
end
|
|
83
89
|
str << '</conditionalFormatting>'
|
|
@@ -24,7 +24,7 @@ module Axlsx
|
|
|
24
24
|
# @option options [Integer] rank If a top/bottom N rule, the value of N
|
|
25
25
|
# @option options [Integer] stdDev The number of standard deviations above or below the average to match
|
|
26
26
|
# @option options [Boolean] stopIfTrue Stop evaluating rules after this rule matches
|
|
27
|
-
# @option options [Symbol] timePeriod The time period in a date
|
|
27
|
+
# @option options [Symbol] timePeriod The time period in a date occurring... rule
|
|
28
28
|
# @option options [String] formula The formula to match against in i.e. an equal rule. Use a [minimum, maximum] array for cellIs between/notBetween conditionals.
|
|
29
29
|
def initialize(options = {})
|
|
30
30
|
@color_scale = @data_bar = @icon_set = @formula = nil
|
|
@@ -155,33 +155,88 @@ module Axlsx
|
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
# @see type
|
|
158
|
-
def type=(v)
|
|
158
|
+
def type=(v)
|
|
159
|
+
Axlsx.validate_conditional_formatting_type(v)
|
|
160
|
+
@type = v
|
|
161
|
+
end
|
|
162
|
+
|
|
159
163
|
# @see aboveAverage
|
|
160
|
-
def aboveAverage=(v)
|
|
164
|
+
def aboveAverage=(v)
|
|
165
|
+
Axlsx.validate_boolean(v)
|
|
166
|
+
@aboveAverage = v
|
|
167
|
+
end
|
|
168
|
+
|
|
161
169
|
# @see bottom
|
|
162
|
-
def bottom=(v)
|
|
170
|
+
def bottom=(v)
|
|
171
|
+
Axlsx.validate_boolean(v)
|
|
172
|
+
@bottom = v
|
|
173
|
+
end
|
|
174
|
+
|
|
163
175
|
# @see dxfId
|
|
164
|
-
def dxfId=(v)
|
|
176
|
+
def dxfId=(v)
|
|
177
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
178
|
+
@dxfId = v
|
|
179
|
+
end
|
|
180
|
+
|
|
165
181
|
# @see equalAverage
|
|
166
|
-
def equalAverage=(v)
|
|
182
|
+
def equalAverage=(v)
|
|
183
|
+
Axlsx.validate_boolean(v)
|
|
184
|
+
@equalAverage = v
|
|
185
|
+
end
|
|
186
|
+
|
|
167
187
|
# @see priority
|
|
168
|
-
def priority=(v)
|
|
188
|
+
def priority=(v)
|
|
189
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
190
|
+
@priority = v
|
|
191
|
+
end
|
|
192
|
+
|
|
169
193
|
# @see operator
|
|
170
|
-
def operator=(v)
|
|
194
|
+
def operator=(v)
|
|
195
|
+
Axlsx.validate_conditional_formatting_operator(v)
|
|
196
|
+
@operator = v
|
|
197
|
+
end
|
|
198
|
+
|
|
171
199
|
# @see text
|
|
172
|
-
def text=(v)
|
|
200
|
+
def text=(v)
|
|
201
|
+
Axlsx.validate_string(v)
|
|
202
|
+
@text = v
|
|
203
|
+
end
|
|
204
|
+
|
|
173
205
|
# @see percent
|
|
174
|
-
def percent=(v)
|
|
206
|
+
def percent=(v)
|
|
207
|
+
Axlsx.validate_boolean(v)
|
|
208
|
+
@percent = v
|
|
209
|
+
end
|
|
210
|
+
|
|
175
211
|
# @see rank
|
|
176
|
-
def rank=(v)
|
|
212
|
+
def rank=(v)
|
|
213
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
214
|
+
@rank = v
|
|
215
|
+
end
|
|
216
|
+
|
|
177
217
|
# @see stdDev
|
|
178
|
-
def stdDev=(v)
|
|
218
|
+
def stdDev=(v)
|
|
219
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
220
|
+
@stdDev = v
|
|
221
|
+
end
|
|
222
|
+
|
|
179
223
|
# @see stopIfTrue
|
|
180
|
-
def stopIfTrue=(v)
|
|
224
|
+
def stopIfTrue=(v)
|
|
225
|
+
Axlsx.validate_boolean(v)
|
|
226
|
+
@stopIfTrue = v
|
|
227
|
+
end
|
|
228
|
+
|
|
181
229
|
# @see timePeriod
|
|
182
|
-
def timePeriod=(v)
|
|
230
|
+
def timePeriod=(v)
|
|
231
|
+
Axlsx.validate_time_period_type(v)
|
|
232
|
+
@timePeriod = v
|
|
233
|
+
end
|
|
234
|
+
|
|
183
235
|
# @see formula
|
|
184
|
-
def formula=(v)
|
|
236
|
+
def formula=(v)
|
|
237
|
+
[*v].each { |x| Axlsx.validate_string(x) }
|
|
238
|
+
@formula = [*v].map { |form| ::CGI.escapeHTML(form) }
|
|
239
|
+
end
|
|
185
240
|
|
|
186
241
|
# @see color_scale
|
|
187
242
|
def color_scale=(v)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Axlsx
|
|
4
|
-
# A simple, self serializing class for storing conditional
|
|
4
|
+
# A simple, self serializing class for storing conditional formatting
|
|
5
5
|
class ConditionalFormattings < SimpleTypedList
|
|
6
6
|
# creates a new Tables object
|
|
7
7
|
def initialize(worksheet)
|
|
8
8
|
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
|
9
9
|
|
|
10
|
-
super
|
|
10
|
+
super(ConditionalFormatting)
|
|
11
11
|
@worksheet = worksheet
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ module Axlsx
|
|
|
15
15
|
# @return [Worksheet]
|
|
16
16
|
attr_reader :worksheet
|
|
17
17
|
|
|
18
|
-
# serialize the conditional
|
|
18
|
+
# serialize the conditional formatting
|
|
19
19
|
def to_xml_string(str = +'')
|
|
20
20
|
return if empty?
|
|
21
21
|
|
|
@@ -178,31 +178,58 @@ module Axlsx
|
|
|
178
178
|
attr_reader :type
|
|
179
179
|
|
|
180
180
|
# @see formula1
|
|
181
|
-
def formula1=(v)
|
|
181
|
+
def formula1=(v)
|
|
182
|
+
Axlsx.validate_string(v)
|
|
183
|
+
@formula1 = v
|
|
184
|
+
end
|
|
182
185
|
|
|
183
186
|
# @see formula2
|
|
184
|
-
def formula2=(v)
|
|
187
|
+
def formula2=(v)
|
|
188
|
+
Axlsx.validate_string(v)
|
|
189
|
+
@formula2 = v
|
|
190
|
+
end
|
|
185
191
|
|
|
186
192
|
# @see allowBlank
|
|
187
|
-
def allowBlank=(v)
|
|
193
|
+
def allowBlank=(v)
|
|
194
|
+
Axlsx.validate_boolean(v)
|
|
195
|
+
@allowBlank = v
|
|
196
|
+
end
|
|
188
197
|
|
|
189
198
|
# @see error
|
|
190
|
-
def error=(v)
|
|
199
|
+
def error=(v)
|
|
200
|
+
Axlsx.validate_string(v)
|
|
201
|
+
@error = v
|
|
202
|
+
end
|
|
191
203
|
|
|
192
204
|
# @see errorStyle
|
|
193
|
-
def errorStyle=(v)
|
|
205
|
+
def errorStyle=(v)
|
|
206
|
+
Axlsx.validate_data_validation_error_style(v)
|
|
207
|
+
@errorStyle = v
|
|
208
|
+
end
|
|
194
209
|
|
|
195
210
|
# @see errorTitle
|
|
196
|
-
def errorTitle=(v)
|
|
211
|
+
def errorTitle=(v)
|
|
212
|
+
Axlsx.validate_string(v)
|
|
213
|
+
@errorTitle = v
|
|
214
|
+
end
|
|
197
215
|
|
|
198
216
|
# @see operator
|
|
199
|
-
def operator=(v)
|
|
217
|
+
def operator=(v)
|
|
218
|
+
Axlsx.validate_data_validation_operator(v)
|
|
219
|
+
@operator = v
|
|
220
|
+
end
|
|
200
221
|
|
|
201
222
|
# @see prompt
|
|
202
|
-
def prompt=(v)
|
|
223
|
+
def prompt=(v)
|
|
224
|
+
Axlsx.validate_string(v)
|
|
225
|
+
@prompt = v
|
|
226
|
+
end
|
|
203
227
|
|
|
204
228
|
# @see promptTitle
|
|
205
|
-
def promptTitle=(v)
|
|
229
|
+
def promptTitle=(v)
|
|
230
|
+
Axlsx.validate_string(v)
|
|
231
|
+
@promptTitle = v
|
|
232
|
+
end
|
|
206
233
|
|
|
207
234
|
# @see showDropDown
|
|
208
235
|
def showDropDown=(v)
|
|
@@ -219,16 +246,28 @@ module Axlsx
|
|
|
219
246
|
end
|
|
220
247
|
|
|
221
248
|
# @see showErrorMessage
|
|
222
|
-
def showErrorMessage=(v)
|
|
249
|
+
def showErrorMessage=(v)
|
|
250
|
+
Axlsx.validate_boolean(v)
|
|
251
|
+
@showErrorMessage = v
|
|
252
|
+
end
|
|
223
253
|
|
|
224
254
|
# @see showInputMessage
|
|
225
|
-
def showInputMessage=(v)
|
|
255
|
+
def showInputMessage=(v)
|
|
256
|
+
Axlsx.validate_boolean(v)
|
|
257
|
+
@showInputMessage = v
|
|
258
|
+
end
|
|
226
259
|
|
|
227
260
|
# @see sqref
|
|
228
|
-
def sqref=(v)
|
|
261
|
+
def sqref=(v)
|
|
262
|
+
Axlsx.validate_string(v)
|
|
263
|
+
@sqref = v
|
|
264
|
+
end
|
|
229
265
|
|
|
230
266
|
# @see type
|
|
231
|
-
def type=(v)
|
|
267
|
+
def type=(v)
|
|
268
|
+
Axlsx.validate_data_validation_type(v)
|
|
269
|
+
@type = v
|
|
270
|
+
end
|
|
232
271
|
|
|
233
272
|
# Serializes the data validation
|
|
234
273
|
# @param [String] str
|
|
@@ -239,7 +278,7 @@ module Axlsx
|
|
|
239
278
|
|
|
240
279
|
str << '<dataValidation '
|
|
241
280
|
h.each_with_index do |key_value, index|
|
|
242
|
-
str << ' ' unless index
|
|
281
|
+
str << ' ' unless index == 0
|
|
243
282
|
str << key_value.first << '="' << Axlsx.booleanize(key_value.last).to_s << '"'
|
|
244
283
|
end
|
|
245
284
|
str << '>'
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Axlsx
|
|
4
|
-
# A simple, self serializing class for storing conditional
|
|
4
|
+
# A simple, self serializing class for storing conditional formatting
|
|
5
5
|
class DataValidations < SimpleTypedList
|
|
6
6
|
# creates a new Tables object
|
|
7
7
|
def initialize(worksheet)
|
|
8
8
|
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
|
9
9
|
|
|
10
|
-
super
|
|
10
|
+
super(DataValidation)
|
|
11
11
|
@worksheet = worksheet
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ module Axlsx
|
|
|
15
15
|
# @return [Worksheet]
|
|
16
16
|
attr_reader :worksheet
|
|
17
17
|
|
|
18
|
-
# serialize the conditional
|
|
18
|
+
# serialize the conditional formatting
|
|
19
19
|
def to_xml_string(str = +'')
|
|
20
20
|
return if empty?
|
|
21
21
|
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
require "date"
|
|
4
4
|
|
|
5
5
|
module Axlsx
|
|
6
|
-
# The DateTimeConverter class converts both data and time types to their
|
|
6
|
+
# The DateTimeConverter class converts both data and time types to their appropriate Excel serializations
|
|
7
7
|
class DateTimeConverter
|
|
8
|
-
# The date_to_serial method converts Date objects to the
|
|
8
|
+
# The date_to_serial method converts Date objects to the equivalent Excel serialized forms
|
|
9
9
|
# @param [Date] date the date to be serialized
|
|
10
10
|
# @return [Numeric]
|
|
11
11
|
def self.date_to_serial(date)
|
|
@@ -7,7 +7,7 @@ module Axlsx
|
|
|
7
7
|
# of plain text and control characters. A fairly comprehensive list of control
|
|
8
8
|
# characters can be found here:
|
|
9
9
|
# https://github.com/randym/axlsx/blob/master/notes_on_header_footer.md
|
|
10
|
-
#
|
|
10
|
+
#
|
|
11
11
|
# @note The recommended way of managing header/footers is via Worksheet#header_footer
|
|
12
12
|
# @see Worksheet#initialize
|
|
13
13
|
class HeaderFooter
|
|
@@ -56,7 +56,10 @@ module Axlsx
|
|
|
56
56
|
attr_reader :interpolationPoints
|
|
57
57
|
|
|
58
58
|
# @see iconSet
|
|
59
|
-
def iconSet=(v)
|
|
59
|
+
def iconSet=(v)
|
|
60
|
+
Axlsx.validate_icon_set(v)
|
|
61
|
+
@iconSet = v
|
|
62
|
+
end
|
|
60
63
|
|
|
61
64
|
# @see interpolationPoints
|
|
62
65
|
def interpolationPoints=(v)
|
|
@@ -66,13 +69,22 @@ module Axlsx
|
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
# @see showValue
|
|
69
|
-
def showValue=(v)
|
|
72
|
+
def showValue=(v)
|
|
73
|
+
Axlsx.validate_boolean(v)
|
|
74
|
+
@showValue = v
|
|
75
|
+
end
|
|
70
76
|
|
|
71
77
|
# @see percent
|
|
72
|
-
def percent=(v)
|
|
78
|
+
def percent=(v)
|
|
79
|
+
Axlsx.validate_boolean(v)
|
|
80
|
+
@percent = v
|
|
81
|
+
end
|
|
73
82
|
|
|
74
83
|
# @see reverse
|
|
75
|
-
def reverse=(v)
|
|
84
|
+
def reverse=(v)
|
|
85
|
+
Axlsx.validate_boolean(v)
|
|
86
|
+
@reverse = v
|
|
87
|
+
end
|
|
76
88
|
|
|
77
89
|
# Serialize this object to an xml string
|
|
78
90
|
# @param [String] str
|
|
@@ -87,7 +99,7 @@ module Axlsx
|
|
|
87
99
|
|
|
88
100
|
private
|
|
89
101
|
|
|
90
|
-
#
|
|
102
|
+
# Initialize the simple typed list of value objects
|
|
91
103
|
def initialize_value_objects
|
|
92
104
|
@value_objects = SimpleTypedList.new Cfvo
|
|
93
105
|
@interpolationPoints.each { |point| @value_objects << Cfvo.new(type: :percent, val: point) }
|
|
@@ -13,7 +13,7 @@ module Axlsx
|
|
|
13
13
|
:apply_styles
|
|
14
14
|
|
|
15
15
|
# These attributes are all boolean so I'm doing a bit of a hand
|
|
16
|
-
# waving magic show to set up the
|
|
16
|
+
# waving magic show to set up the attribute accessors
|
|
17
17
|
boolean_attr_accessor :summary_below,
|
|
18
18
|
:summary_right,
|
|
19
19
|
:apply_styles
|
|
@@ -73,22 +73,45 @@ module Axlsx
|
|
|
73
73
|
margins.select do |k, v|
|
|
74
74
|
next unless MARGIN_KEYS.include? k
|
|
75
75
|
|
|
76
|
-
send("#{k}=", v)
|
|
76
|
+
send(:"#{k}=", v)
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# @see left
|
|
81
|
-
def left=(v)
|
|
81
|
+
def left=(v)
|
|
82
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
83
|
+
@left = v
|
|
84
|
+
end
|
|
85
|
+
|
|
82
86
|
# @see right
|
|
83
|
-
def right=(v)
|
|
87
|
+
def right=(v)
|
|
88
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
89
|
+
@right = v
|
|
90
|
+
end
|
|
91
|
+
|
|
84
92
|
# @see top
|
|
85
|
-
def top=(v)
|
|
93
|
+
def top=(v)
|
|
94
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
95
|
+
@top = v
|
|
96
|
+
end
|
|
97
|
+
|
|
86
98
|
# @see bottom
|
|
87
|
-
def bottom=(v)
|
|
99
|
+
def bottom=(v)
|
|
100
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
101
|
+
@bottom = v
|
|
102
|
+
end
|
|
103
|
+
|
|
88
104
|
# @see header
|
|
89
|
-
def header=(v)
|
|
105
|
+
def header=(v)
|
|
106
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
107
|
+
@header = v
|
|
108
|
+
end
|
|
109
|
+
|
|
90
110
|
# @see footer
|
|
91
|
-
def footer=(v)
|
|
111
|
+
def footer=(v)
|
|
112
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
113
|
+
@footer = v
|
|
114
|
+
end
|
|
92
115
|
|
|
93
116
|
# Serializes the page margins element
|
|
94
117
|
# @param [String] str
|
|
@@ -17,8 +17,7 @@ module Axlsx
|
|
|
17
17
|
|
|
18
18
|
serializable_attributes :auto_page_breaks, :fit_to_page
|
|
19
19
|
|
|
20
|
-
attr_reader :auto_page_breaks
|
|
21
|
-
attr_reader :fit_to_page
|
|
20
|
+
attr_reader :auto_page_breaks, :fit_to_page
|
|
22
21
|
|
|
23
22
|
# Flag indicating whether the Fit to Page print option is enabled.
|
|
24
23
|
# @param [Boolean] value
|
|
@@ -38,13 +38,13 @@ module Axlsx
|
|
|
38
38
|
# * verticalDpi
|
|
39
39
|
|
|
40
40
|
# Number of vertical pages to fit on.
|
|
41
|
-
# @note PageSetup#fit_to is the
|
|
41
|
+
# @note PageSetup#fit_to is the recommended way to manage page fitting as only specifying one of fit_to_width/fit_to_height will result in the counterpart
|
|
42
42
|
# being set to 1.
|
|
43
43
|
# @return [Integer]
|
|
44
44
|
attr_reader :fit_to_height
|
|
45
45
|
|
|
46
46
|
# Number of horizontal pages to fit on.
|
|
47
|
-
# @note PageSetup#fit_to is the
|
|
47
|
+
# @note PageSetup#fit_to is the recommended way to manage page fitting as only specifying one of width/height will result in the counterpart
|
|
48
48
|
# being set to 1.
|
|
49
49
|
# @return [Integer]
|
|
50
50
|
attr_reader :fit_to_width
|
|
@@ -198,17 +198,40 @@ module Axlsx
|
|
|
198
198
|
end
|
|
199
199
|
|
|
200
200
|
# @see fit_to_height
|
|
201
|
-
def fit_to_height=(v)
|
|
201
|
+
def fit_to_height=(v)
|
|
202
|
+
Axlsx.validate_unsigned_int(v)
|
|
203
|
+
@fit_to_height = v
|
|
204
|
+
end
|
|
205
|
+
|
|
202
206
|
# @see fit_to_width
|
|
203
|
-
def fit_to_width=(v)
|
|
207
|
+
def fit_to_width=(v)
|
|
208
|
+
Axlsx.validate_unsigned_int(v)
|
|
209
|
+
@fit_to_width = v
|
|
210
|
+
end
|
|
211
|
+
|
|
204
212
|
# @see orientation
|
|
205
|
-
def orientation=(v)
|
|
213
|
+
def orientation=(v)
|
|
214
|
+
Axlsx.validate_page_orientation(v)
|
|
215
|
+
@orientation = v
|
|
216
|
+
end
|
|
217
|
+
|
|
206
218
|
# @see paper_height
|
|
207
|
-
def paper_height=(v)
|
|
219
|
+
def paper_height=(v)
|
|
220
|
+
Axlsx.validate_number_with_unit(v)
|
|
221
|
+
@paper_height = v
|
|
222
|
+
end
|
|
223
|
+
|
|
208
224
|
# @see paper_width
|
|
209
|
-
def paper_width=(v)
|
|
225
|
+
def paper_width=(v)
|
|
226
|
+
Axlsx.validate_number_with_unit(v)
|
|
227
|
+
@paper_width = v
|
|
228
|
+
end
|
|
229
|
+
|
|
210
230
|
# @see scale
|
|
211
|
-
def scale=(v)
|
|
231
|
+
def scale=(v)
|
|
232
|
+
Axlsx.validate_scale_10_400(v)
|
|
233
|
+
@scale = v
|
|
234
|
+
end
|
|
212
235
|
|
|
213
236
|
# convenience method to achieve sanity when setting fit_to_width and fit_to_height
|
|
214
237
|
# as they both default to 1 if only their counterpart is specified.
|
|
@@ -226,7 +249,7 @@ module Axlsx
|
|
|
226
249
|
# @return [Boolean]
|
|
227
250
|
def fit_to_page?
|
|
228
251
|
# is there some better way to express this?
|
|
229
|
-
|
|
252
|
+
!fit_to_width.nil? || !fit_to_height.nil?
|
|
230
253
|
end
|
|
231
254
|
|
|
232
255
|
# Serializes the page settings element.
|
|
@@ -8,6 +8,7 @@ module Axlsx
|
|
|
8
8
|
class Pane
|
|
9
9
|
include Axlsx::OptionsParser
|
|
10
10
|
include Axlsx::SerializedAttributes
|
|
11
|
+
|
|
11
12
|
# Creates a new {Pane} object
|
|
12
13
|
# @option options [Symbol] active_pane Active Pane
|
|
13
14
|
# @option options [Symbol] state Split State
|
|
@@ -114,10 +115,16 @@ module Axlsx
|
|
|
114
115
|
end
|
|
115
116
|
|
|
116
117
|
# @see x_split
|
|
117
|
-
def x_split=(v)
|
|
118
|
+
def x_split=(v)
|
|
119
|
+
Axlsx.validate_unsigned_int(v)
|
|
120
|
+
@x_split = v
|
|
121
|
+
end
|
|
118
122
|
|
|
119
123
|
# @see y_split
|
|
120
|
-
def y_split=(v)
|
|
124
|
+
def y_split=(v)
|
|
125
|
+
Axlsx.validate_unsigned_int(v)
|
|
126
|
+
@y_split = v
|
|
127
|
+
end
|
|
121
128
|
|
|
122
129
|
# Serializes the data validation
|
|
123
130
|
# @param [String] str
|
|
@@ -26,6 +26,7 @@ module Axlsx
|
|
|
26
26
|
@pages = []
|
|
27
27
|
@subtotal = nil
|
|
28
28
|
@no_subtotals_on_headers = []
|
|
29
|
+
@grand_totals = :both
|
|
29
30
|
@sort_on_headers = {}
|
|
30
31
|
@style_info = {}
|
|
31
32
|
parse_options options
|
|
@@ -51,6 +52,19 @@ module Axlsx
|
|
|
51
52
|
@sort_on_headers = headers
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
# Defines which Grand Totals are to be shown.
|
|
56
|
+
# @return [Symbol] The row and/or column Grand Totals that are to be shown.
|
|
57
|
+
# Defaults to `:both` to show both row & column grand totals.
|
|
58
|
+
# Set to `:row_only`, `:col_only`, or `:none` to hide one or both Grand Totals.
|
|
59
|
+
attr_reader :grand_totals
|
|
60
|
+
|
|
61
|
+
# (see #grand_totals)
|
|
62
|
+
def grand_totals=(value)
|
|
63
|
+
RestrictionValidator.validate "PivotTable.grand_totals", [:both, :row_only, :col_only, :none], value
|
|
64
|
+
|
|
65
|
+
@grand_totals = value
|
|
66
|
+
end
|
|
67
|
+
|
|
54
68
|
# Style info for the pivot table
|
|
55
69
|
# @return [Hash]
|
|
56
70
|
attr_accessor :style_info
|
|
@@ -114,7 +128,8 @@ module Axlsx
|
|
|
114
128
|
@columns = v
|
|
115
129
|
end
|
|
116
130
|
|
|
117
|
-
# The data
|
|
131
|
+
# The data as an array of either headers (String) or hashes or mix of the two.
|
|
132
|
+
# Hash in format of { ref: header, num_fmt: numFmts, subtotal: subtotal }, where header is String, numFmts is Integer, and subtotal one of %w[sum count average max min product countNums stdDev stdDevp var varp]; leave subtotal blank to sum values
|
|
118
133
|
# @return [Array]
|
|
119
134
|
attr_reader :data
|
|
120
135
|
|
|
@@ -188,7 +203,11 @@ module Axlsx
|
|
|
188
203
|
def to_xml_string(str = +'')
|
|
189
204
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
190
205
|
|
|
191
|
-
str << '<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '"'
|
|
206
|
+
str << '<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '"'
|
|
207
|
+
str << ' dataOnRows="1"' if data.size <= 1
|
|
208
|
+
str << ' rowGrandTotals="0"' if grand_totals == :col_only || grand_totals == :none
|
|
209
|
+
str << ' colGrandTotals="0"' if grand_totals == :row_only || grand_totals == :none
|
|
210
|
+
str << ' applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">'
|
|
192
211
|
|
|
193
212
|
str << '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>'
|
|
194
213
|
str << '<pivotFields count="' << header_cells_count.to_s << '">'
|
|
@@ -244,8 +263,9 @@ module Axlsx
|
|
|
244
263
|
unless data.empty?
|
|
245
264
|
str << "<dataFields count=\"#{data.size}\">"
|
|
246
265
|
data.each do |datum_value|
|
|
247
|
-
|
|
248
|
-
|
|
266
|
+
subtotal_name = datum_value[:subtotal] || 'sum'
|
|
267
|
+
subtotal_name = 'count' if name == 'countNums' # both count & countNums are labelled as count
|
|
268
|
+
str << "<dataField name='#{subtotal_name.capitalize} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
|
|
249
269
|
str << " numFmtId='#{datum_value[:num_fmt]}'" if datum_value[:num_fmt]
|
|
250
270
|
str << " subtotal='#{datum_value[:subtotal]}' " if datum_value[:subtotal]
|
|
251
271
|
str << "/>"
|
|
@@ -311,7 +331,11 @@ module Axlsx
|
|
|
311
331
|
elsif columns.include? cell_ref
|
|
312
332
|
attributes << 'axis="axisCol"'
|
|
313
333
|
attributes << "sortType=\"#{sorttype == :descending ? 'descending' : 'ascending'}\"" if sorttype
|
|
314
|
-
|
|
334
|
+
if subtotal
|
|
335
|
+
include_items_tag = true
|
|
336
|
+
else
|
|
337
|
+
attributes << 'defaultSubtotal="0"'
|
|
338
|
+
end
|
|
315
339
|
elsif pages.include? cell_ref
|
|
316
340
|
attributes << 'axis="axisPage"'
|
|
317
341
|
include_items_tag = true
|
|
@@ -319,7 +343,7 @@ module Axlsx
|
|
|
319
343
|
attributes << 'dataField="1"'
|
|
320
344
|
end
|
|
321
345
|
|
|
322
|
-
"<pivotField #{attributes.join(' ')}>#{
|
|
346
|
+
"<pivotField #{attributes.join(' ')}>#{items_tag if include_items_tag}</pivotField>"
|
|
323
347
|
end
|
|
324
348
|
|
|
325
349
|
def data_refs
|