axlsx 1.0.15 → 1.1.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.
- data/.yardopts +1 -0
- data/CHANGELOG.md +58 -2
- data/README.md +425 -207
- data/Rakefile +6 -2
- data/examples/axlsx.xlsx +0 -0
- data/examples/example.csv +1000 -0
- data/examples/example.rb +266 -132
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/real_example.rb +63 -0
- data/examples/sample.png +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/lib/axlsx/content_type/content_type.rb +13 -12
- data/lib/axlsx/content_type/default.rb +10 -6
- data/lib/axlsx/content_type/override.rb +13 -8
- data/lib/axlsx/doc_props/app.rb +38 -41
- data/lib/axlsx/doc_props/core.rb +13 -17
- data/lib/axlsx/drawing/axis.rb +39 -19
- data/lib/axlsx/drawing/bar_3D_chart.rb +34 -32
- data/lib/axlsx/drawing/bar_series.rb +14 -14
- data/lib/axlsx/drawing/cat_axis.rb +16 -14
- data/lib/axlsx/drawing/cat_axis_data.rb +17 -18
- data/lib/axlsx/drawing/chart.rb +40 -41
- data/lib/axlsx/drawing/drawing.rb +27 -12
- data/lib/axlsx/drawing/graphic_frame.rb +22 -21
- data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
- data/lib/axlsx/drawing/hyperlink.rb +96 -0
- data/lib/axlsx/drawing/hyperlink.rb~ +64 -0
- data/lib/axlsx/drawing/line_3D_chart.rb +31 -28
- data/lib/axlsx/drawing/line_series.rb +12 -11
- data/lib/axlsx/drawing/marker.rb +11 -8
- data/lib/axlsx/drawing/named_axis_data.rb +36 -0
- data/lib/axlsx/drawing/one_cell_anchor.rb +18 -16
- data/lib/axlsx/drawing/pic.rb +47 -33
- data/lib/axlsx/drawing/picture_locking.rb +22 -18
- data/lib/axlsx/drawing/pie_3D_chart.rb +11 -8
- data/lib/axlsx/drawing/pie_series.rb +16 -12
- data/lib/axlsx/drawing/scaling.rb +11 -10
- data/lib/axlsx/drawing/scatter_chart.rb +69 -0
- data/lib/axlsx/drawing/scatter_series.rb +39 -0
- data/lib/axlsx/drawing/ser_axis.rb +11 -10
- data/lib/axlsx/drawing/series.rb +16 -15
- data/lib/axlsx/drawing/series_title.rb +15 -14
- data/lib/axlsx/drawing/title.rb +27 -26
- data/lib/axlsx/drawing/two_cell_anchor.rb +19 -20
- data/lib/axlsx/drawing/val_axis.rb +9 -7
- data/lib/axlsx/drawing/val_axis_data.rb +18 -17
- data/lib/axlsx/drawing/view_3D.rb +23 -20
- data/lib/axlsx/package.rb +117 -52
- data/lib/axlsx/rels/relationship.rb +27 -8
- data/lib/axlsx/rels/relationships.rb +9 -2
- data/lib/axlsx/stylesheet/border.rb +28 -23
- data/lib/axlsx/stylesheet/border_pr.rb +17 -15
- data/lib/axlsx/stylesheet/cell_alignment.rb +24 -21
- data/lib/axlsx/stylesheet/cell_protection.rb +11 -7
- data/lib/axlsx/stylesheet/cell_style.rb +9 -5
- data/lib/axlsx/stylesheet/color.rb +20 -14
- data/lib/axlsx/stylesheet/fill.rb +8 -5
- data/lib/axlsx/stylesheet/font.rb +22 -14
- data/lib/axlsx/stylesheet/gradient_fill.rb +20 -17
- data/lib/axlsx/stylesheet/gradient_stop.rb +10 -6
- data/lib/axlsx/stylesheet/num_fmt.rb +13 -6
- data/lib/axlsx/stylesheet/pattern_fill.rb +26 -10
- data/lib/axlsx/stylesheet/styles.rb +55 -41
- data/lib/axlsx/stylesheet/table_style.rb +10 -4
- data/lib/axlsx/stylesheet/table_style_element.rb +11 -7
- data/lib/axlsx/stylesheet/table_styles.rb +12 -8
- data/lib/axlsx/stylesheet/xf.rb +30 -25
- data/lib/axlsx/util/cbf.rb +69 -33
- data/lib/axlsx/util/constants.rb +39 -20
- data/lib/axlsx/util/doc/_index.html +84 -0
- data/lib/axlsx/util/doc/class_list.html +47 -0
- data/lib/axlsx/util/doc/css/common.css +1 -0
- data/lib/axlsx/util/doc/css/full_list.css +55 -0
- data/lib/axlsx/util/doc/css/style.css +322 -0
- data/lib/axlsx/util/doc/file_list.html +46 -0
- data/lib/axlsx/util/doc/frames.html +13 -0
- data/lib/axlsx/util/doc/index.html +84 -0
- data/lib/axlsx/util/doc/js/app.js +205 -0
- data/lib/axlsx/util/doc/js/full_list.js +173 -0
- data/lib/axlsx/util/doc/js/jquery.js +16 -0
- data/lib/axlsx/util/doc/method_list.html +46 -0
- data/lib/axlsx/util/doc/top-level-namespace.html +95 -0
- data/lib/axlsx/util/font_tables.rb~ +0 -0
- data/lib/axlsx/util/ms_off_crypto.rb +10 -10
- data/lib/axlsx/util/parser.rb +1 -0
- data/lib/axlsx/util/simple_typed_list.rb +20 -10
- data/lib/axlsx/util/storage.rb +1 -1
- data/lib/axlsx/util/validators.rb +23 -7
- data/lib/axlsx/version.rb +5 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +68 -0
- data/lib/axlsx/workbook/shared_strings_table.rb~ +69 -0
- data/lib/axlsx/workbook/workbook.rb +82 -26
- data/lib/axlsx/workbook/worksheet/cell.rb +166 -130
- data/lib/axlsx/workbook/worksheet/col.rb +114 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +29 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +97 -0
- data/lib/axlsx/workbook/worksheet/row.rb +53 -21
- data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/table.rb +96 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +97 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +275 -124
- data/lib/axlsx.rb +41 -14
- data/lib/schema/dc.xsd +5 -5
- data/lib/schema/dcmitype.xsd +5 -3
- data/lib/schema/dcterms.xsd +15 -15
- data/lib/schema/opc-coreProperties.xsd +6 -2
- data/lib/schema/xml.xsd +7 -8
- data/test/benchmark.rb +73 -0
- data/test/content_type/tc_content_type.rb +31 -31
- data/test/content_type/tc_default.rb +9 -22
- data/test/content_type/tc_override.rb +8 -21
- data/test/doc_props/tc_app.rb +2 -8
- data/test/doc_props/tc_core.rb +6 -7
- data/test/drawing/tc_axis.rb +7 -3
- data/test/drawing/tc_bar_3D_chart.rb +6 -7
- data/test/drawing/tc_bar_series.rb +4 -5
- data/test/drawing/tc_cat_axis.rb +2 -3
- data/test/drawing/tc_cat_axis_data.rb +2 -3
- data/test/drawing/tc_chart.rb +13 -14
- data/test/drawing/tc_drawing.rb +7 -8
- data/test/drawing/tc_graphic_frame.rb +3 -4
- data/test/drawing/tc_hyperlink.rb +69 -0
- data/test/drawing/tc_line_3d_chart.rb +5 -6
- data/test/drawing/tc_line_series.rb +3 -4
- data/test/drawing/tc_marker.rb +3 -4
- data/test/drawing/tc_one_cell_anchor.rb +6 -7
- data/test/drawing/tc_pic.rb +13 -8
- data/test/drawing/tc_picture_locking.rb +2 -3
- data/test/drawing/tc_pie_3D_chart.rb +5 -6
- data/test/drawing/tc_pie_series.rb +4 -5
- data/test/drawing/tc_scaling.rb +3 -4
- data/test/drawing/tc_scatter_chart.rb +43 -0
- data/test/drawing/tc_scatter_series.rb +20 -0
- data/test/drawing/tc_ser_axis.rb +2 -3
- data/test/drawing/tc_series.rb +4 -5
- data/test/drawing/tc_series_title.rb +4 -5
- data/test/drawing/tc_title.rb +4 -5
- data/test/drawing/tc_two_cell_anchor.rb +4 -5
- data/test/drawing/tc_val_axis.rb +2 -3
- data/test/drawing/tc_val_axis_data.rb +2 -3
- data/test/drawing/tc_view_3D.rb +6 -7
- data/test/profile.rb +34 -0
- data/test/rels/tc_relationship.rb +10 -6
- data/test/rels/tc_relationships.rb +4 -5
- data/test/stylesheet/tc_border.rb +3 -4
- data/test/stylesheet/tc_border_pr.rb +3 -4
- data/test/stylesheet/tc_cell_alignment.rb +10 -6
- data/test/stylesheet/tc_cell_protection.rb +2 -3
- data/test/stylesheet/tc_cell_style.rb +2 -3
- data/test/stylesheet/tc_color.rb +2 -3
- data/test/stylesheet/tc_fill.rb +1 -2
- data/test/stylesheet/tc_font.rb +12 -5
- data/test/stylesheet/tc_gradient_fill.rb +1 -2
- data/test/stylesheet/tc_gradient_stop.rb +1 -2
- data/test/stylesheet/tc_num_fmt.rb +1 -2
- data/test/stylesheet/tc_pattern_fill.rb +3 -4
- data/test/stylesheet/tc_styles.rb +31 -6
- data/test/stylesheet/tc_table_style.rb +2 -3
- data/test/stylesheet/tc_table_style_element.rb +2 -3
- data/test/stylesheet/tc_table_styles.rb +3 -4
- data/test/stylesheet/tc_xf.rb +16 -17
- data/test/tc_axlsx.rb +39 -0
- data/test/tc_helper.rb +3 -0
- data/test/tc_package.rb +43 -9
- data/test/util/tc_simple_typed_list.rb +8 -9
- data/test/util/tc_validators.rb +7 -8
- data/test/workbook/tc_shared_strings_table.rb +38 -0
- data/test/workbook/tc_workbook.rb +32 -6
- data/test/workbook/worksheet/table/tc_table.rb +71 -0
- data/test/workbook/worksheet/table/tc_table.rb~ +72 -0
- data/test/workbook/worksheet/tc_cell.rb +80 -13
- data/test/workbook/worksheet/tc_col.rb +59 -0
- data/test/workbook/worksheet/tc_col.rb~ +10 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb +132 -0
- data/test/workbook/worksheet/tc_page_margins.rb +97 -0
- data/test/workbook/worksheet/tc_row.rb +54 -4
- data/test/workbook/worksheet/tc_worksheet.rb +205 -31
- metadata +78 -84
- data/examples/example.rb~ +0 -112
- data/test/drawing/tc_line_series.tc~ +0 -34
- data/test/drawing/tc_picture_locking.rb~ +0 -77
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# A series title is a Title with a slightly different serialization than chart titles.
|
|
3
4
|
class SeriesTitle < Title
|
|
4
5
|
|
|
5
|
-
# Serializes the
|
|
6
|
-
# @param [
|
|
6
|
+
# Serializes the object
|
|
7
|
+
# @param [String] str
|
|
7
8
|
# @return [String]
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
def to_xml_string(str = '')
|
|
10
|
+
str << '<c:tx>'
|
|
11
|
+
str << '<c:strRef>'
|
|
12
|
+
str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>'
|
|
13
|
+
str << '<c:strCache>'
|
|
14
|
+
str << '<c:ptCount val="1"/>'
|
|
15
|
+
str << '<c:pt idx="0">'
|
|
16
|
+
str << '<c:v>' << @text << '</c:v>'
|
|
17
|
+
str << '</c:pt>'
|
|
18
|
+
str << '</c:strCache>'
|
|
19
|
+
str << '</c:strRef>'
|
|
20
|
+
str << '</c:tx>'
|
|
20
21
|
end
|
|
21
22
|
end
|
|
22
23
|
end
|
data/lib/axlsx/drawing/title.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# A Title stores information about the title of a chart
|
|
3
4
|
class Title
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
# The text to be shown. Setting this property directly with a string will remove the cell reference.
|
|
6
7
|
# @return [String]
|
|
7
8
|
attr_reader :text
|
|
@@ -16,9 +17,9 @@ module Axlsx
|
|
|
16
17
|
self.cell = title if title.is_a?(Cell)
|
|
17
18
|
self.text = title.to_s unless title.is_a?(Cell)
|
|
18
19
|
end
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
# @see text
|
|
21
|
-
def text=(v)
|
|
22
|
+
def text=(v)
|
|
22
23
|
DataTypeValidator.validate 'Title.text', String, v
|
|
23
24
|
@text = v
|
|
24
25
|
@cell = nil
|
|
@@ -29,7 +30,7 @@ module Axlsx
|
|
|
29
30
|
def cell=(v)
|
|
30
31
|
DataTypeValidator.validate 'Title.text', Cell, v
|
|
31
32
|
@cell = v
|
|
32
|
-
@text = v.value.to_s
|
|
33
|
+
@text = v.value.to_s
|
|
33
34
|
v
|
|
34
35
|
end
|
|
35
36
|
|
|
@@ -37,29 +38,29 @@ module Axlsx
|
|
|
37
38
|
#def layout=(v) DataTypeValidator.validate 'Title.layout', Layout, v; @layout = v; end
|
|
38
39
|
#def overlay=(v) Axlsx::validate_boolean v; @overlay=v; end
|
|
39
40
|
#def spPr=(v) DataTypeValidator.validate 'Title.spPr', SpPr, v; @spPr = v; end
|
|
40
|
-
|
|
41
|
-
# Serializes the
|
|
42
|
-
# @param [
|
|
41
|
+
|
|
42
|
+
# Serializes the object
|
|
43
|
+
# @param [String] str
|
|
43
44
|
# @return [String]
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
45
|
+
def to_xml_string(str = '')
|
|
46
|
+
str << '<c:title>'
|
|
47
|
+
unless @text.empty?
|
|
48
|
+
str << '<c:tx>'
|
|
49
|
+
str << '<c:strRef>'
|
|
50
|
+
str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>'
|
|
51
|
+
str << '<c:strCache>'
|
|
52
|
+
str << '<c:ptCount val="1"/>'
|
|
53
|
+
str << '<c:pt idx="0">'
|
|
54
|
+
str << '<c:v>' << @text << '</c:v>'
|
|
55
|
+
str << '</c:pt>'
|
|
56
|
+
str << '</c:strCache>'
|
|
57
|
+
str << '</c:strRef>'
|
|
58
|
+
str << '</c:tx>'
|
|
59
|
+
end
|
|
60
|
+
str << '<c:layout/>'
|
|
61
|
+
str << '<c:overlay val="0"/>'
|
|
62
|
+
str << '</c:title>'
|
|
62
63
|
end
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
end
|
|
65
66
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# This class details the anchor points for drawings.
|
|
3
4
|
# @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.
|
|
@@ -25,7 +26,7 @@ module Axlsx
|
|
|
25
26
|
attr_reader :drawing
|
|
26
27
|
|
|
27
28
|
|
|
28
|
-
# Creates a new TwoCellAnchor object and sets up a reference to the from and to markers in the
|
|
29
|
+
# Creates a new TwoCellAnchor object and sets up a reference to the from and to markers in the
|
|
29
30
|
# graphic_frame's chart. That means that you can do stuff like
|
|
30
31
|
# c = worksheet.add_chart Axlsx::Chart
|
|
31
32
|
# c.start_at 5, 9
|
|
@@ -37,13 +38,13 @@ module Axlsx
|
|
|
37
38
|
# @option options [Array] end_at the col, row to end at
|
|
38
39
|
def initialize(drawing, options={})
|
|
39
40
|
@drawing = drawing
|
|
40
|
-
drawing.anchors << self
|
|
41
|
+
drawing.anchors << self
|
|
41
42
|
@from, @to = Marker.new, Marker.new(:col => 5, :row=>10)
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
# Creates a graphic frame and chart object associated with this anchor
|
|
45
46
|
# @return [Chart]
|
|
46
|
-
def add_chart(chart_type, options)
|
|
47
|
+
def add_chart(chart_type, options)
|
|
47
48
|
@object = GraphicFrame.new(self, chart_type, options)
|
|
48
49
|
@object.chart
|
|
49
50
|
end
|
|
@@ -53,24 +54,22 @@ module Axlsx
|
|
|
53
54
|
def index
|
|
54
55
|
@drawing.anchors.index(self)
|
|
55
56
|
end
|
|
56
|
-
# Serializes the two cell anchor
|
|
57
|
-
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
58
|
-
# @return [String]
|
|
59
|
-
def to_xml(xml)
|
|
60
|
-
#build it for now, break it down later!
|
|
61
|
-
xml[:xdr].twoCellAnchor {
|
|
62
|
-
xml.from {
|
|
63
|
-
from.to_xml(xml)
|
|
64
|
-
}
|
|
65
|
-
xml.to {
|
|
66
|
-
to.to_xml(xml)
|
|
67
|
-
}
|
|
68
|
-
@object.to_xml(xml)
|
|
69
|
-
xml.clientData
|
|
70
|
-
}
|
|
71
|
-
end
|
|
72
57
|
|
|
73
|
-
|
|
58
|
+
# Serializes the object
|
|
59
|
+
# @param [String] str
|
|
60
|
+
# @return [String]
|
|
61
|
+
def to_xml_string(str = '')
|
|
62
|
+
str << '<xdr:twoCellAnchor>'
|
|
63
|
+
str << '<xdr:from>'
|
|
64
|
+
from.to_xml_string str
|
|
65
|
+
str << '</xdr:from>'
|
|
66
|
+
str << '<xdr:to>'
|
|
67
|
+
to.to_xml_string str
|
|
68
|
+
str << '</xdr:to>'
|
|
69
|
+
object.to_xml_string(str)
|
|
70
|
+
str << '<xdr:clientData/>'
|
|
71
|
+
str << '</xdr:twoCellAnchor>'
|
|
72
|
+
end
|
|
74
73
|
|
|
75
74
|
end
|
|
76
75
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# the ValAxis class defines a chart value axis.
|
|
3
4
|
class ValAxis < Axis
|
|
@@ -21,14 +22,15 @@ module Axlsx
|
|
|
21
22
|
# @see crossBetween
|
|
22
23
|
def crossBetween=(v) RestrictionValidator.validate "ValAxis.crossBetween", [:between, :midCat], v; @crossBetween = v; end
|
|
23
24
|
|
|
24
|
-
# Serializes the
|
|
25
|
-
# @param [
|
|
25
|
+
# Serializes the object
|
|
26
|
+
# @param [String] str
|
|
26
27
|
# @return [String]
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
def to_xml_string(str = '')
|
|
29
|
+
str << '<c:valAx>'
|
|
30
|
+
super(str)
|
|
31
|
+
str << '<c:crossBetween val="' << @crossBetween.to_s << '"/>'
|
|
32
|
+
str << '</c:valAx>'
|
|
32
33
|
end
|
|
34
|
+
|
|
33
35
|
end
|
|
34
36
|
end
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# The ValAxisData class manages the values for a chart value series.
|
|
3
4
|
class ValAxisData < CatAxisData
|
|
4
5
|
|
|
5
|
-
# Serializes the
|
|
6
|
-
# @param [
|
|
6
|
+
# Serializes the object
|
|
7
|
+
# @param [String] str
|
|
7
8
|
# @return [String]
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
def to_xml_string(str = '')
|
|
10
|
+
str << '<c:val>'
|
|
11
|
+
str << '<c:numRef>'
|
|
12
|
+
str << '<c:f>' << Axlsx::cell_range(@list) << '</c:f>'
|
|
13
|
+
str << '<c:numCache>'
|
|
14
|
+
str << '<c:formatCode>General</c:formatCode>'
|
|
15
|
+
str << '<c:ptCount val="' << size.to_s << '"/>'
|
|
16
|
+
each_with_index do |item, index|
|
|
17
|
+
v = item.is_a?(Cell) ? item.value.to_s : item
|
|
18
|
+
str << '<c:pt idx="' << index.to_s << '"><c:v>' << v << '</c:v></c:pt>'
|
|
19
|
+
end
|
|
20
|
+
str << '</c:numCache>'
|
|
21
|
+
str << '</c:numRef>'
|
|
22
|
+
str << '</c:val>'
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
end
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
end
|
|
@@ -1,37 +1,38 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
1
2
|
module Axlsx
|
|
2
3
|
# 3D attributes for a chart.
|
|
3
4
|
class View3D
|
|
4
5
|
|
|
5
6
|
# Validation for hPercent
|
|
6
7
|
H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
# validation for depthPercent
|
|
9
10
|
DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)%/
|
|
10
11
|
|
|
11
|
-
# x rotation for the chart
|
|
12
|
+
# x rotation for the chart
|
|
12
13
|
# must be between -90 and 90
|
|
13
14
|
# @return [Integer]
|
|
14
15
|
attr_reader :rotX
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
# height of chart as % of chart
|
|
17
18
|
# must be between 5% and 500%
|
|
18
19
|
# @return [String]
|
|
19
20
|
attr_reader :hPercent
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
# y rotation for the chart
|
|
22
23
|
# must be between 0 and 360
|
|
23
24
|
# @return [Integer]
|
|
24
25
|
attr_reader :rotY
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
# depth or chart as % of chart width
|
|
27
28
|
# must be between 20% and 2000%
|
|
28
29
|
# @return [String]
|
|
29
30
|
attr_reader :depthPercent
|
|
30
|
-
|
|
31
|
+
|
|
31
32
|
# Chart axis are at right angles
|
|
32
33
|
# @return [Boolean]
|
|
33
34
|
attr_reader :rAngAx
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
# field of view angle
|
|
36
37
|
# @return [Integer]
|
|
37
38
|
attr_reader :perspective
|
|
@@ -44,10 +45,10 @@ module Axlsx
|
|
|
44
45
|
# @option options [Boolean] rAngAx
|
|
45
46
|
# @option options [Integer] perspective
|
|
46
47
|
def initialize(options={})
|
|
47
|
-
@rotX, @hPercent, @rotY, @depthPercent, @rAngAx, @perspective = nil, nil, nil, nil, nil, nil
|
|
48
|
+
@rotX, @hPercent, @rotY, @depthPercent, @rAngAx, @perspective = nil, nil, nil, nil, nil, nil
|
|
48
49
|
options.each do |o|
|
|
49
50
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
50
|
-
end
|
|
51
|
+
end
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
# @see rotX
|
|
@@ -68,18 +69,20 @@ module Axlsx
|
|
|
68
69
|
# @see perspective
|
|
69
70
|
def perspective=(v) DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
#
|
|
72
|
+
|
|
73
|
+
# Serializes the object
|
|
74
|
+
# @param [String] str
|
|
73
75
|
# @return [String]
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
def to_xml_string(str = '')
|
|
77
|
+
str << '<c:view3D>'
|
|
78
|
+
str << '<c:rotX val="' << @rotX.to_s << '"/>' unless @rotX.nil?
|
|
79
|
+
str << '<c:hPercent val="' << @hPercent.to_s << '"/>' unless @hPercent.nil?
|
|
80
|
+
str << '<c:rotY val="' << @rotY.to_s << '"/>' unless @rotY.nil?
|
|
81
|
+
str << '<c:depthPercent val="' << @depthPercent.to_s << '"/>' unless @depthPercent.nil?
|
|
82
|
+
str << '<c:rAngAx val="' << @rAngAx.to_s << '"/>' unless @rAngAx.nil?
|
|
83
|
+
str << '<c:perspective val="' << @perspective.to_s << '"/>' unless @perspective.nil?
|
|
84
|
+
str << '</c:view3D>'
|
|
83
85
|
end
|
|
86
|
+
|
|
84
87
|
end
|
|
85
88
|
end
|
data/lib/axlsx/package.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# encoding: UTF-8
|
|
2
2
|
module Axlsx
|
|
3
3
|
# Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
|
|
4
4
|
# xlsx document including valdation and serialization.
|
|
5
5
|
class Package
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
# provides access to the app doc properties for this package
|
|
9
9
|
# see App
|
|
10
10
|
attr_reader :app
|
|
@@ -17,18 +17,43 @@ module Axlsx
|
|
|
17
17
|
#
|
|
18
18
|
# @param [Hash] options A hash that you can use to specify the author and workbook for this package.
|
|
19
19
|
# @option options [String] :author The author of the document
|
|
20
|
+
# @option options [Boolean] :use_shared_strings This is passed to the workbook to specify that shared strings should be used when serializing the package.
|
|
20
21
|
# @example Package.new :author => 'you!', :workbook => Workbook.new
|
|
21
22
|
def initialize(options={})
|
|
22
23
|
@workbook = nil
|
|
23
24
|
@core, @app = Core.new, App.new
|
|
24
25
|
@core.creator = options[:author] || @core.creator
|
|
26
|
+
options.each do |o|
|
|
27
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
28
|
+
end
|
|
25
29
|
yield self if block_given?
|
|
26
30
|
end
|
|
27
31
|
|
|
32
|
+
# Shortcut to specify that the workbook should use autowidth
|
|
33
|
+
# @see Workbook#use_autowidth
|
|
34
|
+
def use_autowidth=(v)
|
|
35
|
+
Axlsx::validate_boolean(v);
|
|
36
|
+
workbook.use_autowidth = v
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Shortcut to specify that the workbook should use shared strings
|
|
41
|
+
# @see Workbook#use_shared_strings
|
|
42
|
+
def use_shared_strings=(v)
|
|
43
|
+
Axlsx::validate_boolean(v);
|
|
44
|
+
workbook.use_shared_strings = v
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Shortcut to determine if the workbook is configured to use shared strings
|
|
48
|
+
# @see Workbook#use_shared_strings
|
|
49
|
+
def use_shared_strings
|
|
50
|
+
workbook.use_shared_strings
|
|
51
|
+
end
|
|
52
|
+
|
|
28
53
|
# The workbook this package will serialize or validate.
|
|
29
54
|
# @return [Workbook] If no workbook instance has been assigned with this package a new Workbook instance is returned.
|
|
30
55
|
# @raise ArgumentError if workbook parameter is not a Workbook instance.
|
|
31
|
-
# @note As there are multiple ways to instantiate a workbook for the package,
|
|
56
|
+
# @note As there are multiple ways to instantiate a workbook for the package,
|
|
32
57
|
# here are a few examples:
|
|
33
58
|
# # assign directly during package instanciation
|
|
34
59
|
# wb = Package.new(:workbook => Workbook.new).workbook
|
|
@@ -42,13 +67,13 @@ module Axlsx
|
|
|
42
67
|
yield @workbook if block_given?
|
|
43
68
|
@workbook
|
|
44
69
|
end
|
|
45
|
-
|
|
70
|
+
|
|
46
71
|
#def self.parse(input, confirm_valid = false)
|
|
47
72
|
# p = Package.new
|
|
48
73
|
# z = Zip::ZipFile.open(input)
|
|
49
74
|
# p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN)
|
|
50
75
|
# p
|
|
51
|
-
#end
|
|
76
|
+
#end
|
|
52
77
|
|
|
53
78
|
# @see workbook
|
|
54
79
|
def workbook=(workbook) DataTypeValidator.validate "Package.workbook", Workbook, workbook; @workbook = workbook; end
|
|
@@ -57,9 +82,10 @@ module Axlsx
|
|
|
57
82
|
#
|
|
58
83
|
# @param [File] output The file you want to serialize your package to
|
|
59
84
|
# @param [Boolean] confirm_valid Validate the package prior to serialization.
|
|
85
|
+
# @option options stream indicates if we should be writing to a stream or a file. True for stream, nil for file
|
|
60
86
|
# @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
|
|
61
87
|
# @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
|
|
62
|
-
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
|
88
|
+
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
|
63
89
|
# @see Package#validate
|
|
64
90
|
# @example
|
|
65
91
|
# # This is how easy it is to create a valid xlsx file. Of course you might want to add a sheet or two, and maybe some data, styles and charts.
|
|
@@ -70,35 +96,37 @@ module Axlsx
|
|
|
70
96
|
# # You will find a file called test.xlsx
|
|
71
97
|
def serialize(output, confirm_valid=false)
|
|
72
98
|
return false unless !confirm_valid || self.validate.empty?
|
|
73
|
-
p = parts
|
|
74
99
|
Zip::ZipOutputStream.open(output) do |zip|
|
|
75
|
-
|
|
76
|
-
unless part[:doc].nil?
|
|
77
|
-
zip.put_next_entry(part[:entry]);
|
|
78
|
-
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
|
79
|
-
zip.puts(entry)
|
|
80
|
-
end
|
|
81
|
-
unless part[:path].nil?
|
|
82
|
-
zip.put_next_entry(part[:entry]);
|
|
83
|
-
# binread for 1.9.3
|
|
84
|
-
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
|
85
|
-
end
|
|
86
|
-
end
|
|
100
|
+
write_parts(zip)
|
|
87
101
|
end
|
|
88
102
|
true
|
|
89
103
|
end
|
|
90
|
-
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Serialize your workbook to a StringIO instance
|
|
107
|
+
# @param [Boolean] confirm_valid Validate the package prior to serialization.
|
|
108
|
+
# @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not.
|
|
109
|
+
def to_stream(confirm_valid=false)
|
|
110
|
+
return false unless !confirm_valid || self.validate.empty?
|
|
111
|
+
zip = write_parts(Zip::ZipOutputStream.new("streamed", true))
|
|
112
|
+
stream = zip.close_buffer
|
|
113
|
+
stream.rewind
|
|
114
|
+
stream
|
|
115
|
+
end
|
|
116
|
+
|
|
91
117
|
# Encrypt the package into a CFB using the password provided
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
# This is not ready yet
|
|
119
|
+
def encrypt(file_name, password)
|
|
120
|
+
return false
|
|
121
|
+
# moc = MsOffCrypto.new(file_name, password)
|
|
122
|
+
# moc.save
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Validate all parts of the package against xsd schema.
|
|
98
126
|
# @return [Array] An array of all validation errors found.
|
|
99
127
|
# @note This gem includes all schema from OfficeOpenXML-XMLSchema-Transitional.zip and OpenPackagingConventions-XMLSchema.zip
|
|
100
128
|
# as per ECMA-376, Third edition. opc schema require an internet connection to import remote schema from dublin core for dc,
|
|
101
|
-
# dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
|
|
129
|
+
# dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
|
|
102
130
|
# refer to the local versions.
|
|
103
131
|
#
|
|
104
132
|
# If by chance you are able to creat a package that does not validate it indicates that the internal
|
|
@@ -111,41 +139,71 @@ module Axlsx
|
|
|
111
139
|
# p.validate.each { |error| puts error.message }
|
|
112
140
|
def validate
|
|
113
141
|
errors = []
|
|
114
|
-
parts.each
|
|
142
|
+
parts.each do |part|
|
|
143
|
+
errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil?
|
|
144
|
+
end
|
|
115
145
|
errors
|
|
116
146
|
end
|
|
117
147
|
|
|
118
|
-
private
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
# Writes the package parts to a zip archive.
|
|
151
|
+
# @param [Zip::ZipOutputStream] zip
|
|
152
|
+
# @return [Zip::ZipOutputStream]
|
|
153
|
+
def write_parts(zip)
|
|
154
|
+
p = parts
|
|
155
|
+
p.each do |part|
|
|
156
|
+
unless part[:doc].nil?
|
|
157
|
+
zip.put_next_entry(part[:entry]);
|
|
158
|
+
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
|
159
|
+
zip.puts(entry)
|
|
160
|
+
end
|
|
161
|
+
unless part[:path].nil?
|
|
162
|
+
zip.put_next_entry(part[:entry]);
|
|
163
|
+
# binread for 1.9.3
|
|
164
|
+
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
zip
|
|
168
|
+
end
|
|
119
169
|
|
|
120
170
|
# The parts of a package
|
|
121
|
-
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
|
|
171
|
+
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
|
|
122
172
|
# @private
|
|
123
173
|
def parts
|
|
124
174
|
@parts = [
|
|
125
|
-
{:entry => RELS_PN, :doc => relationships.
|
|
126
|
-
{:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.
|
|
127
|
-
{:entry => CORE_PN, :doc => @core.
|
|
128
|
-
{:entry => APP_PN, :doc => @app.
|
|
129
|
-
{:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships.
|
|
130
|
-
{:entry => CONTENT_TYPES_PN, :doc => content_types.
|
|
131
|
-
{:entry => WORKBOOK_PN, :doc => workbook.
|
|
175
|
+
{:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD},
|
|
176
|
+
{:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml_string, :schema => SML_XSD},
|
|
177
|
+
{:entry => CORE_PN, :doc => @core.to_xml_string, :schema => CORE_XSD},
|
|
178
|
+
{:entry => APP_PN, :doc => @app.to_xml_string, :schema => APP_XSD},
|
|
179
|
+
{:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships.to_xml_string, :schema => RELS_XSD},
|
|
180
|
+
{:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml_string, :schema => CONTENT_TYPES_XSD},
|
|
181
|
+
{:entry => WORKBOOK_PN, :doc => workbook.to_xml_string, :schema => SML_XSD}
|
|
132
182
|
]
|
|
133
183
|
workbook.drawings.each do |drawing|
|
|
134
|
-
@parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.
|
|
135
|
-
@parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.
|
|
184
|
+
@parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
|
|
185
|
+
@parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
workbook.tables.each do |table|
|
|
189
|
+
@parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
workbook.charts.each do |chart|
|
|
193
|
+
@parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
|
|
136
194
|
end
|
|
137
|
-
|
|
138
|
-
workbook.charts.each do |chart|
|
|
139
|
-
@parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml, :schema => DRAWING_XSD}
|
|
140
|
-
end
|
|
141
195
|
|
|
142
196
|
workbook.images.each do |image|
|
|
143
197
|
@parts << {:entry => "xl/#{image.pn}", :path => image.image_src}
|
|
144
198
|
end
|
|
145
199
|
|
|
146
|
-
|
|
147
|
-
@parts << {:entry => "xl/#{
|
|
148
|
-
|
|
200
|
+
if use_shared_strings
|
|
201
|
+
@parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml_string, :schema => SML_XSD}
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
workbook.worksheets.each do |sheet|
|
|
205
|
+
@parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml_string, :schema => RELS_XSD}
|
|
206
|
+
@parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml_string, :schema => SML_XSD}
|
|
149
207
|
end
|
|
150
208
|
@parts
|
|
151
209
|
end
|
|
@@ -159,7 +217,6 @@ module Axlsx
|
|
|
159
217
|
def validate_single_doc(schema, doc)
|
|
160
218
|
schema = Nokogiri::XML::Schema(File.open(schema))
|
|
161
219
|
doc = Nokogiri::XML(doc)
|
|
162
|
-
|
|
163
220
|
errors = []
|
|
164
221
|
schema.validate(doc).each do |error|
|
|
165
222
|
errors << error
|
|
@@ -173,15 +230,19 @@ module Axlsx
|
|
|
173
230
|
def content_types
|
|
174
231
|
c_types = base_content_types
|
|
175
232
|
workbook.drawings.each do |drawing|
|
|
176
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
|
|
233
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
|
|
177
234
|
:ContentType => DRAWING_CT)
|
|
178
235
|
end
|
|
179
236
|
workbook.charts.each do |chart|
|
|
180
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
|
|
181
|
-
:ContentType => CHART_CT)
|
|
237
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
|
|
238
|
+
:ContentType => CHART_CT)
|
|
239
|
+
end
|
|
240
|
+
workbook.tables.each do |table|
|
|
241
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{table.pn}",
|
|
242
|
+
:ContentType => TABLE_CT)
|
|
182
243
|
end
|
|
183
244
|
workbook.worksheets.each do |sheet|
|
|
184
|
-
c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
|
|
245
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
|
|
185
246
|
:ContentType => WORKSHEET_CT)
|
|
186
247
|
end
|
|
187
248
|
exts = workbook.images.map { |image| image.extname }
|
|
@@ -195,6 +256,10 @@ module Axlsx
|
|
|
195
256
|
end
|
|
196
257
|
c_types << Axlsx::Default.new(:ContentType => ct, :Extension => ext )
|
|
197
258
|
end
|
|
259
|
+
if use_shared_strings
|
|
260
|
+
c_types << Axlsx::Override.new(:PartName => "/xl/#{SHARED_STRINGS_PN}",
|
|
261
|
+
:ContentType => SHARED_STRINGS_CT)
|
|
262
|
+
end
|
|
198
263
|
c_types
|
|
199
264
|
end
|
|
200
265
|
|
|
@@ -208,7 +273,7 @@ module Axlsx
|
|
|
208
273
|
c_types << Override.new(:PartName => "/#{APP_PN}", :ContentType => APP_CT)
|
|
209
274
|
c_types << Override.new(:PartName => "/#{CORE_PN}", :ContentType => CORE_CT)
|
|
210
275
|
c_types << Override.new(:PartName => "/xl/#{STYLES_PN}", :ContentType => STYLES_CT)
|
|
211
|
-
c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT)
|
|
276
|
+
c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT)
|
|
212
277
|
c_types.lock
|
|
213
278
|
c_types
|
|
214
279
|
end
|