caxlsx 3.4.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +9 -11
- data/Rakefile +7 -5
- data/examples/generate.rb +3 -1
- data/lib/axlsx/content_type/abstract_content_type.rb +12 -4
- data/lib/axlsx/content_type/content_type.rb +8 -6
- data/lib/axlsx/content_type/default.rb +7 -2
- data/lib/axlsx/content_type/override.rb +7 -2
- data/lib/axlsx/doc_props/app.rb +95 -26
- data/lib/axlsx/doc_props/core.rb +8 -6
- data/lib/axlsx/drawing/area_chart.rb +10 -8
- data/lib/axlsx/drawing/area_series.rb +20 -12
- data/lib/axlsx/drawing/ax_data_source.rb +2 -0
- data/lib/axlsx/drawing/axes.rb +6 -4
- data/lib/axlsx/drawing/axis.rb +42 -22
- data/lib/axlsx/drawing/bar_3D_chart.rb +14 -12
- data/lib/axlsx/drawing/bar_chart.rb +13 -11
- data/lib/axlsx/drawing/bar_series.rb +20 -9
- data/lib/axlsx/drawing/bubble_chart.rb +6 -4
- data/lib/axlsx/drawing/bubble_series.rb +8 -6
- data/lib/axlsx/drawing/cat_axis.rb +29 -12
- data/lib/axlsx/drawing/chart.rb +46 -20
- data/lib/axlsx/drawing/d_lbls.rb +10 -8
- data/lib/axlsx/drawing/drawing.rb +59 -56
- data/lib/axlsx/drawing/graphic_frame.rb +6 -4
- data/lib/axlsx/drawing/hyperlink.rb +19 -8
- data/lib/axlsx/drawing/line_3D_chart.rb +7 -5
- data/lib/axlsx/drawing/line_chart.rb +10 -8
- data/lib/axlsx/drawing/line_series.rb +20 -12
- data/lib/axlsx/drawing/marker.rb +24 -7
- data/lib/axlsx/drawing/num_data.rb +9 -7
- data/lib/axlsx/drawing/num_data_source.rb +9 -7
- data/lib/axlsx/drawing/num_val.rb +7 -5
- data/lib/axlsx/drawing/one_cell_anchor.rb +13 -5
- data/lib/axlsx/drawing/pic.rb +26 -15
- data/lib/axlsx/drawing/picture_locking.rb +3 -1
- data/lib/axlsx/drawing/pie_3D_chart.rb +6 -4
- data/lib/axlsx/drawing/pie_chart.rb +36 -0
- data/lib/axlsx/drawing/pie_series.rb +23 -9
- data/lib/axlsx/drawing/scaling.rb +25 -9
- data/lib/axlsx/drawing/scatter_chart.rb +7 -5
- data/lib/axlsx/drawing/scatter_series.rb +14 -12
- data/lib/axlsx/drawing/ser_axis.rb +13 -5
- data/lib/axlsx/drawing/series.rb +13 -5
- data/lib/axlsx/drawing/series_title.rb +6 -4
- data/lib/axlsx/drawing/str_data.rb +7 -5
- data/lib/axlsx/drawing/str_val.rb +6 -4
- data/lib/axlsx/drawing/title.rb +13 -14
- data/lib/axlsx/drawing/two_cell_anchor.rb +4 -2
- data/lib/axlsx/drawing/val_axis.rb +4 -2
- data/lib/axlsx/drawing/view_3D.rb +16 -8
- data/lib/axlsx/drawing/vml_drawing.rb +18 -16
- data/lib/axlsx/drawing/vml_shape.rb +24 -22
- data/lib/axlsx/package.rb +73 -67
- data/lib/axlsx/rels/relationship.rb +21 -6
- data/lib/axlsx/rels/relationships.rb +6 -4
- data/lib/axlsx/stylesheet/border.rb +15 -4
- data/lib/axlsx/stylesheet/border_pr.rb +19 -6
- data/lib/axlsx/stylesheet/cell_alignment.rb +41 -10
- data/lib/axlsx/stylesheet/cell_protection.rb +12 -3
- data/lib/axlsx/stylesheet/cell_style.rb +33 -8
- data/lib/axlsx/stylesheet/color.rb +15 -7
- data/lib/axlsx/stylesheet/dxf.rb +34 -9
- data/lib/axlsx/stylesheet/fill.rb +7 -2
- data/lib/axlsx/stylesheet/font.rb +65 -17
- data/lib/axlsx/stylesheet/gradient_fill.rb +12 -4
- data/lib/axlsx/stylesheet/gradient_stop.rb +14 -5
- data/lib/axlsx/stylesheet/num_fmt.rb +14 -10
- data/lib/axlsx/stylesheet/pattern_fill.rb +18 -5
- data/lib/axlsx/stylesheet/styles.rb +124 -82
- data/lib/axlsx/stylesheet/table_style.rb +19 -6
- data/lib/axlsx/stylesheet/table_style_element.rb +15 -4
- data/lib/axlsx/stylesheet/table_styles.rb +14 -5
- data/lib/axlsx/stylesheet/xf.rb +73 -18
- data/lib/axlsx/util/accessors.rb +10 -6
- data/lib/axlsx/util/buffered_zip_output_stream.rb +60 -0
- data/lib/axlsx/util/constants.rb +117 -104
- data/lib/axlsx/util/mime_type_utils.rb +3 -5
- data/lib/axlsx/util/options_parser.rb +3 -1
- data/lib/axlsx/util/serialized_attributes.rb +42 -17
- data/lib/axlsx/util/simple_typed_list.rb +47 -47
- data/lib/axlsx/util/storage.rb +11 -10
- data/lib/axlsx/util/validators.rb +101 -41
- data/lib/axlsx/util/zip_command.rb +10 -10
- data/lib/axlsx/version.rb +3 -1
- data/lib/axlsx/workbook/defined_name.rb +6 -4
- data/lib/axlsx/workbook/defined_names.rb +4 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +8 -6
- data/lib/axlsx/workbook/workbook.rb +94 -79
- data/lib/axlsx/workbook/workbook_view.rb +3 -1
- data/lib/axlsx/workbook/workbook_views.rb +4 -2
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +65 -8
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +11 -5
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +11 -7
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_condition.rb +51 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_state.rb +56 -0
- data/lib/axlsx/workbook/worksheet/border_creator.rb +5 -3
- data/lib/axlsx/workbook/worksheet/break.rb +3 -1
- data/lib/axlsx/workbook/worksheet/cell.rb +83 -64
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +31 -27
- data/lib/axlsx/workbook/worksheet/cfvo.rb +11 -3
- data/lib/axlsx/workbook/worksheet/cfvos.rb +3 -1
- data/lib/axlsx/workbook/worksheet/col.rb +5 -3
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +6 -4
- data/lib/axlsx/workbook/worksheet/color_scale.rb +12 -10
- data/lib/axlsx/workbook/worksheet/cols.rb +4 -2
- data/lib/axlsx/workbook/worksheet/comment.rb +8 -6
- data/lib/axlsx/workbook/worksheet/comments.rb +6 -4
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +16 -5
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +73 -16
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +4 -2
- data/lib/axlsx/workbook/worksheet/data_bar.rb +14 -13
- data/lib/axlsx/workbook/worksheet/data_validation.rb +69 -28
- data/lib/axlsx/workbook/worksheet/data_validations.rb +4 -2
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +7 -5
- data/lib/axlsx/workbook/worksheet/dimension.rb +4 -2
- data/lib/axlsx/workbook/worksheet/header_footer.rb +4 -2
- data/lib/axlsx/workbook/worksheet/icon_set.rb +38 -9
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +6 -6
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/page_margins.rb +39 -11
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +7 -4
- data/lib/axlsx/workbook/worksheet/page_setup.rb +34 -9
- data/lib/axlsx/workbook/worksheet/pane.rb +17 -9
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +20 -19
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +8 -6
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +3 -1
- data/lib/axlsx/workbook/worksheet/print_options.rb +3 -1
- data/lib/axlsx/workbook/worksheet/protected_range.rb +3 -1
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +6 -4
- data/lib/axlsx/workbook/worksheet/rich_text.rb +3 -1
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +46 -24
- data/lib/axlsx/workbook/worksheet/row.rb +11 -9
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +7 -5
- data/lib/axlsx/workbook/worksheet/selection.rb +15 -7
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
- data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +8 -4
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +11 -9
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +38 -15
- data/lib/axlsx/workbook/worksheet/table.rb +9 -7
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +4 -2
- data/lib/axlsx/workbook/worksheet/tables.rb +4 -2
- data/lib/axlsx/workbook/worksheet/worksheet.rb +56 -39
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +4 -2
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +8 -2
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +7 -5
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +5 -3
- data/lib/axlsx.rb +56 -42
- data/lib/caxlsx.rb +3 -1
- metadata +39 -71
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# This class specifies data for a particular data point.
|
3
5
|
class StrVal
|
@@ -21,10 +23,10 @@ module Axlsx
|
|
21
23
|
end
|
22
24
|
|
23
25
|
# serialize the object
|
24
|
-
def to_xml_string(idx, str =
|
25
|
-
Axlsx
|
26
|
-
|
27
|
-
str <<
|
26
|
+
def to_xml_string(idx, str = +'')
|
27
|
+
Axlsx.validate_unsigned_int(idx)
|
28
|
+
unless v.to_s.empty?
|
29
|
+
str << '<c:pt idx="' << idx.to_s << '"><c:v>' << ::CGI.escapeHTML(v.to_s) << '</c:v></c:pt>'
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
data/lib/axlsx/drawing/title.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# A Title stores information about the title of a chart
|
3
5
|
class Title
|
@@ -18,11 +20,11 @@ module Axlsx
|
|
18
20
|
def initialize(title = "", title_size = "")
|
19
21
|
self.cell = title if title.is_a?(Cell)
|
20
22
|
self.text = title.to_s unless title.is_a?(Cell)
|
21
|
-
if title_size.to_s.empty?
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
self.text_size = if title_size.to_s.empty?
|
24
|
+
"1600"
|
25
|
+
else
|
26
|
+
title_size.to_s
|
27
|
+
end
|
26
28
|
end
|
27
29
|
|
28
30
|
# @see text
|
@@ -30,7 +32,6 @@ module Axlsx
|
|
30
32
|
DataTypeValidator.validate 'Title.text', String, v
|
31
33
|
@text = v
|
32
34
|
@cell = nil
|
33
|
-
v
|
34
35
|
end
|
35
36
|
|
36
37
|
# @see text_size
|
@@ -38,7 +39,6 @@ module Axlsx
|
|
38
39
|
DataTypeValidator.validate 'Title.text_size', String, v
|
39
40
|
@text_size = v
|
40
41
|
@cell = nil
|
41
|
-
v
|
42
42
|
end
|
43
43
|
|
44
44
|
# @see cell
|
@@ -46,7 +46,6 @@ module Axlsx
|
|
46
46
|
DataTypeValidator.validate 'Title.text', Cell, v
|
47
47
|
@cell = v
|
48
48
|
@text = v.value.to_s
|
49
|
-
v
|
50
49
|
end
|
51
50
|
|
52
51
|
# Check if the title is empty.
|
@@ -67,18 +66,18 @@ module Axlsx
|
|
67
66
|
# Serializes the object
|
68
67
|
# @param [String] str
|
69
68
|
# @return [String]
|
70
|
-
def to_xml_string(str = '')
|
69
|
+
def to_xml_string(str = +'')
|
71
70
|
str << '<c:title>'
|
72
71
|
unless empty?
|
73
|
-
clean_value = Axlsx
|
72
|
+
clean_value = Axlsx.trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx.sanitize(@text.to_s))
|
74
73
|
str << '<c:tx>'
|
75
74
|
if @cell.is_a?(Cell)
|
76
75
|
str << '<c:strRef>'
|
77
|
-
str <<
|
76
|
+
str << '<c:f>' << Axlsx.cell_range([@cell]) << '</c:f>'
|
78
77
|
str << '<c:strCache>'
|
79
78
|
str << '<c:ptCount val="1"/>'
|
80
79
|
str << '<c:pt idx="0">'
|
81
|
-
str <<
|
80
|
+
str << '<c:v>' << clean_value << '</c:v>'
|
82
81
|
str << '</c:pt>'
|
83
82
|
str << '</c:strCache>'
|
84
83
|
str << '</c:strRef>'
|
@@ -88,8 +87,8 @@ module Axlsx
|
|
88
87
|
str << '<a:lstStyle/>'
|
89
88
|
str << '<a:p>'
|
90
89
|
str << '<a:r>'
|
91
|
-
str <<
|
92
|
-
str <<
|
90
|
+
str << '<a:rPr sz="' << @text_size.to_s << '"/>'
|
91
|
+
str << '<a:t>' << clean_value << '</a:t>'
|
93
92
|
str << '</a:r>'
|
94
93
|
str << '</a:p>'
|
95
94
|
str << '</c:rich>'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# This class details the anchor points for drawings.
|
3
5
|
# @note The recommended way to manage drawings and charts is Worksheet#add_chart. Anchors are specified by the :start_at and :end_at options to that method.
|
@@ -33,7 +35,7 @@ module Axlsx
|
|
33
35
|
def initialize(drawing, options = {})
|
34
36
|
@drawing = drawing
|
35
37
|
drawing.anchors << self
|
36
|
-
@from, @to = Marker.new, Marker.new(:
|
38
|
+
@from, @to = Marker.new, Marker.new(col: 5, row: 10)
|
37
39
|
parse_options options
|
38
40
|
|
39
41
|
# bit of a hack to work around the fact that the coords for start at and end at
|
@@ -79,7 +81,7 @@ module Axlsx
|
|
79
81
|
# Serializes the object
|
80
82
|
# @param [String] str
|
81
83
|
# @return [String]
|
82
|
-
def to_xml_string(str = '')
|
84
|
+
def to_xml_string(str = +'')
|
83
85
|
str << '<xdr:twoCellAnchor>'
|
84
86
|
str << '<xdr:from>'
|
85
87
|
from.to_xml_string str
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# the ValAxis class defines a chart value axis.
|
3
5
|
class ValAxis < Axis
|
@@ -24,10 +26,10 @@ module Axlsx
|
|
24
26
|
# Serializes the object
|
25
27
|
# @param [String] str
|
26
28
|
# @return [String]
|
27
|
-
def to_xml_string(str = '')
|
29
|
+
def to_xml_string(str = +'')
|
28
30
|
str << '<c:valAx>'
|
29
31
|
super(str)
|
30
|
-
str <<
|
32
|
+
str << '<c:crossBetween val="' << @cross_between.to_s << '"/>'
|
31
33
|
str << '</c:valAx>'
|
32
34
|
end
|
33
35
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# 3D attributes for a chart.
|
3
5
|
class View3D
|
@@ -16,10 +18,10 @@ module Axlsx
|
|
16
18
|
end
|
17
19
|
|
18
20
|
# Validation for hPercent
|
19
|
-
H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)
|
21
|
+
H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)/.freeze
|
20
22
|
|
21
23
|
# validation for depthPercent
|
22
|
-
DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)
|
24
|
+
DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)/.freeze
|
23
25
|
|
24
26
|
# x rotation for the chart
|
25
27
|
# must be between -90 and 90
|
@@ -76,11 +78,17 @@ module Axlsx
|
|
76
78
|
alias :rotY= :rot_y=
|
77
79
|
|
78
80
|
# @see depth_percent
|
79
|
-
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
|
80
85
|
alias :depthPercent= :depth_percent=
|
81
86
|
|
82
87
|
# @see r_ang_ax
|
83
|
-
def r_ang_ax=(v)
|
88
|
+
def r_ang_ax=(v)
|
89
|
+
Axlsx.validate_boolean(v)
|
90
|
+
@r_ang_ax = v
|
91
|
+
end
|
84
92
|
alias :rAngAx= :r_ang_ax=
|
85
93
|
|
86
94
|
# @see perspective
|
@@ -94,7 +102,7 @@ module Axlsx
|
|
94
102
|
# Serializes the object
|
95
103
|
# @param [String] str
|
96
104
|
# @return [String]
|
97
|
-
def to_xml_string(str = '')
|
105
|
+
def to_xml_string(str = +'')
|
98
106
|
str << '<c:view3D>'
|
99
107
|
%w(rot_x h_percent rot_y depth_percent r_ang_ax perspective).each do |key|
|
100
108
|
str << element_for_attribute(key, 'c')
|
@@ -104,12 +112,12 @@ module Axlsx
|
|
104
112
|
|
105
113
|
private
|
106
114
|
|
107
|
-
#
|
115
|
+
# NOTE: move this to Axlsx module if we find the same pattern elsewhere.
|
108
116
|
def element_for_attribute(name, namespace = '')
|
109
117
|
val = Axlsx.instance_values_for(self)[name]
|
110
|
-
return "" if val
|
118
|
+
return "" if val.nil?
|
111
119
|
|
112
|
-
"<%s:%s val='%s'/>"
|
120
|
+
format("<%s:%s val='%s'/>", namespace, Axlsx.camel(name, false), val)
|
113
121
|
end
|
114
122
|
end
|
115
123
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
|
-
# a vml drawing used for comments in
|
4
|
+
# a vml drawing used for comments in Excel.
|
3
5
|
class VmlDrawing
|
4
6
|
# creates a new Vml Drawing object.
|
5
7
|
# @param [Comments] comments the comments object this drawing is associated with
|
@@ -12,26 +14,26 @@ module Axlsx
|
|
12
14
|
# The part name for this vml drawing
|
13
15
|
# @return [String]
|
14
16
|
def pn
|
15
|
-
|
17
|
+
format(VML_DRAWING_PN, @comments.worksheet.index + 1)
|
16
18
|
end
|
17
19
|
|
18
20
|
# serialize the vml_drawing to xml.
|
19
21
|
# @param [String] str
|
20
22
|
# @return [String]
|
21
|
-
def to_xml_string(str = '')
|
22
|
-
str <<
|
23
|
-
<xml xmlns:v="urn:schemas-microsoft-com:vml"
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
def to_xml_string(str = +'')
|
24
|
+
str << <<~XML
|
25
|
+
<xml xmlns:v="urn:schemas-microsoft-com:vml"
|
26
|
+
xmlns:o="urn:schemas-microsoft-com:office:office"
|
27
|
+
xmlns:x="urn:schemas-microsoft-com:office:excel">
|
28
|
+
<o:shapelayout v:ext="edit">
|
29
|
+
<o:idmap v:ext="edit" data="#{@comments.worksheet.index + 1}"/>
|
30
|
+
</o:shapelayout>
|
31
|
+
<v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202"
|
32
|
+
path="m0,0l0,21600,21600,21600,21600,0xe">
|
33
|
+
<v:stroke joinstyle="miter"/>
|
34
|
+
<v:path gradientshapeok="t" o:connecttype="rect"/>
|
35
|
+
</v:shapetype>
|
36
|
+
XML
|
35
37
|
@comments.each { |comment| comment.vml_shape.to_xml_string str }
|
36
38
|
str << "</xml>"
|
37
39
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# A VmlShape is used to position and render a comment.
|
3
5
|
class VmlShape
|
@@ -22,7 +24,7 @@ module Axlsx
|
|
22
24
|
@right_offset = 50
|
23
25
|
@bottom_offset = 5
|
24
26
|
@visible = true
|
25
|
-
@id = (
|
27
|
+
@id = Array.new(8) { rand(65..89).chr }.join
|
26
28
|
parse_options options
|
27
29
|
yield self if block_given?
|
28
30
|
end
|
@@ -35,29 +37,29 @@ module Axlsx
|
|
35
37
|
# serialize the shape to a string
|
36
38
|
# @param [String] str
|
37
39
|
# @return [String]
|
38
|
-
def to_xml_string(str = '')
|
39
|
-
str <<
|
40
|
+
def to_xml_string(str = +'')
|
41
|
+
str << <<~XML
|
40
42
|
|
41
|
-
<v:shape id="#{@id}" type="#_x0000_t202" fillcolor="#ffffa1 [80]" o:insetmode="auto"
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
<v:shape id="#{@id}" type="#_x0000_t202" fillcolor="#ffffa1 [80]" o:insetmode="auto"
|
44
|
+
style="visibility:#{@visible ? 'visible' : 'hidden'}">
|
45
|
+
<v:fill color2="#ffffa1 [80]"/>
|
46
|
+
<v:shadow on="t" obscured="t"/>
|
47
|
+
<v:path o:connecttype="none"/>
|
48
|
+
<v:textbox style='mso-fit-text-with-word-wrap:t'>
|
49
|
+
<div style='text-align:left'></div>
|
50
|
+
</v:textbox>
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
<x:ClientData ObjectType="Note">
|
53
|
+
<x:MoveWithCells/>
|
54
|
+
<x:SizeWithCells/>
|
55
|
+
<x:Anchor>#{left_column}, #{left_offset}, #{top_row}, #{top_offset}, #{right_column}, #{right_offset}, #{bottom_row}, #{bottom_offset}</x:Anchor>
|
56
|
+
<x:AutoFill>False</x:AutoFill>
|
57
|
+
<x:Row>#{row}</x:Row>
|
58
|
+
<x:Column>#{column}</x:Column>
|
59
|
+
#{@visible ? '<x:Visible/>' : ''}
|
60
|
+
</x:ClientData>
|
61
|
+
</v:shape>
|
62
|
+
XML
|
61
63
|
end
|
62
64
|
end
|
63
65
|
end
|
data/lib/axlsx/package.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
|
3
5
|
# xlsx document including validation and serialization.
|
@@ -31,7 +33,7 @@ module Axlsx
|
|
31
33
|
# Shortcut to specify that the workbook should use autowidth
|
32
34
|
# @see Workbook#use_autowidth
|
33
35
|
def use_autowidth=(v)
|
34
|
-
Axlsx
|
36
|
+
Axlsx.validate_boolean(v)
|
35
37
|
workbook.use_autowidth = v
|
36
38
|
end
|
37
39
|
|
@@ -44,7 +46,7 @@ module Axlsx
|
|
44
46
|
# Shortcut to specify that the workbook should use shared strings
|
45
47
|
# @see Workbook#use_shared_strings
|
46
48
|
def use_shared_strings=(v)
|
47
|
-
Axlsx
|
49
|
+
Axlsx.validate_boolean(v)
|
48
50
|
workbook.use_shared_strings = v
|
49
51
|
end
|
50
52
|
|
@@ -67,7 +69,10 @@ module Axlsx
|
|
67
69
|
end
|
68
70
|
|
69
71
|
# @see workbook
|
70
|
-
def workbook=(workbook)
|
72
|
+
def workbook=(workbook)
|
73
|
+
DataTypeValidator.validate :Package_workbook, Workbook, workbook
|
74
|
+
@workbook = workbook
|
75
|
+
end
|
71
76
|
|
72
77
|
# Serialize your workbook to disk as an xlsx document.
|
73
78
|
#
|
@@ -99,17 +104,17 @@ module Axlsx
|
|
99
104
|
# s = p.to_stream()
|
100
105
|
# File.open('example_streamed.xlsx', 'wb') { |f| f.write(s.read) }
|
101
106
|
def serialize(output, options = {}, secondary_options = nil)
|
102
|
-
|
107
|
+
unless workbook.styles_applied
|
103
108
|
workbook.apply_styles
|
104
109
|
end
|
105
110
|
|
106
111
|
confirm_valid, zip_command = parse_serialize_options(options, secondary_options)
|
107
|
-
return false unless !confirm_valid ||
|
112
|
+
return false unless !confirm_valid || validate.empty?
|
108
113
|
|
109
114
|
zip_provider = if zip_command
|
110
115
|
ZipCommand.new(zip_command)
|
111
116
|
else
|
112
|
-
|
117
|
+
BufferedZipOutputStream
|
113
118
|
end
|
114
119
|
Relationship.initialize_ids_cache
|
115
120
|
zip_provider.open(output) do |zip|
|
@@ -124,15 +129,16 @@ module Axlsx
|
|
124
129
|
# @param [Boolean] confirm_valid Validate the package prior to serialization.
|
125
130
|
# @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not.
|
126
131
|
def to_stream(confirm_valid = false)
|
127
|
-
|
132
|
+
unless workbook.styles_applied
|
128
133
|
workbook.apply_styles
|
129
134
|
end
|
130
135
|
|
131
|
-
return false unless !confirm_valid ||
|
136
|
+
return false unless !confirm_valid || validate.empty?
|
132
137
|
|
133
138
|
Relationship.initialize_ids_cache
|
134
|
-
|
135
|
-
|
139
|
+
stream = BufferedZipOutputStream.write_buffer do |zip|
|
140
|
+
write_parts(zip)
|
141
|
+
end
|
136
142
|
stream.rewind
|
137
143
|
stream
|
138
144
|
ensure
|
@@ -142,7 +148,7 @@ module Axlsx
|
|
142
148
|
# Encrypt the package into a CFB using the password provided
|
143
149
|
# This is not ready yet
|
144
150
|
def encrypt(file_name, password)
|
145
|
-
|
151
|
+
false
|
146
152
|
# moc = MsOffCrypto.new(file_name, password)
|
147
153
|
# moc.save
|
148
154
|
end
|
@@ -156,7 +162,7 @@ module Axlsx
|
|
156
162
|
#
|
157
163
|
# If by chance you are able to create a package that does not validate it indicates that the internal
|
158
164
|
# validation is not robust enough and needs to be improved. Please report your errors to the gem author.
|
159
|
-
# @see
|
165
|
+
# @see https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
|
160
166
|
# @example
|
161
167
|
# # The following will output any error messages found in serialization.
|
162
168
|
# p = Axlsx::Package.new
|
@@ -213,57 +219,57 @@ module Axlsx
|
|
213
219
|
# @private
|
214
220
|
def parts
|
215
221
|
parts = [
|
216
|
-
{ :
|
217
|
-
{ :
|
218
|
-
{ :
|
219
|
-
{ :
|
220
|
-
{ :
|
222
|
+
{ entry: "xl/#{STYLES_PN}", doc: workbook.styles, schema: SML_XSD },
|
223
|
+
{ entry: CORE_PN, doc: @core, schema: CORE_XSD },
|
224
|
+
{ entry: APP_PN, doc: @app, schema: APP_XSD },
|
225
|
+
{ entry: WORKBOOK_RELS_PN, doc: workbook.relationships, schema: RELS_XSD },
|
226
|
+
{ entry: WORKBOOK_PN, doc: workbook, schema: SML_XSD }
|
221
227
|
]
|
222
228
|
|
223
229
|
workbook.drawings.each do |drawing|
|
224
|
-
parts << { :
|
225
|
-
parts << { :
|
230
|
+
parts << { entry: "xl/#{drawing.rels_pn}", doc: drawing.relationships, schema: RELS_XSD }
|
231
|
+
parts << { entry: "xl/#{drawing.pn}", doc: drawing, schema: DRAWING_XSD }
|
226
232
|
end
|
227
233
|
|
228
234
|
workbook.tables.each do |table|
|
229
|
-
parts << { :
|
235
|
+
parts << { entry: "xl/#{table.pn}", doc: table, schema: SML_XSD }
|
230
236
|
end
|
231
237
|
workbook.pivot_tables.each do |pivot_table|
|
232
238
|
cache_definition = pivot_table.cache_definition
|
233
|
-
parts << { :
|
234
|
-
parts << { :
|
235
|
-
parts << { :
|
239
|
+
parts << { entry: "xl/#{pivot_table.rels_pn}", doc: pivot_table.relationships, schema: RELS_XSD }
|
240
|
+
parts << { entry: "xl/#{pivot_table.pn}", doc: pivot_table } # , :schema => SML_XSD}
|
241
|
+
parts << { entry: "xl/#{cache_definition.pn}", doc: cache_definition } # , :schema => SML_XSD}
|
236
242
|
end
|
237
243
|
|
238
244
|
workbook.comments.each do |comment|
|
239
|
-
|
240
|
-
parts << { :
|
241
|
-
parts << { :
|
245
|
+
unless comment.empty?
|
246
|
+
parts << { entry: "xl/#{comment.pn}", doc: comment, schema: SML_XSD }
|
247
|
+
parts << { entry: "xl/#{comment.vml_drawing.pn}", doc: comment.vml_drawing, schema: nil }
|
242
248
|
end
|
243
249
|
end
|
244
250
|
|
245
251
|
workbook.charts.each do |chart|
|
246
|
-
parts << { :
|
252
|
+
parts << { entry: "xl/#{chart.pn}", doc: chart, schema: DRAWING_XSD }
|
247
253
|
end
|
248
254
|
|
249
255
|
workbook.images.each do |image|
|
250
|
-
parts << { :
|
256
|
+
parts << { entry: "xl/#{image.pn}", path: image.image_src } unless image.remote?
|
251
257
|
end
|
252
258
|
|
253
259
|
if use_shared_strings
|
254
|
-
parts << { :
|
260
|
+
parts << { entry: "xl/#{SHARED_STRINGS_PN}", doc: workbook.shared_strings, schema: SML_XSD }
|
255
261
|
end
|
256
262
|
|
257
263
|
workbook.worksheets.each do |sheet|
|
258
|
-
parts << { :
|
259
|
-
parts << { :
|
264
|
+
parts << { entry: "xl/#{sheet.rels_pn}", doc: sheet.relationships, schema: RELS_XSD }
|
265
|
+
parts << { entry: "xl/#{sheet.pn}", doc: sheet, schema: SML_XSD }
|
260
266
|
end
|
261
267
|
|
262
268
|
# Sort parts for correct MIME detection
|
263
269
|
[
|
264
|
-
{ :
|
265
|
-
{ :
|
266
|
-
*
|
270
|
+
{ entry: CONTENT_TYPES_PN, doc: content_types, schema: CONTENT_TYPES_XSD },
|
271
|
+
{ entry: RELS_PN, doc: relationships, schema: RELS_XSD },
|
272
|
+
*parts.sort_by { |part| part[:entry] }.reverse
|
267
273
|
]
|
268
274
|
end
|
269
275
|
|
@@ -289,56 +295,56 @@ module Axlsx
|
|
289
295
|
def content_types
|
290
296
|
c_types = base_content_types
|
291
297
|
workbook.drawings.each do |drawing|
|
292
|
-
c_types << Axlsx::Override.new(:
|
293
|
-
:
|
298
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{drawing.pn}",
|
299
|
+
ContentType: DRAWING_CT)
|
294
300
|
end
|
295
301
|
|
296
302
|
workbook.charts.each do |chart|
|
297
|
-
c_types << Axlsx::Override.new(:
|
298
|
-
:
|
303
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{chart.pn}",
|
304
|
+
ContentType: CHART_CT)
|
299
305
|
end
|
300
306
|
|
301
307
|
workbook.tables.each do |table|
|
302
|
-
c_types << Axlsx::Override.new(:
|
303
|
-
:
|
308
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{table.pn}",
|
309
|
+
ContentType: TABLE_CT)
|
304
310
|
end
|
305
311
|
|
306
312
|
workbook.pivot_tables.each do |pivot_table|
|
307
|
-
c_types << Axlsx::Override.new(:
|
308
|
-
:
|
309
|
-
c_types << Axlsx::Override.new(:
|
310
|
-
:
|
313
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{pivot_table.pn}",
|
314
|
+
ContentType: PIVOT_TABLE_CT)
|
315
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{pivot_table.cache_definition.pn}",
|
316
|
+
ContentType: PIVOT_TABLE_CACHE_DEFINITION_CT)
|
311
317
|
end
|
312
318
|
|
313
319
|
workbook.comments.each do |comment|
|
314
|
-
|
315
|
-
c_types << Axlsx::Override.new(:
|
316
|
-
:
|
320
|
+
unless comment.empty?
|
321
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{comment.pn}",
|
322
|
+
ContentType: COMMENT_CT)
|
317
323
|
end
|
318
324
|
end
|
319
325
|
|
320
|
-
|
321
|
-
c_types << Axlsx::Default.new(:
|
326
|
+
unless workbook.comments.empty?
|
327
|
+
c_types << Axlsx::Default.new(Extension: "vml", ContentType: VML_DRAWING_CT)
|
322
328
|
end
|
323
329
|
|
324
330
|
workbook.worksheets.each do |sheet|
|
325
|
-
c_types << Axlsx::Override.new(:
|
326
|
-
:
|
331
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{sheet.pn}",
|
332
|
+
ContentType: WORKSHEET_CT)
|
327
333
|
end
|
328
334
|
exts = workbook.images.map { |image| image.extname.downcase }
|
329
335
|
exts.uniq.each do |ext|
|
330
|
-
ct = if
|
336
|
+
ct = if JPEG_EXS.include?(ext)
|
331
337
|
JPEG_CT
|
332
|
-
elsif ext ==
|
338
|
+
elsif ext == GIF_EX
|
333
339
|
GIF_CT
|
334
|
-
elsif ext ==
|
340
|
+
elsif ext == PNG_EX
|
335
341
|
PNG_CT
|
336
342
|
end
|
337
|
-
c_types << Axlsx::Default.new(:
|
343
|
+
c_types << Axlsx::Default.new(ContentType: ct, Extension: ext)
|
338
344
|
end
|
339
345
|
if use_shared_strings
|
340
|
-
c_types << Axlsx::Override.new(:
|
341
|
-
:
|
346
|
+
c_types << Axlsx::Override.new(PartName: "/xl/#{SHARED_STRINGS_PN}",
|
347
|
+
ContentType: SHARED_STRINGS_CT)
|
342
348
|
end
|
343
349
|
c_types
|
344
350
|
end
|
@@ -347,13 +353,13 @@ module Axlsx
|
|
347
353
|
# @return [ContentType]
|
348
354
|
# @private
|
349
355
|
def base_content_types
|
350
|
-
c_types = ContentType.new
|
351
|
-
c_types << Default.new(:
|
352
|
-
c_types << Default.new(:
|
353
|
-
c_types << Override.new(:
|
354
|
-
c_types << Override.new(:
|
355
|
-
c_types << Override.new(:
|
356
|
-
c_types << Axlsx::Override.new(:
|
356
|
+
c_types = ContentType.new
|
357
|
+
c_types << Default.new(ContentType: RELS_CT, Extension: RELS_EX)
|
358
|
+
c_types << Default.new(Extension: XML_EX, ContentType: XML_CT)
|
359
|
+
c_types << Override.new(PartName: "/#{APP_PN}", ContentType: APP_CT)
|
360
|
+
c_types << Override.new(PartName: "/#{CORE_PN}", ContentType: CORE_CT)
|
361
|
+
c_types << Override.new(PartName: "/xl/#{STYLES_PN}", ContentType: STYLES_CT)
|
362
|
+
c_types << Axlsx::Override.new(PartName: "/#{WORKBOOK_PN}", ContentType: WORKBOOK_CT)
|
357
363
|
c_types.lock
|
358
364
|
c_types
|
359
365
|
end
|
@@ -376,19 +382,19 @@ module Axlsx
|
|
376
382
|
# @private
|
377
383
|
def parse_serialize_options(options, secondary_options)
|
378
384
|
if secondary_options
|
379
|
-
warn "[DEPRECATION] Axlsx::Package#serialize with 3 arguments is deprecated. "
|
385
|
+
warn "[DEPRECATION] Axlsx::Package#serialize with 3 arguments is deprecated. " \
|
380
386
|
"Use keyword args instead e.g., package.serialize(output, confirm_valid: false, zip_command: 'zip')"
|
381
387
|
end
|
382
388
|
if options.is_a?(Hash)
|
383
389
|
options.merge!(secondary_options || {})
|
384
390
|
invalid_keys = options.keys - [:confirm_valid, :zip_command]
|
385
391
|
if invalid_keys.any?
|
386
|
-
raise ArgumentError
|
392
|
+
raise ArgumentError, "Invalid keyword arguments: #{invalid_keys}"
|
387
393
|
end
|
388
394
|
|
389
395
|
[options.fetch(:confirm_valid, false), options.fetch(:zip_command, nil)]
|
390
396
|
else
|
391
|
-
warn "[DEPRECATION] Axlsx::Package#serialize with confirm_valid as a boolean is deprecated. "
|
397
|
+
warn "[DEPRECATION] Axlsx::Package#serialize with confirm_valid as a boolean is deprecated. " \
|
392
398
|
"Use keyword args instead e.g., package.serialize(output, confirm_valid: false)"
|
393
399
|
parse_serialize_options((secondary_options || {}).merge(confirm_valid: options), nil)
|
394
400
|
end
|