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
|
@@ -60,10 +60,16 @@ module Axlsx
|
|
|
60
60
|
|
|
61
61
|
#
|
|
62
62
|
# @see height
|
|
63
|
-
def height=(v)
|
|
63
|
+
def height=(v)
|
|
64
|
+
Axlsx.validate_unsigned_int(v)
|
|
65
|
+
@height = v
|
|
66
|
+
end
|
|
64
67
|
|
|
65
68
|
# @see width
|
|
66
|
-
def width=(v)
|
|
69
|
+
def width=(v)
|
|
70
|
+
Axlsx.validate_unsigned_int(v)
|
|
71
|
+
@width = v
|
|
72
|
+
end
|
|
67
73
|
|
|
68
74
|
# The index of this anchor in the drawing
|
|
69
75
|
# @return [Integer]
|
data/lib/axlsx/drawing/pic.rb
CHANGED
|
@@ -69,7 +69,7 @@ module Axlsx
|
|
|
69
69
|
options[:href] = v
|
|
70
70
|
if hyperlink.is_a?(Hyperlink)
|
|
71
71
|
options.each do |o|
|
|
72
|
-
hyperlink.send("#{o[0]}=", o[1]) if hyperlink.respond_to? "#{o[0]}="
|
|
72
|
+
hyperlink.send(:"#{o[0]}=", o[1]) if hyperlink.respond_to? :"#{o[0]}="
|
|
73
73
|
end
|
|
74
74
|
else
|
|
75
75
|
@hyperlink = Hyperlink.new(self, options)
|
|
@@ -80,7 +80,7 @@ module Axlsx
|
|
|
80
80
|
def image_src=(v)
|
|
81
81
|
Axlsx.validate_string(v)
|
|
82
82
|
if remote?
|
|
83
|
-
RegexValidator.validate('Pic.image_src', /\A#{
|
|
83
|
+
RegexValidator.validate('Pic.image_src', /\A#{Axlsx.uri_parser.make_regexp}\z/, v)
|
|
84
84
|
RestrictionValidator.validate 'Pic.image_src', ALLOWED_MIME_TYPES, MimeTypeUtils.get_mime_type_from_uri(v)
|
|
85
85
|
else
|
|
86
86
|
RestrictionValidator.validate 'Pic.image_src', ALLOWED_MIME_TYPES, MimeTypeUtils.get_mime_type(v)
|
|
@@ -91,13 +91,22 @@ module Axlsx
|
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
# @see name
|
|
94
|
-
def name=(v)
|
|
94
|
+
def name=(v)
|
|
95
|
+
Axlsx.validate_string(v)
|
|
96
|
+
@name = v
|
|
97
|
+
end
|
|
95
98
|
|
|
96
99
|
# @see descr
|
|
97
|
-
def descr=(v)
|
|
100
|
+
def descr=(v)
|
|
101
|
+
Axlsx.validate_string(v)
|
|
102
|
+
@descr = v
|
|
103
|
+
end
|
|
98
104
|
|
|
99
105
|
# @see remote
|
|
100
|
-
def remote=(v)
|
|
106
|
+
def remote=(v)
|
|
107
|
+
Axlsx.validate_boolean(v)
|
|
108
|
+
@remote = v
|
|
109
|
+
end
|
|
101
110
|
|
|
102
111
|
def remote?
|
|
103
112
|
remote == 1 || remote.to_s == 'true'
|
|
@@ -109,7 +118,7 @@ module Axlsx
|
|
|
109
118
|
File.basename(image_src) unless remote? || image_src.nil?
|
|
110
119
|
end
|
|
111
120
|
|
|
112
|
-
# returns the extension of image_src without the
|
|
121
|
+
# returns the extension of image_src without the preceding '.'
|
|
113
122
|
# @return [String]
|
|
114
123
|
def extname
|
|
115
124
|
File.extname(image_src).delete('.') unless image_src.nil?
|
|
@@ -213,9 +222,9 @@ module Axlsx
|
|
|
213
222
|
# Return correct xml relationship string portion
|
|
214
223
|
def relationship_xml_portion
|
|
215
224
|
if remote?
|
|
216
|
-
(+'<a:blip xmlns:r
|
|
225
|
+
(+'<a:blip xmlns:r="' << XML_NS_R << '" r:link="' << relationship.Id << '">')
|
|
217
226
|
else
|
|
218
|
-
(+'<a:blip xmlns:r
|
|
227
|
+
(+'<a:blip xmlns:r="' << XML_NS_R << '" r:embed="' << relationship.Id << '">')
|
|
219
228
|
end
|
|
220
229
|
end
|
|
221
230
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Axlsx
|
|
4
|
-
# The Pie3DChart is a three
|
|
4
|
+
# The Pie3DChart is a three dimensional pie chart (who would have guessed?) that you can add to your worksheet.
|
|
5
5
|
# @see Worksheet#add_chart
|
|
6
6
|
# @see Chart#add_series
|
|
7
7
|
# @see README for an example
|
|
@@ -22,7 +22,7 @@ module Axlsx
|
|
|
22
22
|
# @see View3D
|
|
23
23
|
def initialize(frame, options = {})
|
|
24
24
|
@vary_colors = true
|
|
25
|
-
super
|
|
25
|
+
super
|
|
26
26
|
@series_type = PieSeries
|
|
27
27
|
@view_3D = View3D.new({ rot_x: 30, perspective: 30 }.merge(options))
|
|
28
28
|
@d_lbls = nil
|
|
@@ -32,7 +32,7 @@ module Axlsx
|
|
|
32
32
|
# @param [String] str
|
|
33
33
|
# @return [String]
|
|
34
34
|
def to_xml_string(str = +'')
|
|
35
|
-
super
|
|
35
|
+
super do
|
|
36
36
|
str << '<c:pie3DChart>'
|
|
37
37
|
str << '<c:varyColors val="' << vary_colors.to_s << '"/>'
|
|
38
38
|
@series.each { |ser| ser.to_xml_string(str) }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Axlsx
|
|
4
|
+
# The PieChart is a pie chart that you can add to your worksheet.
|
|
5
|
+
# @see Worksheet#add_chart
|
|
6
|
+
# @see Chart#add_series
|
|
7
|
+
# @see README for an example
|
|
8
|
+
class PieChart < Chart
|
|
9
|
+
# Creates a new pie chart object
|
|
10
|
+
# @param [GraphicFrame] frame The workbook that owns this chart.
|
|
11
|
+
# @option options [Cell, String] title
|
|
12
|
+
# @option options [Boolean] show_legend
|
|
13
|
+
# @option options [Symbol] grouping
|
|
14
|
+
# @option options [String] gap_depth
|
|
15
|
+
# @see Chart
|
|
16
|
+
def initialize(frame, options = {})
|
|
17
|
+
@vary_colors = true
|
|
18
|
+
super
|
|
19
|
+
@series_type = PieSeries
|
|
20
|
+
@d_lbls = nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Serializes the object
|
|
24
|
+
# @param [String] str
|
|
25
|
+
# @return [String]
|
|
26
|
+
def to_xml_string(str = +'')
|
|
27
|
+
super do
|
|
28
|
+
str << '<c:pieChart>'
|
|
29
|
+
str << '<c:varyColors val="' << vary_colors.to_s << '"/>'
|
|
30
|
+
@series.each { |ser| ser.to_xml_string(str) }
|
|
31
|
+
d_lbls.to_xml_string(str) if @d_lbls
|
|
32
|
+
str << '</c:pieChart>'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -30,22 +30,28 @@ module Axlsx
|
|
|
30
30
|
def initialize(chart, options = {})
|
|
31
31
|
@explosion = nil
|
|
32
32
|
@colors = []
|
|
33
|
-
super
|
|
33
|
+
super
|
|
34
34
|
self.labels = AxDataSource.new(data: options[:labels]) unless options[:labels].nil?
|
|
35
35
|
self.data = NumDataSource.new(options) unless options[:data].nil?
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# @see colors
|
|
39
|
-
def colors=(v)
|
|
39
|
+
def colors=(v)
|
|
40
|
+
DataTypeValidator.validate "BarSeries.colors", [Array], v
|
|
41
|
+
@colors = v
|
|
42
|
+
end
|
|
40
43
|
|
|
41
44
|
# @see explosion
|
|
42
|
-
def explosion=(v)
|
|
45
|
+
def explosion=(v)
|
|
46
|
+
Axlsx.validate_unsigned_int(v)
|
|
47
|
+
@explosion = v
|
|
48
|
+
end
|
|
43
49
|
|
|
44
50
|
# Serializes the object
|
|
45
51
|
# @param [String] str
|
|
46
52
|
# @return [String]
|
|
47
53
|
def to_xml_string(str = +'')
|
|
48
|
-
super
|
|
54
|
+
super do
|
|
49
55
|
str << '<c:explosion val="' << @explosion.to_s << '"/>' unless @explosion.nil?
|
|
50
56
|
colors.each_with_index do |c, index|
|
|
51
57
|
str << '<c:dPt>'
|
|
@@ -63,9 +69,15 @@ module Axlsx
|
|
|
63
69
|
private
|
|
64
70
|
|
|
65
71
|
# assigns the data for this series
|
|
66
|
-
def data=(v)
|
|
72
|
+
def data=(v)
|
|
73
|
+
DataTypeValidator.validate "Series.data", [NumDataSource], v
|
|
74
|
+
@data = v
|
|
75
|
+
end
|
|
67
76
|
|
|
68
77
|
# assigns the labels for this series
|
|
69
|
-
def labels=(v)
|
|
78
|
+
def labels=(v)
|
|
79
|
+
DataTypeValidator.validate "Series.labels", [AxDataSource], v
|
|
80
|
+
@labels = v
|
|
81
|
+
end
|
|
70
82
|
end
|
|
71
83
|
end
|
|
@@ -35,14 +35,28 @@ module Axlsx
|
|
|
35
35
|
attr_reader :min
|
|
36
36
|
|
|
37
37
|
# @see logBase
|
|
38
|
-
def logBase=(v)
|
|
38
|
+
def logBase=(v)
|
|
39
|
+
DataTypeValidator.validate "Scaling.logBase", [Integer], v, ->(arg) { arg >= 2 && arg <= 1000 }
|
|
40
|
+
@logBase = v
|
|
41
|
+
end
|
|
42
|
+
|
|
39
43
|
# @see orientation
|
|
40
|
-
def orientation=(v)
|
|
44
|
+
def orientation=(v)
|
|
45
|
+
RestrictionValidator.validate "Scaling.orientation", [:minMax, :maxMin], v
|
|
46
|
+
@orientation = v
|
|
47
|
+
end
|
|
48
|
+
|
|
41
49
|
# @see max
|
|
42
|
-
def max=(v)
|
|
50
|
+
def max=(v)
|
|
51
|
+
DataTypeValidator.validate "Scaling.max", Float, v
|
|
52
|
+
@max = v
|
|
53
|
+
end
|
|
43
54
|
|
|
44
55
|
# @see min
|
|
45
|
-
def min=(v)
|
|
56
|
+
def min=(v)
|
|
57
|
+
DataTypeValidator.validate "Scaling.min", Float, v
|
|
58
|
+
@min = v
|
|
59
|
+
end
|
|
46
60
|
|
|
47
61
|
# Serializes the object
|
|
48
62
|
# @param [String] str
|
|
@@ -33,7 +33,7 @@ module Axlsx
|
|
|
33
33
|
@vary_colors = 0
|
|
34
34
|
@scatter_style = :lineMarker
|
|
35
35
|
|
|
36
|
-
super
|
|
36
|
+
super
|
|
37
37
|
@series_type = ScatterSeries
|
|
38
38
|
@d_lbls = nil
|
|
39
39
|
parse_options options
|
|
@@ -50,7 +50,7 @@ module Axlsx
|
|
|
50
50
|
# @param [String] str
|
|
51
51
|
# @return [String]
|
|
52
52
|
def to_xml_string(str = +'')
|
|
53
|
-
super
|
|
53
|
+
super do
|
|
54
54
|
str << '<c:scatterChart>'
|
|
55
55
|
str << '<c:scatterStyle val="' << scatter_style.to_s << '"/>'
|
|
56
56
|
str << '<c:varyColors val="' << vary_colors.to_s << '"/>'
|
|
@@ -50,7 +50,7 @@ module Axlsx
|
|
|
50
50
|
@show_marker = [:lineMarker, :marker, :smoothMarker].include?(chart.scatter_style)
|
|
51
51
|
@marker_symbol = :default
|
|
52
52
|
|
|
53
|
-
super
|
|
53
|
+
super
|
|
54
54
|
@xData = AxDataSource.new(tag_name: :xVal, data: options[:xData]) unless options[:xData].nil?
|
|
55
55
|
@yData = NumDataSource.new({ tag_name: :yVal, data: options[:yData] }) unless options[:yData].nil?
|
|
56
56
|
end
|
|
@@ -81,7 +81,7 @@ module Axlsx
|
|
|
81
81
|
# @param [String] str
|
|
82
82
|
# @return [String]
|
|
83
83
|
def to_xml_string(str = +'')
|
|
84
|
-
super
|
|
84
|
+
super do
|
|
85
85
|
# needs to override the super color here to push in ln/and something else!
|
|
86
86
|
if color
|
|
87
87
|
str << '<c:spPr><a:solidFill>'
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Axlsx
|
|
4
4
|
# A SerAxis object defines a series axis
|
|
5
5
|
class SerAxis < Axis
|
|
6
|
-
# The number of tick
|
|
6
|
+
# The number of tick labels to skip between labels
|
|
7
7
|
# @return [Integer]
|
|
8
8
|
attr_reader :tick_lbl_skip
|
|
9
9
|
alias :tickLblSkip :tick_lbl_skip
|
|
@@ -18,15 +18,21 @@ module Axlsx
|
|
|
18
18
|
# @option options [Integer] tick_mark_skip
|
|
19
19
|
def initialize(options = {})
|
|
20
20
|
@tick_lbl_skip, @tick_mark_skip = 1, 1
|
|
21
|
-
super
|
|
21
|
+
super
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# @see tickLblSkip
|
|
25
|
-
def tick_lbl_skip=(v)
|
|
25
|
+
def tick_lbl_skip=(v)
|
|
26
|
+
Axlsx.validate_unsigned_int(v)
|
|
27
|
+
@tick_lbl_skip = v
|
|
28
|
+
end
|
|
26
29
|
alias :tickLblSkip= :tick_lbl_skip=
|
|
27
30
|
|
|
28
31
|
# @see tickMarkSkip
|
|
29
|
-
def tick_mark_skip=(v)
|
|
32
|
+
def tick_mark_skip=(v)
|
|
33
|
+
Axlsx.validate_unsigned_int(v)
|
|
34
|
+
@tick_mark_skip = v
|
|
35
|
+
end
|
|
30
36
|
alias :tickMarkSkip= :tick_mark_skip=
|
|
31
37
|
|
|
32
38
|
# Serializes the object
|
|
@@ -34,7 +40,7 @@ module Axlsx
|
|
|
34
40
|
# @return [String]
|
|
35
41
|
def to_xml_string(str = +'')
|
|
36
42
|
str << '<c:serAx>'
|
|
37
|
-
super
|
|
43
|
+
super
|
|
38
44
|
str << '<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>' unless @tick_lbl_skip.nil?
|
|
39
45
|
str << '<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>' unless @tick_mark_skip.nil?
|
|
40
46
|
str << '</c:serAx>'
|
data/lib/axlsx/drawing/series.rb
CHANGED
|
@@ -40,7 +40,10 @@ module Axlsx
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
# @see order
|
|
43
|
-
def order=(v)
|
|
43
|
+
def order=(v)
|
|
44
|
+
Axlsx.validate_unsigned_int(v)
|
|
45
|
+
@order = v
|
|
46
|
+
end
|
|
44
47
|
|
|
45
48
|
# @see title
|
|
46
49
|
def title=(v)
|
|
@@ -52,7 +55,10 @@ module Axlsx
|
|
|
52
55
|
private
|
|
53
56
|
|
|
54
57
|
# assigns the chart for this series
|
|
55
|
-
def chart=(v)
|
|
58
|
+
def chart=(v)
|
|
59
|
+
DataTypeValidator.validate "Series.chart", Chart, v
|
|
60
|
+
@chart = v
|
|
61
|
+
end
|
|
56
62
|
|
|
57
63
|
# Serializes the object
|
|
58
64
|
# @param [String] str
|
|
@@ -39,7 +39,7 @@ module Axlsx
|
|
|
39
39
|
parse_options options
|
|
40
40
|
|
|
41
41
|
# bit of a hack to work around the fact that the coords for start at and end at
|
|
42
|
-
# are passed in as an array when specified in
|
|
42
|
+
# are passed in as an array when specified in initialization options - however
|
|
43
43
|
start_at(*options[:start_at]) if options[:start_at]
|
|
44
44
|
end_at(*options[:end_at]) if options[:end_at]
|
|
45
45
|
end
|
|
@@ -13,7 +13,7 @@ module Axlsx
|
|
|
13
13
|
# @option options [Symbol] crosses_between
|
|
14
14
|
def initialize(options = {})
|
|
15
15
|
self.cross_between = :between
|
|
16
|
-
super
|
|
16
|
+
super
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# @see cross_between
|
|
@@ -28,7 +28,7 @@ module Axlsx
|
|
|
28
28
|
# @return [String]
|
|
29
29
|
def to_xml_string(str = +'')
|
|
30
30
|
str << '<c:valAx>'
|
|
31
|
-
super
|
|
31
|
+
super
|
|
32
32
|
str << '<c:crossBetween val="' << @cross_between.to_s << '"/>'
|
|
33
33
|
str << '</c:valAx>'
|
|
34
34
|
end
|
|
@@ -78,11 +78,17 @@ module Axlsx
|
|
|
78
78
|
alias :rotY= :rot_y=
|
|
79
79
|
|
|
80
80
|
# @see depth_percent
|
|
81
|
-
def depth_percent=(v)
|
|
81
|
+
def depth_percent=(v)
|
|
82
|
+
RegexValidator.validate "#{self.class}.depth_percent", DEPTH_PERCENT_REGEX, v
|
|
83
|
+
@depth_percent = v
|
|
84
|
+
end
|
|
82
85
|
alias :depthPercent= :depth_percent=
|
|
83
86
|
|
|
84
87
|
# @see r_ang_ax
|
|
85
|
-
def r_ang_ax=(v)
|
|
88
|
+
def r_ang_ax=(v)
|
|
89
|
+
Axlsx.validate_boolean(v)
|
|
90
|
+
@r_ang_ax = v
|
|
91
|
+
end
|
|
86
92
|
alias :rAngAx= :r_ang_ax=
|
|
87
93
|
|
|
88
94
|
# @see perspective
|
data/lib/axlsx/package.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Axlsx
|
|
4
|
-
# Package is responsible for managing all the bits and
|
|
4
|
+
# Package is responsible for managing all the bits and pieces that Open Office XML requires to make a valid
|
|
5
5
|
# xlsx document including validation and serialization.
|
|
6
6
|
class Package
|
|
7
7
|
include Axlsx::OptionsParser
|
|
@@ -55,11 +55,11 @@ module Axlsx
|
|
|
55
55
|
# @raise ArgumentError if workbook parameter is not a Workbook instance.
|
|
56
56
|
# @note As there are multiple ways to instantiate a workbook for the package,
|
|
57
57
|
# here are a few examples:
|
|
58
|
-
# # assign directly during package
|
|
58
|
+
# # assign directly during package instantiation
|
|
59
59
|
# wb = Package.new(:workbook => Workbook.new).workbook
|
|
60
60
|
#
|
|
61
61
|
# # get a fresh workbook automatically from the package
|
|
62
|
-
# wb =
|
|
62
|
+
# wb = Package.new().workbook
|
|
63
63
|
# # # set the workbook after creating the package
|
|
64
64
|
# wb = Package.new().workbook = Workbook.new
|
|
65
65
|
def workbook
|
|
@@ -69,7 +69,10 @@ module Axlsx
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# @see workbook
|
|
72
|
-
def workbook=(workbook)
|
|
72
|
+
def workbook=(workbook)
|
|
73
|
+
DataTypeValidator.validate :Package_workbook, Workbook, workbook
|
|
74
|
+
@workbook = workbook
|
|
75
|
+
end
|
|
73
76
|
|
|
74
77
|
# Serialize your workbook to disk as an xlsx document.
|
|
75
78
|
#
|
|
@@ -79,6 +82,8 @@ module Axlsx
|
|
|
79
82
|
# @option options [String] :zip_command When `nil`, `#serialize` with RubyZip to
|
|
80
83
|
# zip the XLSX file contents. When a String, the provided zip command (e.g.,
|
|
81
84
|
# "zip") is used to zip the file contents (may be faster for large files)
|
|
85
|
+
# @option options [String] :password When specified, the serialized packaged will be
|
|
86
|
+
# encrypted with the password. Requires ooxml_crypt gem.
|
|
82
87
|
# @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
|
|
83
88
|
# @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
|
|
84
89
|
# options[:confirm_valid] should be used in the rare case that you cannot open the serialized file.
|
|
@@ -105,7 +110,7 @@ module Axlsx
|
|
|
105
110
|
workbook.apply_styles
|
|
106
111
|
end
|
|
107
112
|
|
|
108
|
-
confirm_valid, zip_command = parse_serialize_options(options, secondary_options)
|
|
113
|
+
confirm_valid, zip_command, password = parse_serialize_options(options, secondary_options)
|
|
109
114
|
return false unless !confirm_valid || validate.empty?
|
|
110
115
|
|
|
111
116
|
zip_provider = if zip_command
|
|
@@ -117,15 +122,31 @@ module Axlsx
|
|
|
117
122
|
zip_provider.open(output) do |zip|
|
|
118
123
|
write_parts(zip)
|
|
119
124
|
end
|
|
125
|
+
|
|
126
|
+
if password && !password.empty?
|
|
127
|
+
require_ooxml_crypt!
|
|
128
|
+
OoxmlCrypt.encrypt_file(output, password, output)
|
|
129
|
+
end
|
|
130
|
+
|
|
120
131
|
true
|
|
121
132
|
ensure
|
|
122
133
|
Relationship.clear_ids_cache
|
|
123
134
|
end
|
|
124
135
|
|
|
125
136
|
# Serialize your workbook to a StringIO instance
|
|
126
|
-
# @param [Boolean]
|
|
127
|
-
#
|
|
128
|
-
|
|
137
|
+
# @param [Boolean] old_confirm_valid (Deprecated) Validate the package prior to serialization.
|
|
138
|
+
# Use :confirm_valid keyword arg instead.
|
|
139
|
+
# @option kwargs [Boolean] :confirm_valid Validate the package prior to serialization.
|
|
140
|
+
# @option kwargs [String] :password When specified, the serialized packaged will be
|
|
141
|
+
# encrypted with the password. Requires ooxml_crypt gem.
|
|
142
|
+
# @return [StringIO|Boolean] False if confirm_valid and validation errors exist. Rewound string IO if not.
|
|
143
|
+
def to_stream(old_confirm_valid = nil, confirm_valid: false, password: nil)
|
|
144
|
+
unless old_confirm_valid.nil?
|
|
145
|
+
warn "[DEPRECATION] Axlsx::Package#to_stream with confirm_valid as a non-keyword arg is deprecated. " \
|
|
146
|
+
"Use keyword arg instead e.g., package.to_stream(confirm_valid: false)"
|
|
147
|
+
confirm_valid ||= old_confirm_valid
|
|
148
|
+
end
|
|
149
|
+
|
|
129
150
|
unless workbook.styles_applied
|
|
130
151
|
workbook.apply_styles
|
|
131
152
|
end
|
|
@@ -137,6 +158,12 @@ module Axlsx
|
|
|
137
158
|
write_parts(zip)
|
|
138
159
|
end
|
|
139
160
|
stream.rewind
|
|
161
|
+
|
|
162
|
+
if password && !password.empty?
|
|
163
|
+
require_ooxml_crypt!
|
|
164
|
+
stream = StringIO.new(OoxmlCrypt.encrypt(stream.read, password))
|
|
165
|
+
end
|
|
166
|
+
|
|
140
167
|
stream
|
|
141
168
|
ensure
|
|
142
169
|
Relationship.clear_ids_cache
|
|
@@ -144,7 +171,7 @@ module Axlsx
|
|
|
144
171
|
|
|
145
172
|
# Encrypt the package into a CFB using the password provided
|
|
146
173
|
# This is not ready yet
|
|
147
|
-
def encrypt(file_name, password)
|
|
174
|
+
def encrypt(file_name, password) # rubocop:disable Naming/PredicateMethod
|
|
148
175
|
false
|
|
149
176
|
# moc = MsOffCrypto.new(file_name, password)
|
|
150
177
|
# moc.save
|
|
@@ -204,11 +231,12 @@ module Axlsx
|
|
|
204
231
|
# Note: {Core#created} also defaults to the current time – so to generate identical axlsx packages you have
|
|
205
232
|
# to set this explicitly, too (eg. with `Package.new(created_at: Time.local(2013, 1, 1))`).
|
|
206
233
|
#
|
|
207
|
-
# @param part A hash describing a part of this
|
|
234
|
+
# @param part A hash describing a part of this package (see {#parts})
|
|
208
235
|
# @return [Zip::Entry]
|
|
209
236
|
def zip_entry_for_part(part)
|
|
210
237
|
timestamp = Zip::DOSTime.at(@core.created.to_i)
|
|
211
|
-
|
|
238
|
+
|
|
239
|
+
Zip::Entry.new("", part[:entry], time: timestamp)
|
|
212
240
|
end
|
|
213
241
|
|
|
214
242
|
# The parts of a package
|
|
@@ -217,6 +245,7 @@ module Axlsx
|
|
|
217
245
|
def parts
|
|
218
246
|
parts = [
|
|
219
247
|
{ entry: "xl/#{STYLES_PN}", doc: workbook.styles, schema: SML_XSD },
|
|
248
|
+
{ entry: "xl/#{THEME_PN}", doc: workbook.theme, schema: THEME_XSD },
|
|
220
249
|
{ entry: CORE_PN, doc: @core, schema: CORE_XSD },
|
|
221
250
|
{ entry: APP_PN, doc: @app, schema: APP_XSD },
|
|
222
251
|
{ entry: WORKBOOK_RELS_PN, doc: workbook.relationships, schema: RELS_XSD },
|
|
@@ -270,7 +299,7 @@ module Axlsx
|
|
|
270
299
|
]
|
|
271
300
|
end
|
|
272
301
|
|
|
273
|
-
# Performs xsd validation for a
|
|
302
|
+
# Performs xsd validation for a single document
|
|
274
303
|
#
|
|
275
304
|
# @param [String] schema path to the xsd schema to be used in validation.
|
|
276
305
|
# @param [String] doc The xml text to be validated
|
|
@@ -279,11 +308,8 @@ module Axlsx
|
|
|
279
308
|
def validate_single_doc(schema, doc)
|
|
280
309
|
schema = Nokogiri::XML::Schema(File.open(schema))
|
|
281
310
|
doc = Nokogiri::XML(doc)
|
|
282
|
-
|
|
283
|
-
schema.validate(doc)
|
|
284
|
-
errors << error
|
|
285
|
-
end
|
|
286
|
-
errors
|
|
311
|
+
|
|
312
|
+
schema.validate(doc)
|
|
287
313
|
end
|
|
288
314
|
|
|
289
315
|
# Appends override objects for drawings, charts, and sheets as they exist in your workbook to the default content types.
|
|
@@ -356,6 +382,7 @@ module Axlsx
|
|
|
356
382
|
c_types << Override.new(PartName: "/#{APP_PN}", ContentType: APP_CT)
|
|
357
383
|
c_types << Override.new(PartName: "/#{CORE_PN}", ContentType: CORE_CT)
|
|
358
384
|
c_types << Override.new(PartName: "/xl/#{STYLES_PN}", ContentType: STYLES_CT)
|
|
385
|
+
c_types << Override.new(PartName: "/xl/#{THEME_PN}", ContentType: THEME_CT)
|
|
359
386
|
c_types << Axlsx::Override.new(PartName: "/#{WORKBOOK_PN}", ContentType: WORKBOOK_CT)
|
|
360
387
|
c_types.lock
|
|
361
388
|
c_types
|
|
@@ -374,8 +401,8 @@ module Axlsx
|
|
|
374
401
|
end
|
|
375
402
|
|
|
376
403
|
# Parse the arguments of `#serialize`
|
|
377
|
-
# @return [Boolean, (String or nil)] Returns
|
|
378
|
-
# `confirm_valid` and
|
|
404
|
+
# @return [Boolean, (String or nil), (String or nil)] Returns a 3-tuple where values are
|
|
405
|
+
# `confirm_valid`, `zip_command`, and `password`.
|
|
379
406
|
# @private
|
|
380
407
|
def parse_serialize_options(options, secondary_options)
|
|
381
408
|
if secondary_options
|
|
@@ -384,17 +411,23 @@ module Axlsx
|
|
|
384
411
|
end
|
|
385
412
|
if options.is_a?(Hash)
|
|
386
413
|
options.merge!(secondary_options || {})
|
|
387
|
-
invalid_keys = options.keys - [:confirm_valid, :zip_command]
|
|
414
|
+
invalid_keys = options.keys - [:confirm_valid, :zip_command, :password]
|
|
388
415
|
if invalid_keys.any?
|
|
389
416
|
raise ArgumentError, "Invalid keyword arguments: #{invalid_keys}"
|
|
390
417
|
end
|
|
391
418
|
|
|
392
|
-
[options.fetch(:confirm_valid, false), options.fetch(:zip_command, nil)]
|
|
419
|
+
[options.fetch(:confirm_valid, false), options.fetch(:zip_command, nil), options.fetch(:password, nil)]
|
|
393
420
|
else
|
|
394
421
|
warn "[DEPRECATION] Axlsx::Package#serialize with confirm_valid as a boolean is deprecated. " \
|
|
395
422
|
"Use keyword args instead e.g., package.serialize(output, confirm_valid: false)"
|
|
396
423
|
parse_serialize_options((secondary_options || {}).merge(confirm_valid: options), nil)
|
|
397
424
|
end
|
|
398
425
|
end
|
|
426
|
+
|
|
427
|
+
def require_ooxml_crypt!
|
|
428
|
+
return if defined?(OoxmlCrypt)
|
|
429
|
+
|
|
430
|
+
raise 'Axlsx encryption requires ooxml_crypt gem'
|
|
431
|
+
end
|
|
399
432
|
end
|
|
400
433
|
end
|
|
@@ -15,7 +15,7 @@ module Axlsx
|
|
|
15
15
|
#
|
|
16
16
|
# This should be called before serializing a package (see {Package#serialize} and
|
|
17
17
|
# {Package#to_stream}) to make sure that serialization is idempotent (i.e.
|
|
18
|
-
# Relationship instances are generated with the same IDs
|
|
18
|
+
# Relationship instances are generated with the same IDs every time the package
|
|
19
19
|
# is serialized).
|
|
20
20
|
def initialize_ids_cache
|
|
21
21
|
Thread.current[:axlsx_relationship_ids_cache] = {}
|
|
@@ -92,12 +92,22 @@ module Axlsx
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# @see Target
|
|
95
|
-
def Target=(v)
|
|
95
|
+
def Target=(v)
|
|
96
|
+
Axlsx.validate_string v
|
|
97
|
+
@Target = v
|
|
98
|
+
end
|
|
99
|
+
|
|
96
100
|
# @see Type
|
|
97
|
-
def Type=(v)
|
|
101
|
+
def Type=(v)
|
|
102
|
+
Axlsx.validate_relationship_type v
|
|
103
|
+
@Type = v
|
|
104
|
+
end
|
|
98
105
|
|
|
99
106
|
# @see TargetMode
|
|
100
|
-
def TargetMode=(v)
|
|
107
|
+
def TargetMode=(v)
|
|
108
|
+
RestrictionValidator.validate 'Relationship.TargetMode', [:External, :Internal], v
|
|
109
|
+
@TargetMode = v
|
|
110
|
+
end
|
|
101
111
|
|
|
102
112
|
# serialize relationship
|
|
103
113
|
# @param [String] str
|
|
@@ -106,7 +116,7 @@ module Axlsx
|
|
|
106
116
|
h = Axlsx.instance_values_for(self).reject { |k, _| k == "source_obj" }
|
|
107
117
|
str << '<Relationship '
|
|
108
118
|
h.each_with_index do |key_value, index|
|
|
109
|
-
str << ' ' unless index
|
|
119
|
+
str << ' ' unless index == 0
|
|
110
120
|
str << key_value.first.to_s << '="' << Axlsx.coder.encode(key_value.last.to_s) << '"'
|
|
111
121
|
end
|
|
112
122
|
str << '/>'
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Axlsx
|
|
4
|
-
|
|
4
|
+
require_relative 'relationship'
|
|
5
5
|
|
|
6
6
|
# Relationships are a collection of Relations that define how package parts are related.
|
|
7
|
-
# @note The package automatically manages
|
|
7
|
+
# @note The package automatically manages relationships.
|
|
8
8
|
class Relationships < SimpleTypedList
|
|
9
9
|
# Creates a new Relationships collection based on SimpleTypedList
|
|
10
10
|
def initialize
|
|
11
|
-
super
|
|
11
|
+
super(Relationship)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# The relationship instance for the given source object, or nil if none exists.
|