axlsx 1.0.12 → 1.0.14
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/README.md +165 -134
- data/examples/example.rb +133 -153
- data/lib/axlsx/#cfb.xlsx# +0 -0
- data/lib/axlsx/content_type/content_type.rb +23 -0
- data/lib/axlsx/content_type/default.rb +37 -0
- data/lib/axlsx/content_type/override.rb +37 -0
- data/lib/axlsx/doc_props/app.rb +178 -0
- data/lib/axlsx/doc_props/core.rb +34 -0
- data/lib/axlsx/drawing/axis.rb +93 -0
- data/lib/axlsx/drawing/bar_3D_chart.rb +136 -0
- data/lib/axlsx/drawing/bar_series.rb +64 -0
- data/lib/axlsx/drawing/cat_axis.rb +63 -0
- data/lib/axlsx/drawing/cat_axis_data.rb +35 -0
- data/lib/axlsx/drawing/chart.rb +193 -0
- data/lib/axlsx/drawing/drawing.rb +137 -0
- data/lib/axlsx/drawing/graphic_frame.rb +52 -0
- data/lib/axlsx/drawing/line_3D_chart.rb +114 -0
- data/lib/axlsx/drawing/line_series.rb +46 -0
- data/lib/axlsx/drawing/marker.rb +61 -0
- data/lib/axlsx/drawing/one_cell_anchor.rb +89 -0
- data/lib/axlsx/drawing/pic.rb +153 -0
- data/lib/axlsx/drawing/picture_locking.rb +72 -0
- data/lib/axlsx/drawing/picture_locking.rb~ +36 -0
- data/lib/axlsx/drawing/pie_3D_chart.rb +41 -0
- data/lib/axlsx/drawing/pie_series.rb +56 -0
- data/lib/axlsx/drawing/scaling.rb +59 -0
- data/lib/axlsx/drawing/ser_axis.rb +45 -0
- data/lib/axlsx/drawing/series.rb +71 -0
- data/lib/axlsx/drawing/series_title.rb +22 -0
- data/lib/axlsx/drawing/title.rb +65 -0
- data/lib/axlsx/drawing/two_cell_anchor.rb +76 -0
- data/lib/axlsx/drawing/val_axis.rb +34 -0
- data/lib/axlsx/drawing/val_axis_data.rb +26 -0
- data/lib/axlsx/drawing/view_3D.rb +85 -0
- data/lib/axlsx/package.rb +223 -0
- data/lib/axlsx/rels/relationship.rb +44 -0
- data/lib/axlsx/rels/relationships.rb +25 -0
- data/lib/axlsx/stylesheet/border.rb +57 -0
- data/lib/axlsx/stylesheet/border_pr.rb +68 -0
- data/lib/axlsx/stylesheet/cell_alignment.rb +105 -0
- data/lib/axlsx/stylesheet/cell_protection.rb +36 -0
- data/lib/axlsx/stylesheet/cell_style.rb +65 -0
- data/lib/axlsx/stylesheet/color.rb +69 -0
- data/lib/axlsx/stylesheet/fill.rb +32 -0
- data/lib/axlsx/stylesheet/font.rb +139 -0
- data/lib/axlsx/stylesheet/gradient_fill.rb +76 -0
- data/lib/axlsx/stylesheet/gradient_stop.rb +33 -0
- data/lib/axlsx/stylesheet/num_fmt.rb +63 -0
- data/lib/axlsx/stylesheet/pattern_fill.rb +66 -0
- data/lib/axlsx/stylesheet/styles.rb +298 -0
- data/lib/axlsx/stylesheet/table_style.rb +47 -0
- data/lib/axlsx/stylesheet/table_style_element.rb +71 -0
- data/lib/axlsx/stylesheet/table_styles.rb +39 -0
- data/lib/axlsx/stylesheet/xf.rb +138 -0
- data/lib/axlsx/util/constants.rb +216 -0
- data/lib/axlsx/util/ms_off_crypto.rb +88 -0
- data/lib/axlsx/util/ms_off_crypto.rb~ +3 -0
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
- data/lib/axlsx/util/parser.rb +43 -0
- data/lib/axlsx/util/parser.rb~ +6 -0
- data/lib/axlsx/util/simple_typed_list.rb +160 -0
- data/lib/axlsx/util/validators.rb +132 -0
- data/lib/axlsx/version.rb +4 -0
- data/lib/axlsx/workbook/workbook.rb +161 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +350 -0
- data/lib/axlsx/workbook/worksheet/row.rb +107 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +335 -0
- data/lib/axlsx.rb +59 -0
- data/test/drawing/tc_axis.rb +1 -1
- data/test/drawing/tc_cat_axis.rb +1 -1
- data/test/drawing/tc_line_series.tc~ +34 -0
- data/test/drawing/tc_picture_locking.rb~ +77 -0
- data/test/tc_package.rb +10 -0
- data/test/workbook/worksheet/tc_cell.rb +15 -0
- data/test/workbook/worksheet/tc_worksheet.rb +22 -1
- metadata +117 -5
- data/examples/follow_20111202.xlsx +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# the access class defines common properties and values for a chart axis.
|
|
3
|
+
class Axis
|
|
4
|
+
|
|
5
|
+
# the id of the axis.
|
|
6
|
+
# @return [Integer]
|
|
7
|
+
attr_reader :axId
|
|
8
|
+
|
|
9
|
+
# The perpendicular axis
|
|
10
|
+
# @return [Integer]
|
|
11
|
+
attr_reader :crossAx
|
|
12
|
+
|
|
13
|
+
# The scaling of the axis
|
|
14
|
+
# @see Scaling
|
|
15
|
+
# @return [Scaling]
|
|
16
|
+
attr_reader :scaling
|
|
17
|
+
|
|
18
|
+
# The position of the axis
|
|
19
|
+
# must be one of [:l, :r, :t, :b]
|
|
20
|
+
# @return [Symbol]
|
|
21
|
+
attr_reader :axPos
|
|
22
|
+
|
|
23
|
+
# the position of the tick labels
|
|
24
|
+
# must be one of [:nextTo, :high, :low]
|
|
25
|
+
# @return [Symbol]
|
|
26
|
+
attr_reader :tickLblPos
|
|
27
|
+
|
|
28
|
+
# The number format format code for this axis
|
|
29
|
+
# default :General
|
|
30
|
+
# @return [String]
|
|
31
|
+
attr_reader :format_code
|
|
32
|
+
|
|
33
|
+
# specifies how the perpendicular axis is crossed
|
|
34
|
+
# must be one of [:autoZero, :min, :max]
|
|
35
|
+
# @return [Symbol]
|
|
36
|
+
attr_reader :crosses
|
|
37
|
+
|
|
38
|
+
# Creates an Axis object
|
|
39
|
+
# @param [Integer] axId the id of this axis
|
|
40
|
+
# @param [Integer] crossAx the id of the perpendicular axis
|
|
41
|
+
# @option options [Symbol] axPos
|
|
42
|
+
# @option options [Symbol] crosses
|
|
43
|
+
# @option options [Symbol] tickLblPos
|
|
44
|
+
# @raise [ArgumentError] If axId or crossAx are not unsigned integers
|
|
45
|
+
def initialize(axId, crossAx, options={})
|
|
46
|
+
Axlsx::validate_unsigned_int(axId)
|
|
47
|
+
Axlsx::validate_unsigned_int(crossAx)
|
|
48
|
+
@axId = axId
|
|
49
|
+
@crossAx = crossAx
|
|
50
|
+
@format_code = "General"
|
|
51
|
+
@scaling = Scaling.new(:orientation=>:minMax)
|
|
52
|
+
self.axPos = :b
|
|
53
|
+
self.tickLblPos = :nextTo
|
|
54
|
+
self.format_code = "General"
|
|
55
|
+
self.crosses = :autoZero
|
|
56
|
+
options.each do |o|
|
|
57
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
# The position of the axis
|
|
61
|
+
# must be one of [:l, :r, :t, :b]
|
|
62
|
+
def axPos=(v) RestrictionValidator.validate "#{self.class}.axPos", [:l, :r, :b, :t], v; @axPos = v; end
|
|
63
|
+
|
|
64
|
+
# the position of the tick labels
|
|
65
|
+
# must be one of [:nextTo, :high, :low1]
|
|
66
|
+
def tickLblPos=(v) RestrictionValidator.validate "#{self.class}.tickLblPos", [:nextTo, :high, :low], v; @tickLblPos = v; end
|
|
67
|
+
|
|
68
|
+
# The number format format code for this axis
|
|
69
|
+
# default :General
|
|
70
|
+
def format_code=(v) Axlsx::validate_string(v); @format_code = v; end
|
|
71
|
+
|
|
72
|
+
# specifies how the perpendicular axis is crossed
|
|
73
|
+
# must be one of [:autoZero, :min, :max]
|
|
74
|
+
def crosses=(v) RestrictionValidator.validate "#{self.class}.crosses", [:autoZero, :min, :max], v; @crosses = v; end
|
|
75
|
+
|
|
76
|
+
# Serializes the common axis
|
|
77
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
78
|
+
# @return [String]
|
|
79
|
+
def to_xml(xml)
|
|
80
|
+
xml.axId :val=>@axId
|
|
81
|
+
@scaling.to_xml(xml)
|
|
82
|
+
xml.delete :val=>0
|
|
83
|
+
xml.axPos :val=>@axPos
|
|
84
|
+
xml.majorGridlines
|
|
85
|
+
xml.numFmt :formatCode => @format_code, :sourceLinked=>"1"
|
|
86
|
+
xml.majorTickMark :val=>"none"
|
|
87
|
+
xml.minorTickMark :val=>"none"
|
|
88
|
+
xml.tickLblPos :val=>@tickLblPos
|
|
89
|
+
xml.crossAx :val=>@crossAx
|
|
90
|
+
xml.crosses :val=>@crosses
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# The Bar3DChart is a three dimentional barchart (who would have guessed?) that you can add to your worksheet.
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
# @see Chart#add_series
|
|
6
|
+
# @see Package#serialize
|
|
7
|
+
# @see README for an example
|
|
8
|
+
class Bar3DChart < Chart
|
|
9
|
+
|
|
10
|
+
# the category axis
|
|
11
|
+
# @return [CatAxis]
|
|
12
|
+
attr_reader :catAxis
|
|
13
|
+
|
|
14
|
+
# the valueaxis
|
|
15
|
+
# @return [ValAxis]
|
|
16
|
+
attr_reader :valAxis
|
|
17
|
+
|
|
18
|
+
# The direction of the bars in the chart
|
|
19
|
+
# must be one of [:bar, :col]
|
|
20
|
+
# @return [Symbol]
|
|
21
|
+
attr_reader :barDir
|
|
22
|
+
|
|
23
|
+
# space between bar or column clusters, as a percentage of the bar or column width.
|
|
24
|
+
# @return [String]
|
|
25
|
+
attr_reader :gapDepth
|
|
26
|
+
|
|
27
|
+
# space between bar or column clusters, as a percentage of the bar or column width.
|
|
28
|
+
# @return [String]
|
|
29
|
+
attr_reader :gapWidth
|
|
30
|
+
|
|
31
|
+
#grouping for a column, line, or area chart.
|
|
32
|
+
# must be one of [:percentStacked, :clustered, :standard, :stacked]
|
|
33
|
+
# @return [Symbol]
|
|
34
|
+
attr_reader :grouping
|
|
35
|
+
|
|
36
|
+
# The shabe of the bars or columns
|
|
37
|
+
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
|
38
|
+
# @return [Symbol]
|
|
39
|
+
attr_reader :shape
|
|
40
|
+
|
|
41
|
+
# validation regex for gap amount percent
|
|
42
|
+
GAP_AMOUNT_PERCENT = /0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/
|
|
43
|
+
|
|
44
|
+
# Creates a new bar chart object
|
|
45
|
+
# @param [GraphicFrame] frame The workbook that owns this chart.
|
|
46
|
+
# @option options [Cell, String] title
|
|
47
|
+
# @option options [Boolean] show_legend
|
|
48
|
+
# @option options [Symbol] barDir
|
|
49
|
+
# @option options [Symbol] grouping
|
|
50
|
+
# @option options [String] gapWidth
|
|
51
|
+
# @option options [String] gapDepth
|
|
52
|
+
# @option options [Symbol] shape
|
|
53
|
+
# @option options [Integer] rotX
|
|
54
|
+
# @option options [String] hPercent
|
|
55
|
+
# @option options [Integer] rotY
|
|
56
|
+
# @option options [String] depthPercent
|
|
57
|
+
# @option options [Boolean] rAngAx
|
|
58
|
+
# @option options [Integer] perspective
|
|
59
|
+
# @see Chart
|
|
60
|
+
# @see View3D
|
|
61
|
+
def initialize(frame, options={})
|
|
62
|
+
@barDir = :bar
|
|
63
|
+
@grouping = :clustered
|
|
64
|
+
@gapWidth, @gapDepth, @shape = nil, nil, nil
|
|
65
|
+
@catAxId = rand(8 ** 8)
|
|
66
|
+
@valAxId = rand(8 ** 8)
|
|
67
|
+
@catAxis = CatAxis.new(@catAxId, @valAxId)
|
|
68
|
+
@valAxis = ValAxis.new(@valAxId, @catAxId, :tickLblPos => :low)
|
|
69
|
+
super(frame, options)
|
|
70
|
+
@series_type = BarSeries
|
|
71
|
+
@view3D = View3D.new({:rAngAx=>1}.merge(options))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The direction of the bars in the chart
|
|
75
|
+
# must be one of [:bar, :col]
|
|
76
|
+
def barDir=(v)
|
|
77
|
+
RestrictionValidator.validate "Bar3DChart.barDir", [:bar, :col], v
|
|
78
|
+
@barDir = v
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#grouping for a column, line, or area chart.
|
|
82
|
+
# must be one of [:percentStacked, :clustered, :standard, :stacked]
|
|
83
|
+
def grouping=(v)
|
|
84
|
+
RestrictionValidator.validate "Bar3DChart.grouping", [:percentStacked, :clustered, :standard, :stacked], v
|
|
85
|
+
@grouping = v
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# space between bar or column clusters, as a percentage of the bar or column width.
|
|
89
|
+
def gapWidth=(v)
|
|
90
|
+
RegexValidator.validate "Bar3DChart.gapWidth", GAP_AMOUNT_PERCENT, v
|
|
91
|
+
@gapWidth=(v)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# space between bar or column clusters, as a percentage of the bar or column width.
|
|
95
|
+
def gapDepth=(v)
|
|
96
|
+
RegexValidator.validate "Bar3DChart.gapWidth", GAP_AMOUNT_PERCENT, v
|
|
97
|
+
@gapDepth=(v)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# The shabe of the bars or columns
|
|
101
|
+
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
|
102
|
+
def shape=(v)
|
|
103
|
+
RestrictionValidator.validate "Bar3DChart.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
|
|
104
|
+
@shape = v
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Serializes the bar chart
|
|
108
|
+
# @return [String]
|
|
109
|
+
def to_xml
|
|
110
|
+
super() do |xml|
|
|
111
|
+
xml.bar3DChart {
|
|
112
|
+
xml.barDir :val => barDir
|
|
113
|
+
xml.grouping :val=>grouping
|
|
114
|
+
xml.varyColors :val=>1
|
|
115
|
+
@series.each { |ser| ser.to_xml(xml) }
|
|
116
|
+
xml.dLbls {
|
|
117
|
+
xml.showLegendKey :val=>0
|
|
118
|
+
xml.showVal :val=>0
|
|
119
|
+
xml.showCatName :val=>0
|
|
120
|
+
xml.showSerName :val=>0
|
|
121
|
+
xml.showPercent :val=>0
|
|
122
|
+
xml.showBubbleSize :val=>0
|
|
123
|
+
}
|
|
124
|
+
xml.gapWidth :val=>@gapWidth unless @gapWidth.nil?
|
|
125
|
+
xml.gapDepth :val=>@gapDepth unless @gapDepth.nil?
|
|
126
|
+
xml.shape :val=>@shape unless @shape.nil?
|
|
127
|
+
xml.axId :val=>@catAxId
|
|
128
|
+
xml.axId :val=>@valAxId
|
|
129
|
+
xml.axId :val=>0
|
|
130
|
+
}
|
|
131
|
+
@catAxis.to_xml(xml)
|
|
132
|
+
@valAxis.to_xml(xml)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# A BarSeries defines the title, data and labels for bar charts
|
|
3
|
+
# @note The recommended way to manage series is to use Chart#add_series
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
# @see Chart#add_series
|
|
6
|
+
class BarSeries < Series
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# The data for this series.
|
|
10
|
+
# @return [Array, SimpleTypedList]
|
|
11
|
+
attr_reader :data
|
|
12
|
+
|
|
13
|
+
# The labels for this series.
|
|
14
|
+
# @return [Array, SimpleTypedList]
|
|
15
|
+
attr_reader :labels
|
|
16
|
+
|
|
17
|
+
# The shabe of the bars or columns
|
|
18
|
+
# must be one of [:percentStacked, :clustered, :standard, :stacked]
|
|
19
|
+
# @return [Symbol]
|
|
20
|
+
attr_reader :shape
|
|
21
|
+
|
|
22
|
+
# Creates a new series
|
|
23
|
+
# @option options [Array, SimpleTypedList] data
|
|
24
|
+
# @option options [Array, SimpleTypedList] labels
|
|
25
|
+
# @option options [String] title
|
|
26
|
+
# @option options [String] shape
|
|
27
|
+
# @param [Chart] chart
|
|
28
|
+
def initialize(chart, options={})
|
|
29
|
+
@shape = :box
|
|
30
|
+
super(chart, options)
|
|
31
|
+
self.labels = CatAxisData.new(options[:labels]) unless options[:labels].nil?
|
|
32
|
+
self.data = ValAxisData.new(options[:data]) unless options[:data].nil?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The shabe of the bars or columns
|
|
36
|
+
# must be one of [:percentStacked, :clustered, :standard, :stacked]
|
|
37
|
+
def shape=(v)
|
|
38
|
+
RestrictionValidator.validate "BarSeries.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
|
|
39
|
+
@shape = v
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Serializes the series
|
|
43
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
44
|
+
# @return [String]
|
|
45
|
+
def to_xml(xml)
|
|
46
|
+
super(xml) do |xml_inner|
|
|
47
|
+
@labels.to_xml(xml_inner) unless @labels.nil?
|
|
48
|
+
@data.to_xml(xml_inner) unless @data.nil?
|
|
49
|
+
xml_inner.shape :val=>@shape
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# assigns the data for this series
|
|
57
|
+
def data=(v) DataTypeValidator.validate "Series.data", [SimpleTypedList], v; @data = v; end
|
|
58
|
+
|
|
59
|
+
# assigns the labels for this series
|
|
60
|
+
def labels=(v) DataTypeValidator.validate "Series.labels", [SimpleTypedList], v; @labels = v; end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
#A CatAxis object defines a chart category axis
|
|
3
|
+
class CatAxis < Axis
|
|
4
|
+
|
|
5
|
+
# From the docs: This element specifies that this axis is a date or text axis based on the data that is used for the axis labels, not a specific choice.
|
|
6
|
+
# @return [Boolean]
|
|
7
|
+
attr_reader :auto
|
|
8
|
+
|
|
9
|
+
# specifies how the perpendicular axis is crossed
|
|
10
|
+
# must be one of [:ctr, :l, :r]
|
|
11
|
+
# @return [Symbol]
|
|
12
|
+
attr_reader :lblAlgn
|
|
13
|
+
|
|
14
|
+
# The offset of the labels
|
|
15
|
+
# must be between a string between 0 and 1000
|
|
16
|
+
# @return [Integer]
|
|
17
|
+
attr_reader :lblOffset
|
|
18
|
+
|
|
19
|
+
# regex for validating label offset
|
|
20
|
+
LBL_OFFSET_REGEX = /0*(([0-9])|([1-9][0-9])|([1-9][0-9][0-9])|1000)%/
|
|
21
|
+
|
|
22
|
+
# Creates a new CatAxis object
|
|
23
|
+
# @param [Integer] axId the id of this axis. Inherited
|
|
24
|
+
# @param [Integer] crossAx the id of the perpendicular axis. Inherited
|
|
25
|
+
# @option options [Symbol] axPos. Inherited
|
|
26
|
+
# @option options [Symbol] tickLblPos. Inherited
|
|
27
|
+
# @option options [Symbol] crosses. Inherited
|
|
28
|
+
# @option options [Boolean] auto
|
|
29
|
+
# @option options [Symbol] lblAlgn
|
|
30
|
+
# @option options [Integer] lblOffset
|
|
31
|
+
def initialize(axId, crossAx, options={})
|
|
32
|
+
self.auto = 1
|
|
33
|
+
self.lblAlgn = :ctr
|
|
34
|
+
self.lblOffset = "100%"
|
|
35
|
+
super(axId, crossAx, options)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# From the docs: This element specifies that this axis is a date or text axis based on the data that is used for the axis labels, not a specific choice.
|
|
39
|
+
def auto=(v) Axlsx::validate_boolean(v); @auto = v; end
|
|
40
|
+
|
|
41
|
+
# specifies how the perpendicular axis is crossed
|
|
42
|
+
# must be one of [:ctr, :l, :r]
|
|
43
|
+
def lblAlgn=(v) RestrictionValidator.validate "#{self.class}.lblAlgn", [:ctr, :l, :r], v; @lblAlgn = v; end
|
|
44
|
+
|
|
45
|
+
# The offset of the labels
|
|
46
|
+
# must be between a string between 0 and 1000
|
|
47
|
+
def lblOffset=(v) RegexValidator.validate "#{self.class}.lblOffset", LBL_OFFSET_REGEX, v; @lblOffset = v; end
|
|
48
|
+
|
|
49
|
+
# Serializes the category axis
|
|
50
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
51
|
+
# @return [String]
|
|
52
|
+
def to_xml(xml)
|
|
53
|
+
xml.catAx {
|
|
54
|
+
super(xml)
|
|
55
|
+
xml.auto :val=>@auto
|
|
56
|
+
xml.lblAlgn :val=>@lblAlgn
|
|
57
|
+
xml.lblOffset :val=>@lblOffset
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# The CatAxisData class serializes the category axis data for a chart
|
|
3
|
+
class CatAxisData < SimpleTypedList
|
|
4
|
+
|
|
5
|
+
# Create a new CatAxisData object
|
|
6
|
+
# @param [Array, SimpleTypedList] data the data for this category axis. This can be a simple array or a simple typed list of cells.
|
|
7
|
+
def initialize(data=[])
|
|
8
|
+
super Object
|
|
9
|
+
@list.concat data if data.is_a?(Array)
|
|
10
|
+
data.each { |i| @list << i } if data.is_a?(SimpleTypedList)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Serializes the category axis data
|
|
14
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
15
|
+
# @return [String]
|
|
16
|
+
def to_xml(xml)
|
|
17
|
+
xml.cat {
|
|
18
|
+
xml.strRef {
|
|
19
|
+
xml.f Axlsx::cell_range(@list)
|
|
20
|
+
xml.strCache {
|
|
21
|
+
xml.ptCount :val=>size
|
|
22
|
+
each_with_index do |item, index|
|
|
23
|
+
v = item.is_a?(Cell) ? item.value : item
|
|
24
|
+
xml.pt(:idx=>index) {
|
|
25
|
+
xml.v v
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module Axlsx
|
|
3
|
+
# A Chart is the superclass for specific charts
|
|
4
|
+
# @note Worksheet#add_chart is the recommended way to create charts for your worksheets.
|
|
5
|
+
# @see README for examples
|
|
6
|
+
class Chart
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# The 3D view properties for the chart
|
|
10
|
+
attr_reader :view3D
|
|
11
|
+
|
|
12
|
+
# A reference to the graphic frame that owns this chart
|
|
13
|
+
# @return [GraphicFrame]
|
|
14
|
+
attr_reader :graphic_frame
|
|
15
|
+
|
|
16
|
+
# A collection of series objects that are applied to the chart
|
|
17
|
+
# @return [SimpleTypedList]
|
|
18
|
+
attr_reader :series
|
|
19
|
+
|
|
20
|
+
# The type of series to use for this chart.
|
|
21
|
+
# @return [Series]
|
|
22
|
+
attr_reader :series_type
|
|
23
|
+
|
|
24
|
+
#TODO data labels!
|
|
25
|
+
#attr_reader :dLabls
|
|
26
|
+
|
|
27
|
+
# The title object for the chart.
|
|
28
|
+
# @return [Title]
|
|
29
|
+
attr_reader :title
|
|
30
|
+
|
|
31
|
+
# The style for the chart.
|
|
32
|
+
# see ECMA Part 1 §21.2.2.196
|
|
33
|
+
# @return [Integer]
|
|
34
|
+
attr_reader :style
|
|
35
|
+
|
|
36
|
+
# Show the legend in the chart
|
|
37
|
+
# @return [Boolean]
|
|
38
|
+
attr_reader :show_legend
|
|
39
|
+
|
|
40
|
+
# Creates a new chart object
|
|
41
|
+
# @param [GraphicalFrame] frame The frame that holds this chart.
|
|
42
|
+
# @option options [Cell, String] title
|
|
43
|
+
# @option options [Boolean] show_legend
|
|
44
|
+
def initialize(frame, options={})
|
|
45
|
+
@style = 2
|
|
46
|
+
@graphic_frame=frame
|
|
47
|
+
@graphic_frame.anchor.drawing.worksheet.workbook.charts << self
|
|
48
|
+
@series = SimpleTypedList.new Series
|
|
49
|
+
@show_legend = true
|
|
50
|
+
@series_type = Series
|
|
51
|
+
@title = Title.new
|
|
52
|
+
options.each do |o|
|
|
53
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
54
|
+
end
|
|
55
|
+
start_at *options[:start_at] if options[:start_at]
|
|
56
|
+
end_at *options[:end_at] if options[:start_at]
|
|
57
|
+
yield self if block_given?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The index of this chart in the workbooks charts collection
|
|
61
|
+
# @return [Integer]
|
|
62
|
+
def index
|
|
63
|
+
@graphic_frame.anchor.drawing.worksheet.workbook.charts.index(self)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The part name for this chart
|
|
67
|
+
# @return [String]
|
|
68
|
+
def pn
|
|
69
|
+
"#{CHART_PN % (index+1)}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The title object for the chart.
|
|
73
|
+
# @param [String, Cell] v
|
|
74
|
+
# @return [Title]
|
|
75
|
+
def title=(v)
|
|
76
|
+
DataTypeValidator.validate "#{self.class}.title", [String, Cell], v
|
|
77
|
+
if v.is_a?(String)
|
|
78
|
+
@title.text = v
|
|
79
|
+
elsif v.is_a?(Cell)
|
|
80
|
+
@title.cell = v
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Show the legend in the chart
|
|
85
|
+
# @param [Boolean] v
|
|
86
|
+
# @return [Boolean]
|
|
87
|
+
def show_legend=(v) Axlsx::validate_boolean(v); @show_legend = v; end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# The style for the chart.
|
|
91
|
+
# see ECMA Part 1 §21.2.2.196
|
|
92
|
+
# @param [Integer] v must be between 1 and 48
|
|
93
|
+
def style=(v) DataTypeValidator.validate "Chart.style", Integer, v, lambda { |arg| arg >= 1 && arg <= 48 }; @style = v; end
|
|
94
|
+
|
|
95
|
+
# backwards compatibility to allow chart.to and chart.from access to anchor markers
|
|
96
|
+
# @note This will be disconinued in version 2.0.0. Please use the end_at method
|
|
97
|
+
def to
|
|
98
|
+
@graphic_frame.anchor.to
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# backwards compatibility to allow chart.to and chart.from access to anchor markers
|
|
102
|
+
# @note This will be disconinued in version 2.0.0. please use the start_at method
|
|
103
|
+
def from
|
|
104
|
+
@graphic_frame.anchor.from
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Adds a new series to the chart's series collection.
|
|
108
|
+
# @return [Series]
|
|
109
|
+
# @see Series
|
|
110
|
+
def add_series(options={})
|
|
111
|
+
@series_type.new(self, options)
|
|
112
|
+
@series.last
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Chart Serialization
|
|
116
|
+
# serializes the chart
|
|
117
|
+
def to_xml
|
|
118
|
+
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
|
119
|
+
xml.send('c:chartSpace', :'xmlns:c' => XML_NS_C, :'xmlns:a' => XML_NS_A) {
|
|
120
|
+
xml[:c].date1904 :val => Axlsx::Workbook.date1904
|
|
121
|
+
xml[:c].style :val=>style
|
|
122
|
+
xml[:c].chart {
|
|
123
|
+
@title.to_xml(xml)
|
|
124
|
+
xml.autoTitleDeleted :val=>0
|
|
125
|
+
@view3D.to_xml(xml) unless @view3D.nil?
|
|
126
|
+
|
|
127
|
+
xml.floor { xml.thickness(:val=>0) }
|
|
128
|
+
xml.sideWall { xml.thickness(:val=>0) }
|
|
129
|
+
xml.backWall { xml.thickness(:val=>0) }
|
|
130
|
+
xml.plotArea {
|
|
131
|
+
xml.layout
|
|
132
|
+
yield xml if block_given?
|
|
133
|
+
}
|
|
134
|
+
if @show_legend
|
|
135
|
+
xml.legend {
|
|
136
|
+
xml.legendPos :val => "r"
|
|
137
|
+
xml.layout
|
|
138
|
+
xml.overlay :val => 0
|
|
139
|
+
}
|
|
140
|
+
end
|
|
141
|
+
xml.plotVisOnly :val => 1
|
|
142
|
+
xml.dispBlanksAs :val => :zero
|
|
143
|
+
xml.showDLblsOverMax :val => 1
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
end
|
|
148
|
+
builder.to_xml
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# This is a short cut method to set the start anchor position
|
|
152
|
+
# If you need finer granularity in positioning use
|
|
153
|
+
# graphic_frame.anchor.from.colOff / rowOff
|
|
154
|
+
# @param [Integer] x The column
|
|
155
|
+
# @param [Integer] y The row
|
|
156
|
+
# @return [Marker]
|
|
157
|
+
def start_at(x, y=0)
|
|
158
|
+
x, y = *parse_coord_args(x, y)
|
|
159
|
+
@graphic_frame.anchor.from.col = x
|
|
160
|
+
@graphic_frame.anchor.from.row = y
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# This is a short cut method to set the end anchor position
|
|
164
|
+
# If you need finer granularity in positioning use
|
|
165
|
+
# graphic_frame.anchor.to.colOff / rowOff
|
|
166
|
+
# @param [Integer] x The column
|
|
167
|
+
# @param [Integer] y The row
|
|
168
|
+
# @return [Marker]
|
|
169
|
+
def end_at(x, y=0)
|
|
170
|
+
x, y = *parse_coord_args(x, y)
|
|
171
|
+
@graphic_frame.anchor.to.col = x
|
|
172
|
+
@graphic_frame.anchor.to.row = y
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
private
|
|
176
|
+
|
|
177
|
+
def parse_coord_args(x, y=0)
|
|
178
|
+
if x.is_a?(String)
|
|
179
|
+
x, y = *Axlsx::name_to_indices(x)
|
|
180
|
+
end
|
|
181
|
+
if x.is_a?(Cell)
|
|
182
|
+
x, y = *x.pos
|
|
183
|
+
end
|
|
184
|
+
if x.is_a?(Array)
|
|
185
|
+
x, y = *x
|
|
186
|
+
end
|
|
187
|
+
[x, y]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def view3D=(v) DataTypeValidator.validate "#{self.class}.view3D", View3D, v; @view3D = v; end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|