axlsx 2.0.1 → 3.0.0.pre
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 +5 -0
- data/README.md +23 -23
- data/Rakefile +9 -11
- data/examples/auto_filter.rb +10 -1
- data/examples/conditional_formatting/example_conditional_formatting.rb +18 -3
- data/examples/example.rb +102 -4
- data/examples/merge_cells.rb +17 -0
- data/examples/no_grid_with_borders.rb +18 -0
- data/examples/pivot_test.rb +63 -0
- data/examples/split.rb +16 -0
- data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
- data/lib/axlsx/content_type/content_type.rb +1 -1
- data/lib/axlsx/doc_props/app.rb +1 -1
- data/lib/axlsx/doc_props/core.rb +5 -5
- data/lib/axlsx/drawing/area_chart.rb +99 -0
- data/lib/axlsx/drawing/area_series.rb +110 -0
- data/lib/axlsx/drawing/axes.rb +1 -1
- data/lib/axlsx/drawing/axis.rb +12 -9
- data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
- data/lib/axlsx/drawing/bar_chart.rb +143 -0
- data/lib/axlsx/drawing/bar_series.rb +9 -9
- data/lib/axlsx/drawing/bubble_chart.rb +59 -0
- data/lib/axlsx/drawing/bubble_series.rb +63 -0
- data/lib/axlsx/drawing/cat_axis.rb +5 -5
- data/lib/axlsx/drawing/chart.rb +52 -8
- data/lib/axlsx/drawing/d_lbls.rb +3 -3
- data/lib/axlsx/drawing/drawing.rb +6 -1
- data/lib/axlsx/drawing/graphic_frame.rb +3 -3
- data/lib/axlsx/drawing/hyperlink.rb +1 -3
- data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
- data/lib/axlsx/drawing/line_chart.rb +10 -10
- data/lib/axlsx/drawing/line_series.rb +32 -3
- data/lib/axlsx/drawing/marker.rb +1 -1
- data/lib/axlsx/drawing/num_data.rb +4 -4
- data/lib/axlsx/drawing/num_data_source.rb +6 -6
- data/lib/axlsx/drawing/num_val.rb +3 -1
- data/lib/axlsx/drawing/one_cell_anchor.rb +3 -2
- data/lib/axlsx/drawing/pic.rb +25 -19
- data/lib/axlsx/drawing/picture_locking.rb +1 -3
- data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
- data/lib/axlsx/drawing/pie_series.rb +6 -6
- data/lib/axlsx/drawing/scaling.rb +6 -6
- data/lib/axlsx/drawing/scatter_chart.rb +10 -10
- data/lib/axlsx/drawing/scatter_series.rb +40 -7
- data/lib/axlsx/drawing/ser_axis.rb +2 -2
- data/lib/axlsx/drawing/series.rb +3 -3
- data/lib/axlsx/drawing/series_title.rb +2 -2
- data/lib/axlsx/drawing/str_data.rb +3 -3
- data/lib/axlsx/drawing/str_val.rb +3 -1
- data/lib/axlsx/drawing/title.rb +22 -4
- data/lib/axlsx/drawing/two_cell_anchor.rb +6 -1
- data/lib/axlsx/drawing/val_axis.rb +1 -1
- data/lib/axlsx/drawing/view_3D.rb +2 -2
- data/lib/axlsx/drawing/vml_drawing.rb +1 -1
- data/lib/axlsx/package.rb +34 -32
- data/lib/axlsx/rels/relationship.rb +1 -1
- data/lib/axlsx/rels/relationships.rb +7 -4
- data/lib/axlsx/stylesheet/border_pr.rb +2 -2
- data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
- data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
- data/lib/axlsx/stylesheet/cell_style.rb +1 -3
- data/lib/axlsx/stylesheet/color.rb +1 -3
- data/lib/axlsx/stylesheet/font.rb +1 -1
- data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
- data/lib/axlsx/stylesheet/num_fmt.rb +10 -3
- data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
- data/lib/axlsx/stylesheet/styles.rb +7 -7
- data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
- data/lib/axlsx/util/accessors.rb +6 -6
- data/lib/axlsx/util/constants.rb +107 -99
- data/lib/axlsx/util/mime_type_utils.rb +11 -0
- data/lib/axlsx/util/options_parser.rb +2 -1
- data/lib/axlsx/util/parser.rb +4 -4
- data/lib/axlsx/util/serialized_attributes.rb +16 -6
- data/lib/axlsx/util/simple_typed_list.rb +28 -52
- data/lib/axlsx/util/storage.rb +4 -4
- data/lib/axlsx/util/validators.rb +29 -17
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +11 -12
- data/lib/axlsx/workbook/defined_names.rb +2 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
- data/lib/axlsx/workbook/workbook.rb +36 -11
- data/lib/axlsx/workbook/workbook_view.rb +80 -0
- data/lib/axlsx/workbook/workbook_views.rb +22 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
- data/lib/axlsx/workbook/worksheet/break.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cell.rb +136 -74
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +63 -43
- data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cfvos.rb +4 -1
- data/lib/axlsx/workbook/worksheet/col.rb +7 -10
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/cols.rb +5 -2
- data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
- data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
- data/lib/axlsx/workbook/worksheet/data_validation.rb +6 -4
- data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
- data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
- data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +4 -2
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +33 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
- data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +44 -28
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
- data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +5 -2
- data/lib/axlsx/workbook/worksheet/rich_text.rb +55 -0
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +250 -0
- data/lib/axlsx/workbook/worksheet/row.rb +40 -51
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +21 -3
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/table.rb +6 -6
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
- data/lib/axlsx/workbook/worksheet/tables.rb +4 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +64 -78
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +10 -10
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
- data/lib/axlsx.rb +34 -15
- data/test/drawing/tc_area_chart.rb +39 -0
- data/test/drawing/tc_area_series.rb +71 -0
- data/test/drawing/tc_axis.rb +27 -0
- data/test/drawing/tc_bar_chart.rb +71 -0
- data/test/drawing/tc_bubble_chart.rb +44 -0
- data/test/drawing/tc_bubble_series.rb +21 -0
- data/test/drawing/tc_chart.rb +23 -10
- data/test/drawing/tc_data_source.rb +6 -0
- data/test/drawing/tc_drawing.rb +2 -2
- data/test/drawing/tc_line_chart.rb +5 -5
- data/test/drawing/tc_line_series.rb +47 -6
- data/test/drawing/tc_pic.rb +11 -15
- data/test/drawing/tc_scatter_series.rb +36 -1
- data/test/drawing/tc_str_val.rb +9 -0
- data/test/drawing/tc_title.rb +5 -0
- data/test/stylesheet/tc_styles.rb +2 -2
- data/test/tc_axlsx.rb +31 -0
- data/test/tc_helper.rb +2 -0
- data/test/tc_package.rb +19 -1
- data/test/util/tc_mime_type_utils.rb +13 -0
- data/test/util/tc_simple_typed_list.rb +2 -3
- data/test/util/tc_validators.rb +34 -10
- data/test/workbook/tc_defined_name.rb +12 -4
- data/test/workbook/tc_shared_strings_table.rb +16 -1
- data/test/workbook/tc_workbook.rb +38 -3
- data/test/workbook/tc_workbook_view.rb +50 -0
- data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
- data/test/workbook/worksheet/tc_break.rb +1 -1
- data/test/workbook/worksheet/tc_cell.rb +76 -8
- data/test/workbook/worksheet/tc_col.rb +2 -2
- data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
- data/test/workbook/worksheet/tc_data_bar.rb +1 -1
- data/test/workbook/worksheet/tc_data_validation.rb +11 -11
- data/test/workbook/worksheet/tc_header_footer.rb +2 -2
- data/test/workbook/worksheet/tc_icon_set.rb +1 -1
- data/test/workbook/worksheet/tc_outline_pr.rb +19 -0
- data/test/workbook/worksheet/tc_page_setup.rb +3 -3
- data/test/workbook/worksheet/tc_pivot_table.rb +21 -6
- data/test/workbook/worksheet/tc_print_options.rb +1 -1
- data/test/workbook/worksheet/tc_rich_text.rb +44 -0
- data/test/workbook/worksheet/tc_rich_text_run.rb +172 -0
- data/test/workbook/worksheet/tc_row.rb +7 -2
- data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
- data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
- data/test/workbook/worksheet/tc_sheet_pr.rb +26 -4
- data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
- data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
- data/test/workbook/worksheet/tc_table.rb +2 -3
- data/test/workbook/worksheet/tc_worksheet.rb +99 -45
- metadata +142 -64
@@ -30,17 +30,24 @@ module Axlsx
|
|
30
30
|
# @option options [String] color an 8 letter rgb specification
|
31
31
|
# @option options [Number] formula_value The value to cache for a formula cell.
|
32
32
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
33
|
-
def initialize(row, value=
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
def initialize(row, value = nil, options = {})
|
34
|
+
@row = row
|
35
|
+
# Do not use instance vars if not needed to use less RAM
|
36
|
+
# And do not call parse_options on frequently used options
|
37
|
+
# to get less GC cycles
|
38
|
+
type = options.delete(:type) || cell_type_from_value(value)
|
39
|
+
self.type = type unless type == :string
|
40
|
+
|
41
|
+
|
42
|
+
val = options.delete(:style)
|
43
|
+
self.style = val unless val.nil? || val == 0
|
44
|
+
val = options.delete(:formula_value)
|
45
|
+
self.formula_value = val unless val.nil?
|
46
|
+
|
47
|
+
parse_options(options)
|
48
|
+
|
49
|
+
self.value = value
|
50
|
+
value.cell = self if contains_rich_text?
|
44
51
|
end
|
45
52
|
|
46
53
|
# this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview
|
@@ -53,21 +60,27 @@ module Axlsx
|
|
53
60
|
# needs to define bla=(v) and bla methods on the class that hook into a
|
54
61
|
# set_attr method that kicks the suplied validator and updates the instance_variable
|
55
62
|
# for the key
|
56
|
-
INLINE_STYLES = [
|
57
|
-
|
58
|
-
|
59
|
-
|
63
|
+
INLINE_STYLES = [:value, :type, :font_name, :charset,
|
64
|
+
:family, :b, :i, :strike, :outline,
|
65
|
+
:shadow, :condense, :extend, :u,
|
66
|
+
:vertAlign, :sz, :color, :scheme].freeze
|
67
|
+
|
68
|
+
# An array of valid cell types
|
69
|
+
CELL_TYPES = [:date, :time, :float, :integer, :richtext,
|
70
|
+
:string, :boolean, :iso_8601, :text].freeze
|
60
71
|
|
61
72
|
# The index of the cellXfs item to be applied to this cell.
|
62
73
|
# @return [Integer]
|
63
74
|
# @see Axlsx::Styles
|
64
|
-
|
75
|
+
def style
|
76
|
+
defined?(@style) ? @style : 0
|
77
|
+
end
|
65
78
|
|
66
79
|
# The row this cell belongs to.
|
67
80
|
# @return [Row]
|
68
81
|
attr_reader :row
|
69
82
|
|
70
|
-
# The cell's data type.
|
83
|
+
# The cell's data type.
|
71
84
|
# Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
|
72
85
|
# automatically determed.
|
73
86
|
# @see Cell#cell_type_from_value
|
@@ -78,18 +91,21 @@ module Axlsx
|
|
78
91
|
# :string to :integer or :float, type conversions always return 0 or 0.0
|
79
92
|
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
80
93
|
# No support is currently implemented for parsing time strings.
|
81
|
-
|
94
|
+
def type
|
95
|
+
defined?(@type) ? @type : :string
|
96
|
+
end
|
97
|
+
|
82
98
|
# @see type
|
83
99
|
def type=(v)
|
84
|
-
RestrictionValidator.validate
|
85
|
-
@type=v
|
86
|
-
self.value = @value unless @value.nil?
|
100
|
+
RestrictionValidator.validate :cell_type, CELL_TYPES, v
|
101
|
+
@type = v
|
102
|
+
self.value = @value unless !defined?(@value) || @value.nil?
|
87
103
|
end
|
88
104
|
|
89
|
-
|
90
105
|
# The value of this cell.
|
91
106
|
# @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
|
92
107
|
attr_reader :value
|
108
|
+
|
93
109
|
# @see value
|
94
110
|
def value=(v)
|
95
111
|
#TODO: consider doing value based type determination first?
|
@@ -99,16 +115,20 @@ module Axlsx
|
|
99
115
|
# Indicates that the cell has one or more of the custom cell styles applied.
|
100
116
|
# @return [Boolean]
|
101
117
|
def is_text_run?
|
102
|
-
@is_text_run
|
118
|
+
defined?(@is_text_run) && @is_text_run && !contains_rich_text?
|
119
|
+
end
|
120
|
+
|
121
|
+
def contains_rich_text?
|
122
|
+
type == :richtext
|
103
123
|
end
|
104
124
|
|
105
125
|
# Indicates if the cell is good for shared string table
|
106
126
|
def plain_string?
|
107
|
-
|
127
|
+
(type == :string || type == :text) && # String typed
|
108
128
|
!is_text_run? && # No inline styles
|
109
129
|
!@value.nil? && # Not nil
|
110
130
|
!@value.empty? && # Not empty
|
111
|
-
!@value.start_with?(
|
131
|
+
!@value.start_with?(?=) # Not a formula
|
112
132
|
end
|
113
133
|
|
114
134
|
# The inline font_name property for the cell
|
@@ -231,7 +251,7 @@ module Axlsx
|
|
231
251
|
attr_reader :vertAlign
|
232
252
|
# @see vertAlign
|
233
253
|
def vertAlign=(v)
|
234
|
-
RestrictionValidator.validate
|
254
|
+
RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v
|
235
255
|
set_run_style nil, :vertAlign, v
|
236
256
|
end
|
237
257
|
|
@@ -241,7 +261,7 @@ module Axlsx
|
|
241
261
|
attr_reader :scheme
|
242
262
|
# @see scheme
|
243
263
|
def scheme=(v)
|
244
|
-
RestrictionValidator.validate
|
264
|
+
RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v
|
245
265
|
set_run_style nil, :scheme, v
|
246
266
|
end
|
247
267
|
|
@@ -251,14 +271,14 @@ module Axlsx
|
|
251
271
|
|
252
272
|
# @return [Integer] The index of the cell in the containing row.
|
253
273
|
def index
|
254
|
-
@row.
|
274
|
+
@row.index(self)
|
255
275
|
end
|
256
276
|
|
257
277
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
258
278
|
# @example Relative Cell Reference
|
259
279
|
# ws.rows.first.cells.first.r #=> "A1"
|
260
280
|
def r
|
261
|
-
Axlsx::cell_r index, @row.
|
281
|
+
Axlsx::cell_r index, @row.row_index
|
262
282
|
end
|
263
283
|
|
264
284
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
@@ -272,26 +292,26 @@ module Axlsx
|
|
272
292
|
# @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
|
273
293
|
def style=(v)
|
274
294
|
Axlsx::validate_unsigned_int(v)
|
275
|
-
count =
|
295
|
+
count = styles.cellXfs.size
|
276
296
|
raise ArgumentError, "Invalid cellXfs id" unless v < count
|
277
297
|
@style = v
|
278
298
|
end
|
279
299
|
|
280
|
-
# @return [Array] of x/y coordinates in the
|
300
|
+
# @return [Array] of x/y coordinates in the sheet for this cell.
|
281
301
|
def pos
|
282
|
-
[index, row.
|
302
|
+
[index, row.row_index]
|
283
303
|
end
|
284
304
|
|
285
305
|
# Merges all the cells in a range created between this cell and the cell or string name for a cell provided
|
286
306
|
# @see worksheet.merge_cells
|
287
307
|
# @param [Cell, String] target The last cell, or str ref for the cell in the merge range
|
288
308
|
def merge(target)
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
self.row.worksheet.merge_cells "#{
|
309
|
+
start, stop = if target.is_a?(String)
|
310
|
+
[self.r, target]
|
311
|
+
elsif(target.is_a?(Cell))
|
312
|
+
Axlsx.sort_cells([self, target]).map { |c| c.r }
|
313
|
+
end
|
314
|
+
self.row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
|
295
315
|
end
|
296
316
|
|
297
317
|
# Serializes the cell
|
@@ -304,17 +324,11 @@ module Axlsx
|
|
304
324
|
end
|
305
325
|
|
306
326
|
def is_formula?
|
307
|
-
|
327
|
+
type == :string && @value.to_s.start_with?(?=)
|
308
328
|
end
|
309
329
|
|
310
|
-
|
311
|
-
|
312
|
-
# - different fonts have different mdw and char widths
|
313
|
-
def autowidth
|
314
|
-
return if is_formula? || value == nil
|
315
|
-
mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
|
316
|
-
font_scale = (font_size/10.0).to_f
|
317
|
-
((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
|
330
|
+
def is_array_formula?
|
331
|
+
type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
|
318
332
|
end
|
319
333
|
|
320
334
|
# returns the absolute or relative string style reference for
|
@@ -326,21 +340,71 @@ module Axlsx
|
|
326
340
|
absolute ? r_abs : r
|
327
341
|
end
|
328
342
|
|
343
|
+
# Creates a defined name in the workbook for this cell.
|
344
|
+
def name=(label)
|
345
|
+
row.worksheet.workbook.add_defined_name "#{row.worksheet.name}!#{r_abs}", name: label
|
346
|
+
@name = label
|
347
|
+
end
|
348
|
+
|
349
|
+
# returns the name of the cell
|
350
|
+
attr_reader :name
|
351
|
+
|
352
|
+
# Attempts to determine the correct width for this cell's content
|
353
|
+
# @return [Float]
|
354
|
+
def autowidth
|
355
|
+
return if is_formula? || value.nil?
|
356
|
+
if contains_rich_text?
|
357
|
+
string_width('', font_size) + value.autowidth
|
358
|
+
elsif styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
|
359
|
+
max_width = 0
|
360
|
+
value.to_s.split(/\r?\n/).each do |line|
|
361
|
+
width = string_width(line, font_size)
|
362
|
+
max_width = width if width > max_width
|
363
|
+
end
|
364
|
+
max_width
|
365
|
+
else
|
366
|
+
string_width(value, font_size)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Returns the sanatized value
|
371
|
+
# TODO find a better way to do this as it accounts for 30% of
|
372
|
+
# processing time in benchmarking...
|
373
|
+
def clean_value
|
374
|
+
if (type == :string || type == :text) && !Axlsx::trust_input
|
375
|
+
Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
|
376
|
+
else
|
377
|
+
@value.to_s
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
329
381
|
private
|
330
382
|
|
383
|
+
def styles
|
384
|
+
row.worksheet.styles
|
385
|
+
end
|
386
|
+
|
387
|
+
# Returns the width of a string according to the current style
|
388
|
+
# This is still not perfect...
|
389
|
+
# - scaling is not linear as font sizes increase
|
390
|
+
def string_width(string, font_size)
|
391
|
+
font_scale = font_size / 10.0
|
392
|
+
(string.to_s.count(Worksheet::THIN_CHARS) + 3.0) * font_scale
|
393
|
+
end
|
394
|
+
|
331
395
|
# we scale the font size if bold style is applied to either the style font or
|
332
396
|
# the cell itself. Yes, it is a bit of a hack, but it is much better than using
|
333
397
|
# imagemagick and loading metrics for every character.
|
334
398
|
def font_size
|
335
|
-
|
336
|
-
|
337
|
-
|
399
|
+
return sz if sz
|
400
|
+
font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0]
|
401
|
+
(font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz
|
338
402
|
end
|
339
403
|
|
340
404
|
# Utility method for setting inline style attributes
|
341
|
-
def set_run_style(
|
342
|
-
return unless INLINE_STYLES.include?(attr.
|
343
|
-
Axlsx.send(validator, value) unless validator
|
405
|
+
def set_run_style(validator, attr, value)
|
406
|
+
return unless INLINE_STYLES.include?(attr.to_sym)
|
407
|
+
Axlsx.send(validator, value) unless validator.nil?
|
344
408
|
self.instance_variable_set :"@#{attr.to_s}", value
|
345
409
|
@is_text_run = true
|
346
410
|
end
|
@@ -351,9 +415,6 @@ module Axlsx
|
|
351
415
|
@ssti = v
|
352
416
|
end
|
353
417
|
|
354
|
-
# assigns the owning row for this cell.
|
355
|
-
def row=(v) @row=v end
|
356
|
-
|
357
418
|
# Determines the cell type based on the cell value.
|
358
419
|
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
|
359
420
|
# 1. If the value is an instance of Date, the type is set to :date
|
@@ -369,15 +430,14 @@ module Axlsx
|
|
369
430
|
:time
|
370
431
|
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
371
432
|
:boolean
|
372
|
-
elsif v.to_s =~
|
433
|
+
elsif v.to_s =~ Axlsx::NUMERIC_REGEX
|
373
434
|
:integer
|
374
|
-
elsif v.to_s =~
|
435
|
+
elsif v.to_s =~ Axlsx::FLOAT_REGEX
|
375
436
|
:float
|
376
|
-
|
377
|
-
# T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?
|
378
|
-
# (Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z
|
379
|
-
elsif v.to_s =~/\A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/
|
437
|
+
elsif v.to_s =~ Axlsx::ISO_8601_REGEX
|
380
438
|
:iso_8601
|
439
|
+
elsif v.is_a? RichText
|
440
|
+
:richtext
|
381
441
|
else
|
382
442
|
:string
|
383
443
|
end
|
@@ -388,27 +448,29 @@ module Axlsx
|
|
388
448
|
# About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
|
389
449
|
# @see Axlsx#date1904
|
390
450
|
def cast_value(v)
|
391
|
-
return
|
392
|
-
|
451
|
+
return v if v.is_a?(RichText) || v.nil?
|
452
|
+
case type
|
453
|
+
when :date
|
393
454
|
self.style = STYLE_DATE if self.style == 0
|
394
455
|
v
|
395
|
-
|
456
|
+
when :time
|
396
457
|
self.style = STYLE_DATE if self.style == 0
|
397
|
-
v.
|
398
|
-
|
458
|
+
if !v.is_a?(Time) && v.respond_to?(:to_time)
|
459
|
+
v.to_time
|
460
|
+
else
|
461
|
+
v
|
462
|
+
end
|
463
|
+
when :float
|
399
464
|
v.to_f
|
400
|
-
|
465
|
+
when :integer
|
401
466
|
v.to_i
|
402
|
-
|
467
|
+
when :boolean
|
403
468
|
v ? 1 : 0
|
404
|
-
|
469
|
+
when :iso_8601
|
405
470
|
#consumer is responsible for ensuring the iso_8601 format when specifying this type
|
406
471
|
v
|
407
472
|
else
|
408
|
-
|
409
|
-
# TODO find a better way to do this as it accounts for 30% of
|
410
|
-
# processing time in benchmarking...
|
411
|
-
Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
|
473
|
+
v.to_s
|
412
474
|
end
|
413
475
|
end
|
414
476
|
|
@@ -3,43 +3,32 @@ module Axlsx
|
|
3
3
|
# The Cell Serializer class contains the logic for serializing cells based on their type.
|
4
4
|
class CellSerializer
|
5
5
|
class << self
|
6
|
-
|
7
|
-
|
8
6
|
# Calls the proper serialization method based on type.
|
9
7
|
# @param [Integer] row_index The index of the cell's row
|
10
8
|
# @param [Integer] column_index The index of the cell's column
|
11
9
|
# @param [String] str The string to apend serialization to.
|
12
10
|
# @return [String]
|
13
11
|
def to_xml_string(row_index, column_index, cell, str='')
|
14
|
-
str << '<c r="' << Axlsx::cell_r(column_index, row_index) << '" s="' << cell.style.to_s << '" '
|
12
|
+
str << ('<c r="' << Axlsx::cell_r(column_index, row_index) << '" s="' << cell.style.to_s << '" ')
|
15
13
|
return str << '/>' if cell.value.nil?
|
16
|
-
method =
|
14
|
+
method = cell.type
|
17
15
|
self.send(method, cell, str)
|
18
16
|
str << '</c>'
|
19
|
-
end
|
20
|
-
|
17
|
+
end
|
21
18
|
|
22
19
|
# builds an xml text run based on this cells attributes.
|
23
20
|
# @param [String] str The string instance this run will be concated to.
|
24
21
|
# @return [String]
|
25
22
|
def run_xml_string(cell, str = '')
|
26
23
|
if cell.is_text_run?
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
str << "<rFont val='"<< cell.font_name << "'/>"
|
34
|
-
when 'color'
|
35
|
-
str << data[key].to_xml_string
|
36
|
-
else
|
37
|
-
str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
str << "</rPr>" << "<t>" << cell.value.to_s << "</t></r>"
|
24
|
+
valid = RichTextRun::INLINE_STYLES - [:value, :type]
|
25
|
+
data = Hash[cell.instance_values.map{ |k, v| [k.to_sym, v] }]
|
26
|
+
data = data.select { |key, value| valid.include?(key) && !value.nil? }
|
27
|
+
RichText.new(cell.value.to_s, data).to_xml_string(str)
|
28
|
+
elsif cell.contains_rich_text?
|
29
|
+
cell.value.to_xml_string(str)
|
41
30
|
else
|
42
|
-
str <<
|
31
|
+
str << ('<t>' << cell.clean_value << '</t>')
|
43
32
|
end
|
44
33
|
str
|
45
34
|
end
|
@@ -48,16 +37,15 @@ module Axlsx
|
|
48
37
|
# @param [Cell] cell The cell that is being serialized
|
49
38
|
# @param [String] str The string the serialized content will be appended to.
|
50
39
|
# @return [String]
|
51
|
-
def
|
40
|
+
def iso_8601(cell, str='')
|
52
41
|
value_serialization 'd', cell.value, str
|
53
42
|
end
|
54
43
|
|
55
|
-
|
56
44
|
# serializes cells that are type date
|
57
45
|
# @param [Cell] cell The cell that is being serialized
|
58
46
|
# @param [String] str The string the serialized content will be appended to.
|
59
47
|
# @return [String]
|
60
|
-
def
|
48
|
+
def date(cell, str='')
|
61
49
|
value_serialization false, DateTimeConverter::date_to_serial(cell.value).to_s, str
|
62
50
|
end
|
63
51
|
|
@@ -65,7 +53,7 @@ module Axlsx
|
|
65
53
|
# @param [Cell] cell The cell that is being serialized
|
66
54
|
# @param [String] str The string the serialized content will be appended to.
|
67
55
|
# @return [String]
|
68
|
-
def
|
56
|
+
def time(cell, str='')
|
69
57
|
value_serialization false, DateTimeConverter::time_to_serial(cell.value).to_s, str
|
70
58
|
end
|
71
59
|
|
@@ -73,7 +61,7 @@ module Axlsx
|
|
73
61
|
# @param [Cell] cell The cell that is being serialized
|
74
62
|
# @param [String] str The string the serialized content will be appended to.
|
75
63
|
# @return [String]
|
76
|
-
def
|
64
|
+
def boolean(cell, str='')
|
77
65
|
value_serialization 'b', cell.value.to_s, str
|
78
66
|
end
|
79
67
|
|
@@ -81,26 +69,34 @@ module Axlsx
|
|
81
69
|
# @param [Cell] cell The cell that is being serialized
|
82
70
|
# @param [String] str The string the serialized content will be appended to.
|
83
71
|
# @return [String]
|
84
|
-
def
|
85
|
-
|
72
|
+
def float(cell, str='')
|
73
|
+
numeric cell, str
|
86
74
|
end
|
87
75
|
|
88
76
|
# Serializes cells that are type integer
|
89
77
|
# @param [Cell] cell The cell that is being serialized
|
90
78
|
# @param [String] str The string the serialized content will be appended to.
|
91
79
|
# @return [String]
|
92
|
-
def
|
93
|
-
|
80
|
+
def integer(cell, str = '')
|
81
|
+
numeric cell, str
|
94
82
|
end
|
95
83
|
|
96
|
-
|
97
84
|
# Serializes cells that are type formula
|
98
85
|
# @param [Cell] cell The cell that is being serialized
|
99
86
|
# @param [String] str The string the serialized content will be appended to.
|
100
87
|
# @return [String]
|
101
88
|
def formula_serialization(cell, str='')
|
102
|
-
str << 't="str"
|
103
|
-
str << '<v>' << cell.formula_value.to_s << '</v>' unless cell.formula_value.nil?
|
89
|
+
str << ('t="str"><f>' << cell.clean_value.to_s.sub('=', '') << '</f>')
|
90
|
+
str << ('<v>' << cell.formula_value.to_s << '</v>') unless cell.formula_value.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Serializes cells that are type array formula
|
94
|
+
# @param [Cell] cell The cell that is being serialized
|
95
|
+
# @param [String] str The string the serialized content will be appended to.
|
96
|
+
# @return [String]
|
97
|
+
def array_formula_serialization(cell, str='')
|
98
|
+
str << ('t="str">' << '<f t="array" ref="' << cell.r << '">' << cell.clean_value.to_s.sub('{=', '').sub(/}$/, '') << '</f>')
|
99
|
+
str << ('<v>' << cell.formula_value.to_s << '</v>') unless cell.formula_value.nil?
|
104
100
|
end
|
105
101
|
|
106
102
|
# Serializes cells that are type inline_string
|
@@ -108,7 +104,7 @@ module Axlsx
|
|
108
104
|
# @param [String] str The string the serialized content will be appended to.
|
109
105
|
# @return [String]
|
110
106
|
def inline_string_serialization(cell, str = '')
|
111
|
-
str << 't="inlineStr"
|
107
|
+
str << 't="inlineStr"><is>'
|
112
108
|
run_xml_string cell, str
|
113
109
|
str << '</is>'
|
114
110
|
end
|
@@ -117,28 +113,52 @@ module Axlsx
|
|
117
113
|
# @param [Cell] cell The cell that is being serialized
|
118
114
|
# @param [String] str The string the serialized content will be appended to.
|
119
115
|
# @return [String]
|
120
|
-
def
|
121
|
-
if cell.
|
116
|
+
def string(cell, str='')
|
117
|
+
if cell.is_array_formula?
|
118
|
+
array_formula_serialization cell, str
|
119
|
+
elsif cell.is_formula?
|
122
120
|
formula_serialization cell, str
|
123
121
|
elsif !cell.ssti.nil?
|
124
|
-
value_serialization 's', cell.ssti
|
122
|
+
value_serialization 's', cell.ssti, str
|
125
123
|
else
|
126
124
|
inline_string_serialization cell, str
|
127
125
|
end
|
128
126
|
end
|
129
127
|
|
128
|
+
# Serializes cells that are of the type richtext
|
129
|
+
# @param [Cell] cell The cell that is being serialized
|
130
|
+
# @param [String] str The string the serialized content will be appended to.
|
131
|
+
# @return [String]
|
132
|
+
def richtext(cell, str)
|
133
|
+
if cell.ssti.nil?
|
134
|
+
inline_string_serialization cell, str
|
135
|
+
else
|
136
|
+
value_serialization 's', cell.ssti, str
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Serializes cells that are of the type text
|
141
|
+
# @param [Cell] cell The cell that is being serialized
|
142
|
+
# @param [String] str The string the serialized content will be appended to.
|
143
|
+
# @return [String]
|
144
|
+
def text(cell, str)
|
145
|
+
if cell.ssti.nil?
|
146
|
+
inline_string_serialization cell, str
|
147
|
+
else
|
148
|
+
value_serialization 's', cell.ssti, str
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
130
152
|
private
|
131
153
|
|
132
|
-
def
|
133
|
-
value_serialization 'n', cell.value
|
154
|
+
def numeric(cell, str = '')
|
155
|
+
value_serialization 'n', cell.value, str
|
134
156
|
end
|
135
157
|
|
136
158
|
def value_serialization(serialization_type, serialization_value, str = '')
|
137
|
-
str << 't="' << serialization_type << '"' if serialization_type
|
138
|
-
str << '><v>' << serialization_value << '</v>'
|
159
|
+
str << ('t="' << serialization_type.to_s << '"') if serialization_type
|
160
|
+
str << ('><v>' << serialization_value.to_s << '</v>')
|
139
161
|
end
|
140
|
-
|
141
|
-
|
142
162
|
end
|
143
163
|
end
|
144
164
|
end
|
@@ -8,8 +8,11 @@ module Axlsx
|
|
8
8
|
super(Cfvo)
|
9
9
|
end
|
10
10
|
|
11
|
+
# Serialize the Cfvo object
|
12
|
+
# @param [String] str
|
13
|
+
# @return [String]
|
11
14
|
def to_xml_string(str='')
|
12
|
-
|
15
|
+
each { |cfvo| cfvo.to_xml_string(str) }
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -122,22 +122,19 @@ module Axlsx
|
|
122
122
|
# @param [Boolean] use_autowidth If this is false, the cell's
|
123
123
|
# autowidth value will be ignored.
|
124
124
|
def update_width(cell, fixed_width=nil, use_autowidth=true)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
125
|
+
if fixed_width.is_a? Numeric
|
126
|
+
self.width = fixed_width
|
127
|
+
elsif use_autowidth
|
128
|
+
cell_width = cell.autowidth
|
129
|
+
self.width = cell_width unless (width || 0) > (cell_width || 0)
|
130
|
+
end
|
132
131
|
end
|
133
132
|
|
134
133
|
# Serialize this columns data to an xml string
|
135
134
|
# @param [String] str
|
136
135
|
# @return [String]
|
137
136
|
def to_xml_string(str = '')
|
138
|
-
|
139
|
-
serialized_attributes str
|
140
|
-
str << '/>'
|
137
|
+
serialized_tag('col', str)
|
141
138
|
end
|
142
139
|
|
143
140
|
end
|
@@ -16,7 +16,7 @@ module Axlsx
|
|
16
16
|
# Break will be passed to the created break object.
|
17
17
|
# @see Break
|
18
18
|
def add_break(options)
|
19
|
-
|
19
|
+
self << Break.new(options.merge(:max => 1048575, :man => true))
|
20
20
|
last
|
21
21
|
end
|
22
22
|
|
@@ -27,7 +27,7 @@ module Axlsx
|
|
27
27
|
# </colBreaks>
|
28
28
|
def to_xml_string(str='')
|
29
29
|
return if empty?
|
30
|
-
str << '<colBreaks count="' <<
|
30
|
+
str << ('<colBreaks count="' << size.to_s << '" manualBreakCount="' << size.to_s << '">')
|
31
31
|
each { |brk| brk.to_xml_string(str) }
|
32
32
|
str << '</colBreaks>'
|
33
33
|
end
|