axlsx 1.1.5 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -7
- data/Rakefile +2 -1
- data/examples/chart_colors.xlsx +0 -0
- data/examples/data_validation.rb +50 -0
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/examples_saved.xlsx +0 -0
- data/examples/fish.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/pareto.rb +28 -0
- data/examples/pareto.xlsx +0 -0
- data/examples/pie_chart.rb +16 -0
- data/examples/pie_chart.xlsx +0 -0
- data/examples/pie_chart_saved.xlsx +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_protection.rb +10 -0
- data/examples/sheet_protection.xlsx +0 -0
- data/examples/two_cell_anchor_image.rb +11 -0
- data/examples/two_cell_anchor_image.xlsx +0 -0
- data/examples/~$pie_chart_saved.xlsx +0 -0
- data/lib/axlsx.rb +7 -0
- data/lib/axlsx/content_type/default.rb +15 -9
- data/lib/axlsx/content_type/override.rb +10 -6
- data/lib/axlsx/doc_props/app.rb +152 -99
- data/lib/axlsx/drawing/axis.rb +30 -23
- data/lib/axlsx/drawing/bar_series.rb +1 -1
- data/lib/axlsx/drawing/drawing.rb +7 -2
- data/lib/axlsx/drawing/pic.rb +44 -4
- data/lib/axlsx/drawing/two_cell_anchor.rb +6 -1
- data/lib/axlsx/drawing/vml_shape.rb +2 -5
- data/lib/axlsx/rels/relationships.rb +1 -1
- data/lib/axlsx/stylesheet/table_style.rb +3 -3
- data/lib/axlsx/util/simple_typed_list.rb +0 -13
- data/lib/axlsx/util/validators.rb +21 -0
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +2 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +3 -4
- data/lib/axlsx/workbook/worksheet/comment.rb +3 -9
- data/lib/axlsx/workbook/worksheet/data_validation.rb +245 -0
- data/lib/axlsx/workbook/worksheet/page_setup.rb +17 -3
- data/lib/axlsx/workbook/worksheet/row.rb +34 -18
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +224 -0
- data/lib/axlsx/workbook/worksheet/table.rb +2 -2
- data/lib/axlsx/workbook/worksheet/worksheet.rb +57 -22
- data/test/doc_props/tc_app.rb +31 -1
- data/test/drawing/tc_axis.rb +12 -2
- data/test/drawing/tc_chart.rb +21 -3
- data/test/drawing/tc_drawing.rb +6 -1
- data/test/drawing/tc_hyperlink.rb +0 -5
- data/test/drawing/tc_pic.rb +22 -2
- data/test/drawing/tc_scatter_chart.rb +6 -1
- data/test/drawing/tc_two_cell_anchor.rb +1 -2
- data/test/stylesheet/tc_styles.rb +3 -4
- data/test/stylesheet/tc_table_style.rb +8 -0
- data/test/stylesheet/tc_table_style_element.rb +10 -1
- data/test/tc_package.rb +43 -15
- data/test/util/tc_simple_typed_list.rb +13 -0
- data/test/util/tc_validators.rb +7 -7
- data/test/workbook/worksheet/table/tc_table.rb +3 -3
- data/test/workbook/worksheet/tc_cell.rb +15 -6
- data/test/workbook/worksheet/tc_col.rb +9 -0
- data/test/workbook/worksheet/tc_comment.rb +8 -7
- data/test/workbook/worksheet/tc_comments.rb +8 -1
- data/test/workbook/worksheet/tc_conditional_formatting.rb +44 -0
- data/test/workbook/worksheet/tc_data_bar.rb +1 -1
- data/test/workbook/worksheet/tc_data_validation.rb +265 -0
- data/test/workbook/worksheet/tc_page_setup.rb +22 -4
- data/test/workbook/worksheet/tc_row.rb +14 -2
- data/test/workbook/worksheet/tc_sheet_protection.rb +117 -0
- data/test/workbook/worksheet/tc_worksheet.rb +29 -4
- metadata +31 -10
data/lib/axlsx/drawing/axis.rb
CHANGED
@@ -5,11 +5,13 @@ module Axlsx
|
|
5
5
|
|
6
6
|
# the id of the axis.
|
7
7
|
# @return [Integer]
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :ax_id
|
9
|
+
alias :axID :ax_id
|
9
10
|
|
10
11
|
# The perpendicular axis
|
11
12
|
# @return [Integer]
|
12
|
-
attr_reader :
|
13
|
+
attr_reader :cross_ax
|
14
|
+
alias :crossAx :cross_ax
|
13
15
|
|
14
16
|
# The scaling of the axis
|
15
17
|
# @see Scaling
|
@@ -19,12 +21,14 @@ module Axlsx
|
|
19
21
|
# The position of the axis
|
20
22
|
# must be one of [:l, :r, :t, :b]
|
21
23
|
# @return [Symbol]
|
22
|
-
attr_reader :
|
24
|
+
attr_reader :ax_pos
|
25
|
+
alias :axPos :ax_pos
|
23
26
|
|
24
27
|
# the position of the tick labels
|
25
28
|
# must be one of [:nextTo, :high, :low]
|
26
29
|
# @return [Symbol]
|
27
|
-
attr_reader :
|
30
|
+
attr_reader :tick_lbl_pos
|
31
|
+
alias :tickLblPos :tick_lbl_pos
|
28
32
|
|
29
33
|
# The number format format code for this axis
|
30
34
|
# default :General
|
@@ -49,22 +53,22 @@ module Axlsx
|
|
49
53
|
attr_reader :delete
|
50
54
|
|
51
55
|
# Creates an Axis object
|
52
|
-
# @param [Integer]
|
53
|
-
# @param [Integer]
|
54
|
-
# @option options [Symbol]
|
56
|
+
# @param [Integer] ax_id the id of this axis
|
57
|
+
# @param [Integer] cross_ax the id of the perpendicular axis
|
58
|
+
# @option options [Symbol] ax_pos
|
55
59
|
# @option options [Symbol] crosses
|
56
|
-
# @option options [Symbol]
|
57
|
-
# @raise [ArgumentError] If
|
58
|
-
def initialize(
|
59
|
-
Axlsx::validate_unsigned_int(
|
60
|
-
Axlsx::validate_unsigned_int(
|
61
|
-
@
|
62
|
-
@
|
60
|
+
# @option options [Symbol] tick_lbl_pos
|
61
|
+
# @raise [ArgumentError] If axi_id or cross_ax are not unsigned integers
|
62
|
+
def initialize(ax_id, cross_ax, options={})
|
63
|
+
Axlsx::validate_unsigned_int(ax_id)
|
64
|
+
Axlsx::validate_unsigned_int(cross_ax)
|
65
|
+
@ax_id = ax_id
|
66
|
+
@cross_ax = cross_ax
|
63
67
|
@format_code = "General"
|
64
68
|
@delete = @label_rotation = 0
|
65
69
|
@scaling = Scaling.new(:orientation=>:minMax)
|
66
|
-
self.
|
67
|
-
self.
|
70
|
+
self.ax_pos = :b
|
71
|
+
self.tick_lbl_pos = :nextTo
|
68
72
|
self.format_code = "General"
|
69
73
|
self.crosses = :autoZero
|
70
74
|
self.gridlines = true
|
@@ -72,13 +76,16 @@ module Axlsx
|
|
72
76
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
73
77
|
end
|
74
78
|
end
|
79
|
+
|
75
80
|
# The position of the axis
|
76
81
|
# must be one of [:l, :r, :t, :b]
|
77
|
-
def
|
82
|
+
def ax_pos=(v) RestrictionValidator.validate "#{self.class}.ax_pos", [:l, :r, :b, :t], v; @ax_pos = v; end
|
83
|
+
alias :axPos= :ax_pos=
|
78
84
|
|
79
85
|
# the position of the tick labels
|
80
86
|
# must be one of [:nextTo, :high, :low1]
|
81
|
-
def
|
87
|
+
def tick_lbl_pos=(v) RestrictionValidator.validate "#{self.class}.tick_lbl_pos", [:nextTo, :high, :low], v; @tick_lbl_pos = v; end
|
88
|
+
alias :tickLblPos= :tick_lbl_pos=
|
82
89
|
|
83
90
|
# The number format format code for this axis
|
84
91
|
# default :General
|
@@ -111,12 +118,12 @@ module Axlsx
|
|
111
118
|
# @param [String] str
|
112
119
|
# @return [String]
|
113
120
|
def to_xml_string(str = '')
|
114
|
-
str << '<c:axId val="' << @
|
121
|
+
str << '<c:axId val="' << @ax_id.to_s << '"/>'
|
115
122
|
@scaling.to_xml_string str
|
116
123
|
str << '<c:delete val="'<< @delete.to_s << '"/>'
|
117
|
-
str << '<c:axPos val="' << @
|
124
|
+
str << '<c:axPos val="' << @ax_pos.to_s << '"/>'
|
118
125
|
str << '<c:majorGridlines>'
|
119
|
-
if
|
126
|
+
if gridlines == false
|
120
127
|
str << '<c:spPr>'
|
121
128
|
str << '<a:ln>'
|
122
129
|
str << '<a:noFill/>'
|
@@ -127,10 +134,10 @@ module Axlsx
|
|
127
134
|
str << '<c:numFmt formatCode="' << @format_code << '" sourceLinked="1"/>'
|
128
135
|
str << '<c:majorTickMark val="none"/>'
|
129
136
|
str << '<c:minorTickMark val="none"/>'
|
130
|
-
str << '<c:tickLblPos val="' << @
|
137
|
+
str << '<c:tickLblPos val="' << @tick_lbl_pos.to_s << '"/>'
|
131
138
|
# some potential value in implementing this in full. Very detailed!
|
132
139
|
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>'
|
133
|
-
str << '<c:crossAx val="' << @
|
140
|
+
str << '<c:crossAx val="' << @cross_ax.to_s << '"/>'
|
134
141
|
str << '<c:crosses val="' << @crosses.to_s << '"/>'
|
135
142
|
end
|
136
143
|
|
@@ -42,7 +42,7 @@ module Axlsx
|
|
42
42
|
def colors=(v) DataTypeValidator.validate "BarSeries.colors", [Array], v; @colors = v end
|
43
43
|
|
44
44
|
# The shabe of the bars or columns
|
45
|
-
# must be one of [:
|
45
|
+
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
46
46
|
def shape=(v)
|
47
47
|
RestrictionValidator.validate "BarSeries.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
|
48
48
|
@shape = v
|
@@ -68,11 +68,16 @@ module Axlsx
|
|
68
68
|
@anchors = SimpleTypedList.new [TwoCellAnchor, OneCellAnchor]
|
69
69
|
end
|
70
70
|
|
71
|
-
# Adds an image to the chart
|
71
|
+
# Adds an image to the chart If th end_at option is specified we create a two cell anchor. By default we use a one cell anchor.
|
72
72
|
# @note The recommended way to manage images is to use Worksheet.add_image. Please refer to that method for documentation.
|
73
73
|
# @see Worksheet#add_image
|
74
|
+
# @return [Pic]
|
74
75
|
def add_image(options={})
|
75
|
-
|
76
|
+
if options[:end_at]
|
77
|
+
TwoCellAnchor.new(self, options).add_pic(options)
|
78
|
+
else
|
79
|
+
OneCellAnchor.new(self, options)
|
80
|
+
end
|
76
81
|
@anchors.last.object
|
77
82
|
end
|
78
83
|
|
data/lib/axlsx/drawing/pic.rb
CHANGED
@@ -90,8 +90,7 @@ module Axlsx
|
|
90
90
|
# @return [String]
|
91
91
|
def extname
|
92
92
|
File.extname(image_src).delete('.') unless image_src.nil?
|
93
|
-
end
|
94
|
-
|
93
|
+
end
|
95
94
|
# The index of this image in the workbooks images collections
|
96
95
|
# @return [Index]
|
97
96
|
def index
|
@@ -113,27 +112,32 @@ module Axlsx
|
|
113
112
|
# @param [Integer] v
|
114
113
|
# @see OneCellAnchor.width
|
115
114
|
def width
|
115
|
+
return unless @anchor.is_a?(OneCellAnchor)
|
116
116
|
@anchor.width
|
117
117
|
end
|
118
118
|
|
119
119
|
# @see width
|
120
120
|
def width=(v)
|
121
|
+
use_one_cell_anchor unless @anchor.is_a?(OneCellAnchor)
|
121
122
|
@anchor.width = v
|
122
123
|
end
|
123
124
|
|
124
125
|
# providing access to update the anchor's height attribute
|
125
126
|
# @param [Integer] v
|
126
127
|
# @see OneCellAnchor.width
|
128
|
+
# @note this is a noop if you are using a TwoCellAnchor
|
127
129
|
def height
|
128
130
|
@anchor.height
|
129
131
|
end
|
130
132
|
|
131
133
|
# @see height
|
134
|
+
# @note This is a noop if you are using a TwoCellAnchor
|
132
135
|
def height=(v)
|
136
|
+
use_one_cell_anchor unless @anchor.is_a?(OneCellAnchor)
|
133
137
|
@anchor.height = v
|
134
138
|
end
|
135
|
-
|
136
|
-
|
139
|
+
|
140
|
+
# This is a short cut method to set the start anchor position
|
137
141
|
# If you need finer granularity in positioning use
|
138
142
|
# graphic_frame.anchor.from.colOff / rowOff
|
139
143
|
# @param [Integer] x The column
|
@@ -142,6 +146,18 @@ module Axlsx
|
|
142
146
|
def start_at(x, y)
|
143
147
|
@anchor.from.col = x
|
144
148
|
@anchor.from.row = y
|
149
|
+
@anchor.from
|
150
|
+
end
|
151
|
+
|
152
|
+
# noop if not using a two cell anchor
|
153
|
+
# @param [Integer] x The column
|
154
|
+
# @param [Integer] y The row
|
155
|
+
# @return [Marker]
|
156
|
+
def end_at(x, y)
|
157
|
+
use_two_cell_anchor unless @anchor.is_a?(TwoCellAnchor)
|
158
|
+
@anchor.to.col = x
|
159
|
+
@anchor.to.row = y
|
160
|
+
@anchor.to
|
145
161
|
end
|
146
162
|
|
147
163
|
# Serializes the object
|
@@ -162,6 +178,30 @@ module Axlsx
|
|
162
178
|
str << '<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr></xdr:pic>'
|
163
179
|
|
164
180
|
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# Changes the anchor to a one cell anchor.
|
185
|
+
def use_one_cell_anchor
|
186
|
+
return if @anchor.is_a?(OneCellAnchor)
|
187
|
+
swap_anchor(OneCellAnchor.new(@anchor.drawing, :from => @anchor.from))
|
188
|
+
end
|
189
|
+
|
190
|
+
#changes the anchor type to a two cell anchor
|
191
|
+
def use_two_cell_anchor
|
192
|
+
return if @anchor.is_a?(TwoCellAnchor)
|
193
|
+
swap_anchor(TwoCellAnchor.new(@anchor.drawing)).tap do |new_anchor|
|
194
|
+
new_anchor.from.col = @anchor.from.col
|
195
|
+
new_anchor.from.row = @anchor.from.row
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# refactoring of swapping code, law of demeter be damned!
|
200
|
+
def swap_anchor(new_anchor)
|
201
|
+
new_anchor.drawing.anchors.delete(new_anchor)
|
202
|
+
@anchor.drawing.anchors[@anchor.drawing.anchors.index(@anchor)] = new_anchor
|
203
|
+
@anchor = new_anchor
|
204
|
+
end
|
165
205
|
|
166
206
|
end
|
167
207
|
end
|
@@ -34,7 +34,7 @@ module Axlsx
|
|
34
34
|
# @param [Drawing] drawing
|
35
35
|
# @param [Class] chart_type This is passed to the graphic frame for instantiation. must be Chart or a subclass of Chart
|
36
36
|
# @param object The object this anchor holds.
|
37
|
-
# @option options [Array] start_at the col, row to start at
|
37
|
+
# @option options [Array] start_at the col, row to start at THIS IS DOCUMENTED BUT NOT IMPLEMENTED HERE!
|
38
38
|
# @option options [Array] end_at the col, row to end at
|
39
39
|
def initialize(drawing, options={})
|
40
40
|
@drawing = drawing
|
@@ -49,6 +49,11 @@ module Axlsx
|
|
49
49
|
@object.chart
|
50
50
|
end
|
51
51
|
|
52
|
+
# Creates an image associated with this anchor.
|
53
|
+
def add_pic(options={})
|
54
|
+
@object = Pic.new(self, options)
|
55
|
+
end
|
56
|
+
|
52
57
|
# The index of this anchor in the drawing
|
53
58
|
# @return [Integer]
|
54
59
|
def index
|
@@ -58,6 +58,7 @@ module Axlsx
|
|
58
58
|
@top_offset = 2
|
59
59
|
@right_offset = 50
|
60
60
|
@bottom_offset = 5
|
61
|
+
@id = (0...8).map{65.+(rand(25)).chr}.join
|
61
62
|
options.each do |o|
|
62
63
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
63
64
|
end
|
@@ -99,14 +100,10 @@ module Axlsx
|
|
99
100
|
def to_xml_string(str ='')
|
100
101
|
str << <<SHAME_ON_YOU
|
101
102
|
|
102
|
-
<v:shape id="" type="#_x0000_t202"
|
103
|
-
style='position:absolute;margin-left:104pt;margin-top:2pt;width:800px;height:27pt;z-index:1;mso-wrap-style:tight'
|
104
|
-
fillcolor="#ffffa1 [80]" o:insetmode="auto">
|
105
|
-
|
103
|
+
<v:shape id="#{@id}" type="#_x0000_t202" fillcolor="#ffffa1 [80]" o:insetmode="auto">
|
106
104
|
<v:fill color2="#ffffa1 [80]"/>
|
107
105
|
<v:shadow on="t" obscured="t"/>
|
108
106
|
<v:path o:connecttype="none"/>
|
109
|
-
|
110
107
|
<v:textbox style='mso-fit-text-with-word-wrap:t'>
|
111
108
|
<div style='text-align:left'></div>
|
112
109
|
</v:textbox>
|
@@ -40,10 +40,10 @@ module Axlsx
|
|
40
40
|
# @param [String] str
|
41
41
|
# @return [String]
|
42
42
|
def to_xml_string(str = '')
|
43
|
-
|
44
|
-
|
43
|
+
attrs = instance_values.reject { |k, v| ![:name, :pivot, :table].include?(k) }
|
44
|
+
attrs[:count] = self.size
|
45
45
|
str << '<tableStyle '
|
46
|
-
str <<
|
46
|
+
str << attrs.map { |key, value| '' << key.to_s << '="' << value.to_s << '"' }.join(' ')
|
47
47
|
str << '>'
|
48
48
|
each { |table_style_el| table_style_el.to_xml_string(str) }
|
49
49
|
str << '</tableStyle>'
|
@@ -155,19 +155,6 @@ module Axlsx
|
|
155
155
|
str << '</' << el_name << '>'
|
156
156
|
end
|
157
157
|
|
158
|
-
# Serializes the list
|
159
|
-
# If the serialize_as property is set, it is used as the parent node name.
|
160
|
-
# If the serialize_as property is nil, the first item in the list of allowed_types will be used, having the first letter of the class changed to lower case.
|
161
|
-
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
162
|
-
# @return [String]
|
163
|
-
def to_xml(xml)
|
164
|
-
classname = @allowed_types[0].name.split('::').last
|
165
|
-
el_name = serialize_as || (classname[0,1].downcase + classname[1..-1])
|
166
|
-
xml.send(el_name, :count=>@list.size) {
|
167
|
-
@list.each { |item| item.to_xml(xml) }
|
168
|
-
}
|
169
|
-
end
|
170
|
-
|
171
158
|
end
|
172
159
|
|
173
160
|
|
@@ -217,4 +217,25 @@ module Axlsx
|
|
217
217
|
RestrictionValidator.validate :table_element_type, [:wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues], v
|
218
218
|
end
|
219
219
|
|
220
|
+
# Requires that the value is a valid data_validation_error_style
|
221
|
+
# :information, :stop, :warning
|
222
|
+
# @param [Any] v The value validated
|
223
|
+
def self.validate_data_validation_error_style(v)
|
224
|
+
RestrictionValidator.validate :validate_data_validation_error_style, [:information, :stop, :warning], v
|
225
|
+
end
|
226
|
+
|
227
|
+
# Requires that the value is valid data validation operator.
|
228
|
+
# valid operators must be one of lessThan, lessThanOrEqual, equal,
|
229
|
+
# notEqual, greaterThanOrEqual, greaterThan, between, notBetween
|
230
|
+
# @param [Any] v The value validated
|
231
|
+
def self.validate_data_validation_operator(v)
|
232
|
+
RestrictionValidator.validate :data_validation_operator, [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween], v
|
233
|
+
end
|
234
|
+
|
235
|
+
# Requires that the value is valid data validation type.
|
236
|
+
# valid types must be one of custom, data, decimal, list, none, textLength, time, whole
|
237
|
+
# @param [Any] v The value validated
|
238
|
+
def self.validate_data_validation_type(v)
|
239
|
+
RestrictionValidator.validate :data_validation_type, [:custom, :data, :decimal, :list, :none, :textLength, :time, :whole], v
|
240
|
+
end
|
220
241
|
end
|
data/lib/axlsx/version.rb
CHANGED
@@ -5,6 +5,6 @@ module Axlsx
|
|
5
5
|
# When using bunle exec rake and referencing the gem on github or locally
|
6
6
|
# it will use the gemspec, which preloads this constant for the gem's version.
|
7
7
|
# We check to make sure that it has not already been loaded
|
8
|
-
VERSION="1.1.
|
8
|
+
VERSION="1.1.6" unless defined? Axlsx::VERSION
|
9
9
|
|
10
10
|
end
|
@@ -16,9 +16,11 @@ require 'axlsx/workbook/worksheet/row.rb'
|
|
16
16
|
require 'axlsx/workbook/worksheet/col.rb'
|
17
17
|
require 'axlsx/workbook/worksheet/comments.rb'
|
18
18
|
require 'axlsx/workbook/worksheet/comment.rb'
|
19
|
+
require 'axlsx/workbook/worksheet/sheet_protection.rb'
|
19
20
|
require 'axlsx/workbook/worksheet/worksheet.rb'
|
20
21
|
require 'axlsx/workbook/shared_strings_table.rb'
|
21
22
|
require 'axlsx/workbook/worksheet/table.rb'
|
23
|
+
require 'axlsx/workbook/worksheet/data_validation.rb'
|
22
24
|
|
23
25
|
# The Workbook class is an xlsx workbook that manages worksheets, charts, drawings and styles.
|
24
26
|
# The following parts of the Office Open XML spreadsheet specification are not implimented in this version.
|
@@ -195,7 +195,7 @@ module Axlsx
|
|
195
195
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
196
196
|
def initialize(row, value="", options={})
|
197
197
|
self.row=row
|
198
|
-
@font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
198
|
+
@value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
199
199
|
@condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
|
200
200
|
@styles = row.worksheet.workbook.styles
|
201
201
|
@row.cells << self
|
@@ -261,9 +261,8 @@ module Axlsx
|
|
261
261
|
# @return [String]
|
262
262
|
def run_xml_string(str = '')
|
263
263
|
if is_text_run?
|
264
|
-
data =
|
264
|
+
data = instance_values.reject{|key, value| value == nil || key == 'value' || key == 'type' }
|
265
265
|
keys = data.keys & INLINE_STYLES
|
266
|
-
keys.delete ['value', 'type']
|
267
266
|
str << "<r><rPr>"
|
268
267
|
keys.each do |key|
|
269
268
|
case key
|
@@ -272,7 +271,7 @@ module Axlsx
|
|
272
271
|
when 'color'
|
273
272
|
str << data[key].to_xml_string
|
274
273
|
else
|
275
|
-
"<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
274
|
+
str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
276
275
|
end
|
277
276
|
end
|
278
277
|
str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
|
@@ -41,12 +41,6 @@ module Axlsx
|
|
41
41
|
@vml_shape ||= initialize_vml_shape
|
42
42
|
end
|
43
43
|
|
44
|
-
# The index of this comment
|
45
|
-
# @return [Integer]
|
46
|
-
def index
|
47
|
-
@comments.index(self)
|
48
|
-
end
|
49
|
-
|
50
44
|
#
|
51
45
|
# The index of this author in a unique sorted list of all authors in
|
52
46
|
# the comment.
|
@@ -96,10 +90,10 @@ module Axlsx
|
|
96
90
|
def initialize_vml_shape
|
97
91
|
pos = Axlsx::name_to_indices(ref)
|
98
92
|
@vml_shape = VmlShape.new(:row => pos[1], :column => pos[0]) do |vml|
|
99
|
-
vml.left_column = vml.
|
100
|
-
vml.right_column = vml.column +
|
93
|
+
vml.left_column = vml.column
|
94
|
+
vml.right_column = vml.column + 2
|
101
95
|
vml.top_row = vml.row
|
102
|
-
|
96
|
+
vml.bottom_row = vml.row + 4
|
103
97
|
end
|
104
98
|
end
|
105
99
|
|
@@ -0,0 +1,245 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Axlsx
|
3
|
+
# Data validation allows the validation of cell data
|
4
|
+
#
|
5
|
+
# @note The recommended way to manage data validations is via Worksheet#add_data_validation
|
6
|
+
# @see Worksheet#add_data_validation
|
7
|
+
class DataValidation
|
8
|
+
|
9
|
+
# instance values that must be serialized as their own elements - e.g. not attributes.
|
10
|
+
CHILD_ELEMENTS = [:formula1, :formula2]
|
11
|
+
|
12
|
+
# Formula1
|
13
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
14
|
+
# @see type
|
15
|
+
# @return [String]
|
16
|
+
# default nil
|
17
|
+
attr_reader :formula1
|
18
|
+
|
19
|
+
# Formula2
|
20
|
+
# Available for type whole, decimal, date, time, textLength
|
21
|
+
# @see type
|
22
|
+
# @return [String]
|
23
|
+
# default nil
|
24
|
+
attr_reader :formula2
|
25
|
+
|
26
|
+
# Allow Blank
|
27
|
+
# A boolean value indicating whether the data validation allows the use of empty or blank
|
28
|
+
# entries. 1 means empty entries are OK and do not violate the validation constraints.
|
29
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
30
|
+
# @see type
|
31
|
+
# @return [Boolean]
|
32
|
+
# default true
|
33
|
+
attr_reader :allowBlank
|
34
|
+
|
35
|
+
# Error Message
|
36
|
+
# Message text of error alert.
|
37
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
38
|
+
# @see type
|
39
|
+
# @return [String]
|
40
|
+
# default nil
|
41
|
+
attr_reader :error
|
42
|
+
|
43
|
+
# Error Style (ST_DataValidationErrorStyle)
|
44
|
+
# The style of error alert used for this data validation.
|
45
|
+
# Options are:
|
46
|
+
# * information: This data validation error style uses an information icon in the error alert.
|
47
|
+
# * stop: This data validation error style uses a stop icon in the error alert.
|
48
|
+
# * warning: This data validation error style uses a warning icon in the error alert.
|
49
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
50
|
+
# @see type
|
51
|
+
# @return [Symbol]
|
52
|
+
# default :stop
|
53
|
+
attr_reader :errorStyle
|
54
|
+
|
55
|
+
# Error Title
|
56
|
+
# Title bar text of error alert.
|
57
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
58
|
+
# @see type
|
59
|
+
# @return [String]
|
60
|
+
# default nil
|
61
|
+
attr_reader :errorTitle
|
62
|
+
|
63
|
+
# Operator (ST_DataValidationOperator)
|
64
|
+
# The relational operator used with this data validation.
|
65
|
+
# Options are:
|
66
|
+
# * between: Data validation which checks if a value is between two other values.
|
67
|
+
# * equal: Data validation which checks if a value is equal to a specified value.
|
68
|
+
# * greater_than: Data validation which checks if a value is greater than a specified value.
|
69
|
+
# * greater_than_or_equal: Data validation which checks if a value is greater than or equal to a specified value.
|
70
|
+
# * less_than: Data validation which checks if a value is less than a specified value.
|
71
|
+
# * less_than_or_equal: Data validation which checks if a value is less than or equal to a specified value.
|
72
|
+
# * not_between: Data validation which checks if a value is not between two other values.
|
73
|
+
# * not_equal: Data validation which checks if a value is not equal to a specified value.
|
74
|
+
# Available for type whole, decimal, date, time, textLength
|
75
|
+
# @see type
|
76
|
+
# @return [Symbol]
|
77
|
+
# default nil
|
78
|
+
attr_reader :operator
|
79
|
+
|
80
|
+
# Input prompt
|
81
|
+
# Message text of input prompt.
|
82
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
83
|
+
# @see type
|
84
|
+
# @return [String]
|
85
|
+
# default nil
|
86
|
+
attr_reader :prompt
|
87
|
+
|
88
|
+
# Prompt title
|
89
|
+
# Title bar text of input prompt.
|
90
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
91
|
+
# @see type
|
92
|
+
# @return [String]
|
93
|
+
# default nil
|
94
|
+
attr_reader :promptTitle
|
95
|
+
|
96
|
+
# Show drop down
|
97
|
+
# A boolean value indicating whether to display a dropdown combo box for a list type data
|
98
|
+
# validation. Be careful: false shows the dropdown list!
|
99
|
+
# Available for type list
|
100
|
+
# @see type
|
101
|
+
# @return [Boolean]
|
102
|
+
# default false
|
103
|
+
attr_reader :showDropDown
|
104
|
+
|
105
|
+
# Show error message
|
106
|
+
# A boolean value indicating whether to display the error alert message when an invalid
|
107
|
+
# value has been entered, according to the criteria specified.
|
108
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
109
|
+
# @see type
|
110
|
+
# @return [Boolean]
|
111
|
+
# default false
|
112
|
+
attr_reader :showErrorMessage
|
113
|
+
|
114
|
+
# Show input message
|
115
|
+
# A boolean value indicating whether to display the input prompt message.
|
116
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
117
|
+
# @see type
|
118
|
+
# @return [Boolean]
|
119
|
+
# default false
|
120
|
+
attr_reader :showInputMessage
|
121
|
+
|
122
|
+
# Range over which data validation is applied, in "A1:B2" format
|
123
|
+
# Available for type whole, decimal, date, time, textLength, list, custom
|
124
|
+
# @see type
|
125
|
+
# @return [String]
|
126
|
+
# default nil
|
127
|
+
attr_reader :sqref
|
128
|
+
|
129
|
+
# The type (ST_DataValidationType) of data validation.
|
130
|
+
# Options are:
|
131
|
+
# * custom: Data validation which uses a custom formula to check the cell value.
|
132
|
+
# * date: Data validation which checks for date values satisfying the given condition.
|
133
|
+
# * decimal: Data validation which checks for decimal values satisfying the given condition.
|
134
|
+
# * list: Data validation which checks for a value matching one of list of values.
|
135
|
+
# * none: No data validation.
|
136
|
+
# * textLength: Data validation which checks for text values, whose length satisfies the given condition.
|
137
|
+
# * time: Data validation which checks for time values satisfying the given condition.
|
138
|
+
# * whole: Data validation which checks for whole number values satisfying the given condition.
|
139
|
+
# @return [Symbol]
|
140
|
+
# default none
|
141
|
+
attr_reader :type
|
142
|
+
|
143
|
+
# Creates a new {DataValidation} object
|
144
|
+
# @option options [String] formula1
|
145
|
+
# @option options [String] formula2
|
146
|
+
# @option options [Boolean] allowBlank - A boolean value indicating whether the data validation allows the use of empty or blank entries.
|
147
|
+
# @option options [String] error - Message text of error alert.
|
148
|
+
# @option options [Symbol] errorStyle - The style of error alert used for this data validation.
|
149
|
+
# @option options [String] errorTitle - itle bar text of error alert.
|
150
|
+
# @option options [Symbol] operator - The relational operator used with this data validation.
|
151
|
+
# @option options [String] prompt - Message text of input prompt.
|
152
|
+
# @option options [String] promptTitle - Title bar text of input prompt.
|
153
|
+
# @option options [Boolean] showDropDown - A boolean value indicating whether to display a dropdown combo box for a list type data validation
|
154
|
+
# @option options [Boolean] showErrorMessage - A boolean value indicating whether to display the error alert message when an invalid value has been entered, according to the criteria specified.
|
155
|
+
# @option options [Boolean] showInputMessage - A boolean value indicating whether to display the input prompt message.
|
156
|
+
# @option options [String] sqref - Range over which data validation is applied, in "A1:B2" format.
|
157
|
+
# @option options [Symbol] type - The type of data validation.
|
158
|
+
def initialize(options={})
|
159
|
+
# defaults
|
160
|
+
@formula1 = @formula2 = @error = @errorTitle = @operator = @prompt = @promptTitle = @sqref = nil
|
161
|
+
@allowBlank = @showErrorMessage = true
|
162
|
+
@showDropDown = @showInputMessage = false
|
163
|
+
@type = :none
|
164
|
+
@errorStyle = :stop
|
165
|
+
|
166
|
+
options.each do |o|
|
167
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# @see formula1
|
172
|
+
def formula1=(v); Axlsx::validate_string(v); @formula1 = v end
|
173
|
+
|
174
|
+
# @see formula2
|
175
|
+
def formula2=(v); Axlsx::validate_string(v); @formula2 = v end
|
176
|
+
|
177
|
+
# @see allowBlank
|
178
|
+
def allowBlank=(v); Axlsx::validate_boolean(v); @allowBlank = v end
|
179
|
+
|
180
|
+
# @see error
|
181
|
+
def error=(v); Axlsx::validate_string(v); @error = v end
|
182
|
+
|
183
|
+
# @see errorStyle
|
184
|
+
def errorStyle=(v); Axlsx::validate_data_validation_error_style(v); @errorStyle = v end
|
185
|
+
|
186
|
+
# @see errorTitle
|
187
|
+
def errorTitle=(v); Axlsx::validate_string(v); @errorTitle = v end
|
188
|
+
|
189
|
+
# @see operator
|
190
|
+
def operator=(v); Axlsx::validate_data_validation_operator(v); @operator = v end
|
191
|
+
|
192
|
+
# @see prompt
|
193
|
+
def prompt=(v); Axlsx::validate_string(v); @prompt = v end
|
194
|
+
|
195
|
+
# @see promptTitle
|
196
|
+
def promptTitle=(v); Axlsx::validate_string(v); @promptTitle = v end
|
197
|
+
|
198
|
+
# @see showDropDown
|
199
|
+
def showDropDown=(v); Axlsx::validate_boolean(v); @showDropDown = v end
|
200
|
+
|
201
|
+
# @see showErrorMessage
|
202
|
+
def showErrorMessage=(v); Axlsx::validate_boolean(v); @showErrorMessage = v end
|
203
|
+
|
204
|
+
# @see showInputMessage
|
205
|
+
def showInputMessage=(v); Axlsx::validate_boolean(v); @showInputMessage = v end
|
206
|
+
|
207
|
+
# @see sqref
|
208
|
+
def sqref=(v); Axlsx::validate_string(v); @sqref = v end
|
209
|
+
|
210
|
+
# @see type
|
211
|
+
def type=(v); Axlsx::validate_data_validation_type(v); @type = v end
|
212
|
+
|
213
|
+
# Serializes the data validation
|
214
|
+
# @param [String] str
|
215
|
+
# @return [String]
|
216
|
+
def to_xml_string(str = '')
|
217
|
+
valid_attributes = get_valid_attributes
|
218
|
+
|
219
|
+
str << '<dataValidation '
|
220
|
+
str << instance_values.map { |key, value| '' << key << '="' << value.to_s << '"' if (valid_attributes.include?(key.to_sym) and not CHILD_ELEMENTS.include?(key.to_sym)) }.join(' ')
|
221
|
+
str << '>'
|
222
|
+
str << '<formula1>' << self.formula1 << '</formula1>' if @formula1 and valid_attributes.include?(:formula1)
|
223
|
+
str << '<formula2>' << self.formula2 << '</formula2>' if @formula2 and valid_attributes.include?(:formula2)
|
224
|
+
str << '</dataValidation>'
|
225
|
+
end
|
226
|
+
|
227
|
+
private
|
228
|
+
def get_valid_attributes
|
229
|
+
attributes = [:allowBlank, :error, :errorStyle, :errorTitle, :prompt, :promptTitle, :showErrorMessage, :showInputMessage, :sqref, :type ]
|
230
|
+
|
231
|
+
if [:whole, :decimal, :data, :time, :textLength].include?(@type)
|
232
|
+
attributes << [:operator, :formula1]
|
233
|
+
attributes << [:formula2] if [:between, :notBetween].include?(@operator)
|
234
|
+
elsif @type == :list
|
235
|
+
attributes << [:showDropDown, :formula1]
|
236
|
+
elsif @type == :custom
|
237
|
+
attributes << [:formula1]
|
238
|
+
else
|
239
|
+
attributes = []
|
240
|
+
end
|
241
|
+
|
242
|
+
attributes.flatten!
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|