1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# frozen_string_literal: true
module Axlsx
# the access class defines common properties and values for a chart axis.
class Axis
include Axlsx::OptionsParser
# Creates an Axis object
# @option options [Axis] cross_axis the perpendicular axis
# @option options [Symbol] ax_pos
# @option options [Symbol] crosses
# @option options [Symbol] tick_lbl_pos
# @raise [ArgumentError] If axi_id or cross_ax are not unsigned integers
def initialize(options = {})
@id = rand(8**8)
@format_code = "General"
@delete = @label_rotation = 0
@scaling = Scaling.new(orientation: :minMax)
@title = @color = nil
self.ax_pos = :b
self.tick_lbl_pos = :nextTo
self.format_code = "General"
self.crosses = :autoZero
self.gridlines = true
parse_options options
end
# the fill color to use in the axis shape properties. This should be a 6 character long hex string
# e.g. FF0000 for red
# @return [String]
attr_reader :color
# the id of the axis.
# @return [Integer]
attr_reader :id
alias :axID :id
# The perpendicular axis
# @return [Integer]
attr_reader :cross_axis
alias :crossAx :cross_axis
# The scaling of the axis
# @see Scaling
# @return [Scaling]
attr_reader :scaling
# The position of the axis
# must be one of [:l, :r, :t, :b]
# @return [Symbol]
attr_reader :ax_pos
alias :axPos :ax_pos
# the position of the tick labels
# must be one of [:nextTo, :high, :low]
# @return [Symbol]
attr_reader :tick_lbl_pos
alias :tickLblPos :tick_lbl_pos
# The number format format code for this axis
# default :General
# @return [String]
attr_reader :format_code
# specifies how the perpendicular axis is crossed
# must be one of [:autoZero, :min, :max]
# @return [Symbol]
attr_reader :crosses
# specifies how the degree of label rotation
# @return [Integer]
attr_reader :label_rotation
# specifies if gridlines should be shown in the chart
# @return [Boolean]
attr_reader :gridlines
# specifies if gridlines should be shown in the chart
# @return [Boolean]
attr_reader :delete
# the title for the axis. This can be a cell or a fixed string.
attr_reader :title
# The color for this axis. This value is used when rendering the axis line in the chart.
# colors should be in 6 character rbg format
# @return [String] the rbg color assinged.
# @see color
def color=(color_rgb)
@color = color_rgb
end
# The crossing axis for this axis
# @param [Axis] axis
def cross_axis=(axis)
DataTypeValidator.validate "#{self.class}.cross_axis", [Axis], axis
@cross_axis = axis
end
# The position of the axis
# must be one of [:l, :r, :t, :b]
def ax_pos=(v) RestrictionValidator.validate "#{self.class}.ax_pos", [:l, :r, :b, :t], v; @ax_pos = v; end
alias :axPos= :ax_pos=
# the position of the tick labels
# must be one of [:nextTo, :high, :low1]
def tick_lbl_pos=(v) RestrictionValidator.validate "#{self.class}.tick_lbl_pos", [:nextTo, :high, :low, :none], v; @tick_lbl_pos = v; end
alias :tickLblPos= :tick_lbl_pos=
# The number format format code for this axis
# default :General
def format_code=(v) Axlsx.validate_string(v); @format_code = v; end
# Specify if gridlines should be shown for this axis
# default true
def gridlines=(v) Axlsx.validate_boolean(v); @gridlines = v; end
# Specify if axis should be removed from the chart
# default false
def delete=(v) Axlsx.validate_boolean(v); @delete = v; end
# specifies how the perpendicular axis is crossed
# must be one of [:autoZero, :min, :max]
def crosses=(v) RestrictionValidator.validate "#{self.class}.crosses", [:autoZero, :min, :max], v; @crosses = v; end
# Specify the degree of label rotation to apply to labels
# default true
def label_rotation=(v)
Axlsx.validate_int(v)
adjusted = v.to_i * 60000
Axlsx.validate_angle(adjusted)
@label_rotation = adjusted
end
# The title object for the chart.
# @param [String, Cell] v
# @return [Title]
def title=(v)
DataTypeValidator.validate "#{self.class}.title", [String, Cell], v
@title ||= Title.new
if v.is_a?(String)
@title.text = v
elsif v.is_a?(Cell)
@title.cell = v
end
end
# Serializes the object
# @param [String] str
# @return [String]
def to_xml_string(str = +'')
str << '<c:axId val="' << @id.to_s << '"/>'
@scaling.to_xml_string str
str << '<c:delete val="' << @delete.to_s << '"/>'
str << '<c:axPos val="' << @ax_pos.to_s << '"/>'
str << '<c:majorGridlines>'
# TODO: shape properties need to be extracted into a class
if gridlines == false
str << '<c:spPr>'
str << '<a:ln>'
str << '<a:noFill/>'
str << '</a:ln>'
str << '</c:spPr>'
end
str << '</c:majorGridlines>'
@title.to_xml_string(str) unless @title.nil?
# Need to set sourceLinked to 0 if we're setting a format code on this row
# otherwise it will never take, as it will always prefer the 'General' formatting
# of the cells themselves
str << '<c:numFmt formatCode="' << @format_code << '" sourceLinked="' << (@format_code.eql?('General') ? '1' : '0') << '"/>'
str << '<c:majorTickMark val="none"/>'
str << '<c:minorTickMark val="none"/>'
str << '<c:tickLblPos val="' << @tick_lbl_pos.to_s << '"/>'
# TODO: this is also being used for series colors
# time to extract this into a class spPr - Shape Properties
if @color
str << '<c:spPr><a:ln><a:solidFill>'
str << '<a:srgbClr val="' << @color << '"/>'
str << '</a:solidFill></a:ln></c:spPr>'
end
# some potential value in implementing this in full. Very detailed!
str << '<c:txPr><a:bodyPr rot="' << @label_rotation.to_s << '"/><a:lstStyle/><a:p><a:pPr><a:defRPr/></a:pPr><a:endParaRPr/></a:p></c:txPr>'
str << '<c:crossAx val="' << @cross_axis.id.to_s << '"/>'
str << '<c:crosses val="' << @crosses.to_s << '"/>'
end
end
end
|