axlsx 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/README.md +18 -7
  2. data/examples/conditional_formatting/example_conditional_formatting.rb +72 -0
  3. data/examples/conditional_formatting/getting_barred.rb +37 -0
  4. data/examples/conditional_formatting/hitting_the_high_notes.rb +37 -0
  5. data/examples/conditional_formatting/scaled_colors.rb +39 -0
  6. data/examples/conditional_formatting/stop_and_go.rb +37 -0
  7. data/examples/example.rb +6 -2
  8. data/examples/{real_example.rb → skydrive/real_example.rb} +0 -0
  9. data/lib/axlsx.rb +1 -1
  10. data/lib/axlsx/drawing/axis.rb +16 -0
  11. data/lib/axlsx/stylesheet/dxf.rb +79 -0
  12. data/lib/axlsx/stylesheet/font.rb +2 -1
  13. data/lib/axlsx/stylesheet/styles.rb +141 -50
  14. data/lib/axlsx/stylesheet/xf.rb +2 -0
  15. data/lib/axlsx/util/constants.rb +8 -0
  16. data/lib/axlsx/util/validators.rb +44 -0
  17. data/lib/axlsx/version.rb +1 -1
  18. data/lib/axlsx/workbook/workbook.rb +6 -0
  19. data/lib/axlsx/workbook/worksheet/cfvo.rb +62 -0
  20. data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
  21. data/lib/axlsx/workbook/worksheet/color_scale.rb +76 -0
  22. data/lib/axlsx/workbook/worksheet/color_scale.rb~ +46 -0
  23. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +82 -0
  24. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +216 -0
  25. data/lib/axlsx/workbook/worksheet/data_bar.rb +97 -0
  26. data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
  27. data/lib/axlsx/workbook/worksheet/icon_set.rb +83 -0
  28. data/lib/axlsx/workbook/worksheet/icon_set.rb~ +95 -0
  29. data/lib/axlsx/workbook/worksheet/row.rb +2 -0
  30. data/lib/axlsx/workbook/worksheet/worksheet.rb +25 -3
  31. data/test/drawing/tc_axis.rb +8 -0
  32. data/test/stylesheet/tc_dxf.rb +81 -0
  33. data/test/stylesheet/tc_styles.rb +148 -2
  34. data/test/workbook/worksheet/tc_cfvo.rb +31 -0
  35. data/test/workbook/worksheet/tc_cfvo.rb~ +20 -0
  36. data/test/workbook/worksheet/tc_color_scale.rb +29 -0
  37. data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
  38. data/test/workbook/worksheet/tc_conditional_formatting.rb +173 -0
  39. data/test/workbook/worksheet/tc_data_bar.rb +39 -0
  40. data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
  41. data/test/workbook/worksheet/tc_icon_set.rb +45 -0
  42. data/test/workbook/worksheet/tc_icon_set.rb~ +0 -0
  43. data/test/workbook/worksheet/tc_row.rb +9 -2
  44. metadata +45 -27
  45. data/examples/axlsx.xlsx +0 -0
  46. data/examples/example.xlsx +0 -0
  47. data/examples/example_streamed.xlsx +0 -0
  48. data/examples/no-use_autowidth.xlsx +0 -0
  49. data/examples/shared_strings_example.xlsx +0 -0
  50. data/lib/axlsx/util/doc/_index.html +0 -84
  51. data/lib/axlsx/util/doc/class_list.html +0 -47
  52. data/lib/axlsx/util/doc/css/common.css +0 -1
  53. data/lib/axlsx/util/doc/css/full_list.css +0 -55
  54. data/lib/axlsx/util/doc/css/style.css +0 -322
  55. data/lib/axlsx/util/doc/file_list.html +0 -46
  56. data/lib/axlsx/util/doc/frames.html +0 -13
  57. data/lib/axlsx/util/doc/index.html +0 -84
  58. data/lib/axlsx/util/doc/js/app.js +0 -205
  59. data/lib/axlsx/util/doc/js/full_list.js +0 -173
  60. data/lib/axlsx/util/doc/js/jquery.js +0 -16
  61. data/lib/axlsx/util/doc/method_list.html +0 -46
  62. data/lib/axlsx/util/doc/top-level-namespace.html +0 -95
@@ -103,7 +103,8 @@ module Axlsx
103
103
  # @option options [Integer] sz
104
104
  def initialize(options={})
105
105
  options.each do |o|
106
- self.send("#{o[0]}=", o[1]) if self.respond_to? o[0]
106
+ next if o[1].nil?
107
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
107
108
  end
108
109
  end
109
110
  # @see name
@@ -14,6 +14,7 @@ module Axlsx
14
14
  require 'axlsx/stylesheet/table_style.rb'
15
15
  require 'axlsx/stylesheet/table_styles.rb'
16
16
  require 'axlsx/stylesheet/table_style_element.rb'
17
+ require 'axlsx/stylesheet/dxf.rb'
17
18
  require 'axlsx/stylesheet/xf.rb'
18
19
  require 'axlsx/stylesheet/cell_protection.rb'
19
20
 
@@ -137,6 +138,7 @@ module Axlsx
137
138
  # @option options [String] bg_color The background color to apply to the cell
138
139
  # @option options [Boolean] hidden Indicates if the cell should be hidden
139
140
  # @option options [Boolean] locked Indicates if the cell should be locked
141
+ # @option options [Symbol] type What type of style is this. Options are [:dxf, :xf]. :xf is default
140
142
  # @option options [Hash] alignment A hash defining any of the attributes used in CellAlignment
141
143
  # @see CellAlignment
142
144
  #
@@ -189,67 +191,156 @@ module Axlsx
189
191
  # ws.add_row :values => ["Q4", 2000, 20], :style=>[title, currency, percent]
190
192
  # f = File.open('example_you_got_style.xlsx', 'w')
191
193
  # p.serialize(f)
194
+ #
195
+ # @example Differential styling
196
+ # # Differential styles apply on top of cell styles. Used in Conditional Formatting. Must specify :type => :dxf, and you can't use :num_fmt.
197
+ # require "rubygems" # if that is your preferred way to manage gems!
198
+ # require "axlsx"
199
+ #
200
+ # p = Axlsx::Package.new
201
+ # wb = p.workbook
202
+ # ws = wb.add_worksheet
203
+ #
204
+ # # define your styles
205
+ # profitable = wb.styles.add_style(:bg_color => "FFFF0000",
206
+ # :fg_color=>"#FF000000",
207
+ # :type => :dxf)
208
+ #
209
+ # ws.add_row :values => ["Genreated At:", Time.now], :styles=>[nil, date_time]
210
+ # ws.add_row :values => ["Previous Year Quarterly Profits (JPY)"], :style=>title
211
+ # ws.add_row :values => ["Quarter", "Profit", "% of Total"], :style=>title
212
+ # ws.add_row :values => ["Q1", 4000, 40], :style=>[title, currency, percent]
213
+ # ws.add_row :values => ["Q2", 3000, 30], :style=>[title, currency, percent]
214
+ # ws.add_row :values => ["Q3", 1000, 10], :style=>[title, currency, percent]
215
+ # ws.add_row :values => ["Q4", 2000, 20], :style=>[title, currency, percent]
216
+ #
217
+ # ws.add_conditional_formatting("A1:A7", { :type => :cellIs, :operator => :greaterThan, :formula => "2000", :dxfId => profitable, :priority => 1 })
218
+ # f = File.open('example_differential_styling', 'w')
219
+ # p.serialize(f)
220
+ #
192
221
  def add_style(options={})
193
-
194
- numFmtId = if options[:format_code]
195
- n = @numFmts.map{ |f| f.numFmtId }.max + 1
196
- numFmts << NumFmt.new(:numFmtId => n, :formatCode=> options[:format_code])
197
- n
198
- else
199
- options[:num_fmt] || 0
200
- end
201
-
202
- borderId = options[:border] || 0
203
-
204
- if borderId.is_a?(Hash)
205
- raise ArgumentError, "border hash definitions must include both style and color" unless borderId.keys.include?(:style) && borderId.keys.include?(:color)
206
-
207
- s = borderId[:style]
208
- c = borderId[:color]
209
- edges = borderId[:edges] || [:left, :right, :top, :bottom]
210
-
211
- border = Border.new
212
- edges.each {|pr| border.prs << BorderPr.new(:name => pr, :style=>s, :color => Color.new(:rgb => c))}
213
- borderId = self.borders << border
222
+ # Default to :xf
223
+ options[:type] ||= :xf
224
+ raise ArgumentError, "Type must be one of [:xf, :dxf]" unless [:xf, :dxf].include?(options[:type] )
225
+
226
+ fill = parse_fill_options options
227
+ font = parse_font_options options
228
+ numFmt = parse_num_fmt_options options
229
+ border = parse_border_options options
230
+ alignment = parse_alignment_options options
231
+ protection = parse_protection_options options
232
+
233
+ case options[:type]
234
+ when :dxf
235
+ style = Dxf.new :fill => fill, :font => font, :numFmt => numFmt, :border => border, :alignment => alignment, :protection => protection
236
+ else
237
+ style = Xf.new :fillId=>fill || 0, :fontId=>font || 0, :numFmtId=>numFmt || 0, :borderId=>border || 0, :alignment => alignment, :protection => protection, :applyFill=>!fill.nil?, :applyFont=>!font.nil?, :applyNumberFormat =>!numFmt.nil?, :applyBorder=>!border.nil?, :applyAlignment => !alignment.nil?, :applyProtection => !protection.nil?
214
238
  end
215
239
 
216
- raise ArgumentError, "Invalid borderId" unless borderId < borders.size
240
+ options[:type] == :xf ? cellXfs << style : dxfs << style
241
+ end
217
242
 
218
- fill = if options[:bg_color]
219
- color = Color.new(:rgb=>options[:bg_color])
220
- pattern = PatternFill.new(:patternType =>:solid, :fgColor=>color)
221
- fills << Fill.new(pattern)
222
- else
223
- 0
224
- end
243
+ # parses add_style options for protection styles
244
+ # noop if options hash does not include :hide or :locked key
225
245
 
226
- fontId = if (options.values_at(:fg_color, :sz, :b, :i, :u, :strike, :outline, :shadow, :charset, :family, :font_name).length)
227
- font = Font.new()
228
- [:b, :i, :u, :strike, :outline, :shadow, :charset, :family, :sz].each { |k| font.send("#{k}=", options[k]) unless options[k].nil? }
229
- font.color = Color.new(:rgb => options[:fg_color]) unless options[:fg_color].nil?
230
- font.name = options[:font_name] unless options[:font_name].nil?
231
- fonts << font
232
- else
233
- 0
234
- end
246
+ # @option options [Boolean] hide boolean value defining cell protection attribute for hiding.
247
+ # @option options [Boolean] locked boolean value defining cell protection attribute for locking.
248
+ # @return [CellProtection]
249
+ def parse_protection_options(options={})
250
+ return if (options.keys & [:hidden, :locked]).empty?
251
+ CellProtection.new(options)
252
+ end
235
253
 
236
- applyProtection = (options[:hidden] || options[:locked]) ? 1 : 0
254
+ # parses add_style options for alignment
255
+ # noop if options hash does not include :alignment key
256
+ # @option options [Hash] alignment A hash of options to prive the CellAlignment intializer
257
+ # @return [CellAlignment]
258
+ # @see CellAlignment
259
+ def parse_alignment_options(options={})
260
+ return unless options[:alignment]
261
+ CellAlignment.new options[:alignment]
262
+ end
237
263
 
238
- xf = Xf.new(:fillId => fill, :fontId=>fontId, :applyFill=>1, :applyFont=>1, :numFmtId=>numFmtId, :borderId=>borderId, :applyProtection=>applyProtection)
264
+ # parses add_style options for fonts. If the options hash contains :type => :dxf we return a new Font object.
265
+ # if not, we return the index of the newly created font object in the styles.fonts collection.
266
+ # @note noop if none of the options described here are set on the options parameter.
267
+ # @option options [Symbol] type The type of style object we are working with (dxf or xf)
268
+ # @option options [String] fg_color The text color
269
+ # @option options [Integer] sz The text size
270
+ # @option options [Boolean] b Indicates if the text should be bold
271
+ # @option options [Boolean] i Indicates if the text should be italicised
272
+ # @option options [Boolean] u Indicates if the text should be underlined
273
+ # @option options [Boolean] strike Indicates if the text should be rendered with a strikethrough
274
+ # @option options [Boolean] outline Indicates if the text should be rendered with a shadow
275
+ # @option options [Integer] charset The character set to use.
276
+ # @option options [Integer] family The font family to use.
277
+ # @option options [String] font_name The name of the font to use
278
+ # @return [Font|Integer]
279
+ def parse_font_options(options={})
280
+ return if (options.keys & [:fg_color, :sz, :b, :i, :u, :strike, :outline, :shadow, :charset, :family, :font_name]).empty?
281
+ font = Font.new(options)
282
+ font.color = Color.new(:rgb => options[:fg_color]) if options[:fg_color]
283
+ font.name = options[:font_name] if options[:font_name]
284
+ options[:type] == :dxf ? font : fonts << font
285
+ end
239
286
 
240
- xf.applyNumberFormat = true if xf.numFmtId > 0
241
- xf.applyBorder = true if borderId > 0
287
+ # parses add_style options for fills. If the options hash contains :type => :dxf we return a Fill object. If not, we return the index of the fill after being added to the fills collection.
288
+ # @note noop if :bg_color is not specified in options
289
+ # @option options [String] bg_color The rgb color to apply to the fill
290
+ # @return [Fill|Integer]
291
+ def parse_fill_options(options={})
292
+ return unless options[:bg_color]
293
+ color = Color.new(:rgb=>options[:bg_color])
294
+ pattern = PatternFill.new(:patternType =>:solid, :fgColor=>color)
295
+ fill = Fill.new(pattern)
296
+ options[:type] == :dxf ? fill : fills << fill
297
+ end
242
298
 
243
- if options[:alignment]
244
- xf.alignment = CellAlignment.new(options[:alignment])
245
- xf.applyAlignment = true
299
+ # parses Style#add_style options for borders.
300
+ # @note noop if :border is not specified in options
301
+ # @option options [Hash|Integer] A border style definition hash or the index of an existing border. Border style definition hashes must include :style and color: key-value entries and may include an :edges entry that references an array of symbols identifying which border edges you wish to apply the style or any other valid Border initializer options. If the :edges entity is not provided the style is applied to all edges of cells that reference this style.
302
+ # @example
303
+ # #apply a thick red border to the top and bottom
304
+ # { :border => { :style => :thick, :color => "FFFF0000", :edges => [:top, :bottom] }
305
+ # @return [Border|Integer]
306
+ def parse_border_options(options={})
307
+ return unless options[:border]
308
+ b_opts = options[:border]
309
+ if b_opts.is_a?(Hash)
310
+ raise ArgumentError, (ERR_INVALID_BORDER_OPTIONS % b_opts) unless b_opts.values_at(:style, :color).size == 2
311
+ border = Border.new b_opts
312
+ (b_opts[:edges] || [:left, :right, :top, :bottom]).each do |edge|
313
+ b_options = { :name => edge, :style => b_opts[:style], :color => Color.new(:rgb => b_opts[:color]) }
314
+ border.prs << BorderPr.new(b_options)
315
+ end
316
+ options[:type] == :dxf ? border : borders << border
317
+ elsif b_opts.is_a? Integer
318
+ raise ArgumentError, (ERR_INVALID_BORDER_ID % b_opts) unless b_opts < borders.size
319
+ if options[:type] == :dxf
320
+ borders[b_opts].clone
321
+ else
322
+ border = b_opts
323
+ end
246
324
  end
325
+ end
247
326
 
248
- if applyProtection
249
- xf.protection = CellProtection.new(options)
327
+ # Parses Style#add_style options for number formatting.
328
+ # noop if neither :format_code or :num_format options are set.
329
+ # @option options [Hash] A hash describing the :format_code and/or :num_fmt integer for the style.
330
+ # @return [NumFmt|Integer]
331
+ def parse_num_fmt_options(options={})
332
+ return if (options.keys & [:format_code, :num_fmt]).empty?
333
+
334
+ #When the user provides format_code - we always need to create a new numFmt object
335
+ #When the type is :dxf we always need to create a new numFmt object
336
+ if options[:format_code] || options[:type] == :dxf
337
+ #If this is a standard xf we pull from numFmts the highest current and increment for num_fmt
338
+ options[:num_fmt] ||= (@numFmts.map{ |num_fmt| num_fmt.numFmtId }.max + 1) if options[:type] != :dxf
339
+ numFmt = NumFmt.new(:numFmtId => options[:num_fmt] || 0, :formatCode=> options[:format_code].to_s)
340
+ options[:type] == :dxf ? numFmt : (numFmts << numFmt; numFmt.numFmtId)
341
+ else
342
+ options[:num_fmt]
250
343
  end
251
-
252
- cellXfs << xf
253
344
  end
254
345
 
255
346
  # Serializes the object
@@ -306,7 +397,7 @@ module Axlsx
306
397
  @cellXfs << Xf.new(:borderId=>0, :xfId=>0, :numFmtId=>14, :fontId=>0, :fillId=>0, :applyNumberFormat=>1)
307
398
  @cellXfs.lock
308
399
 
309
- @dxfs = SimpleTypedList.new(Xf, "dxfs"); @dxfs.lock
400
+ @dxfs = SimpleTypedList.new(Dxf, "dxfs"); @dxfs.lock
310
401
  @tableStyles = TableStyles.new(:defaultTableStyle => "TableStyleMedium9", :defaultPivotStyle => "PivotStyleLight16"); @tableStyles.lock
311
402
  end
312
403
  end
@@ -85,6 +85,7 @@ module Axlsx
85
85
  # @option options [CellProtection] protection
86
86
  def initialize(options={})
87
87
  options.each do |o|
88
+ next if o[1].nil?
88
89
  self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
89
90
  end
90
91
  end
@@ -139,5 +140,6 @@ module Axlsx
139
140
  str << '</xf>'
140
141
  end
141
142
 
143
+
142
144
  end
143
145
  end
@@ -232,4 +232,12 @@ module Axlsx
232
232
  # error message for duplicate sheet names
233
233
  ERR_DUPLICATE_SHEET_NAME = "There is already a worksheet in this workbook named '%s'. Please use a unique name"
234
234
 
235
+ # error message when user does not provide color and or style options for border in Style#add_sytle
236
+ ERR_INVALID_BORDER_OPTIONS = "border hash must include both style and color. e.g. :border => { :color => 'FF000000', :style => :thin }. You provided: %s"
237
+
238
+ # error message for invalid border id reference
239
+ ERR_INVALID_BORDER_ID = "The border id you specified (%s) does not exist. Please add a border with Style#add_style before referencing its index."
240
+
241
+ # error message for invalid angles
242
+ ERR_ANGLE = "Angles must be a value between -90 and 90. You provided: %s"
235
243
  end
@@ -45,6 +45,9 @@ module Axlsx
45
45
  true
46
46
  end
47
47
 
48
+ def self.validate_angle(v)
49
+ raise ArgumentError, (ERR_ANGLE % v.inspect) unless (v >= -5400000 && v <= 5400000)
50
+ end
48
51
  # Requires that the value is a Fixnum or Integer and is greater or equal to 0
49
52
  # @param [Any] v The value validated
50
53
  # @raise [ArgumentError] raised if the value is not a Fixnum or Integer value greater or equal to 0
@@ -96,6 +99,47 @@ module Axlsx
96
99
  :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, :gray0625], v
97
100
  end
98
101
 
102
+ # Requires that the value is one of the ST_TimePeriod types
103
+ # valid time period types are today, yesterday, tomorrow, last7Days,
104
+ # thisMonth, lastMonth, nextMonth, thisWeek, lastWeek, nextWeek
105
+ def self.validate_time_period_type(v)
106
+ RestrictionValidator.validate :time_period_type, [:today, :yesterday, :tomorrow, :last7Days, :thisMonth, :lastMonth, :nextMonth, :thisWeek, :lastWeek, :nextWeek], v
107
+
108
+
109
+ end
110
+
111
+ # Requires that the value is one of the valid ST_IconSet types
112
+ # Allowed values are: 3Arrows, 3ArrowsGray, 3Flags, 3TrafficLights1, 3TrafficLights2, 3Signs, 3Symbols, 3Symbols2, 4Arrows, 4ArrowsGray, 4RedToBlack, 4Rating, 4TrafficLights, 5Arrows, 5ArrowsGray, 5Rating, 5Quarters
113
+ def self.validate_icon_set(v)
114
+ RestrictionValidator.validate :iconSet, ["3Arrows", "3ArrowsGray", "3Flags", "3TrafficLights1", "3TrafficLights2", "3Signs", "3Symbols", "3Symbols2", "4Arrows", "4ArrowsGray", "4RedToBlack", "4Rating", "4TrafficLights", "5Arrows", "5ArrowsGray", "5Rating", "5Quarters"], v
115
+ end
116
+
117
+ # Requires that the value is valid conditional formatting type.
118
+ # valid types must be one of expression, cellIs, colorScale,
119
+ # dataBar, iconSet, top10, uniqueValues, duplicateValues,
120
+ # containsText, notContainsText, beginsWith, endsWith,
121
+ # containsBlanks, notContainsBlanks, containsErrors,
122
+ # notContainsErrors, timePeriod, aboveAverage
123
+ # @param [Any] v The value validated
124
+ def self.validate_conditional_formatting_type(v)
125
+ RestrictionValidator.validate :conditional_formatting_type, [:expression, :cellIs, :colorScale, :dataBar, :iconSet, :top10, :uniqueValues, :duplicateValues, :containsText, :notContainsText, :beginsWith, :endsWith, :containsBlanks, :notContainsBlanks, :containsErrors, :notContainsErrors, :timePeriod, :aboveAverage], v
126
+ end
127
+
128
+ # Requires thatt he value is a valid conditional formatting value object type.
129
+ # valid types must be one of num, percent, max, min, formula and percentile
130
+ def self.validate_conditional_formatting_value_object_type(v)
131
+ RestrictionValidator.validate :conditional_formatting_value_object_type, [:num, :percent, :max, :min, :formula, :percentile], v
132
+ end
133
+
134
+ # Requires that the value is valid conditional formatting operator.
135
+ # valid operators must be one of lessThan, lessThanOrEqual, equal,
136
+ # notEqual, greaterThanOrEqual, greaterThan, between, notBetween,
137
+ # containsText, notContains, beginsWith, endsWith
138
+ # @param [Any] v The value validated
139
+ def self.validate_conditional_formatting_operator(v)
140
+ RestrictionValidator.validate :conditional_formatting_type, [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween, :containsText, :notContains, :beginsWith, :endsWith], v
141
+ end
142
+
99
143
  # Requires that the value is a gradient_type.
100
144
  # valid types are :linear and :path
101
145
  # @param [Any] v The value validated
@@ -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.1" unless defined? Axlsx::VERSION
8
+ VERSION="1.1.2" unless defined? Axlsx::VERSION
9
9
 
10
10
  end
@@ -4,6 +4,12 @@ module Axlsx
4
4
  require 'axlsx/workbook/worksheet/date_time_converter.rb'
5
5
  require 'axlsx/workbook/worksheet/cell.rb'
6
6
  require 'axlsx/workbook/worksheet/page_margins.rb'
7
+ require 'axlsx/workbook/worksheet/cfvo.rb'
8
+ require 'axlsx/workbook/worksheet/color_scale.rb'
9
+ require 'axlsx/workbook/worksheet/data_bar.rb'
10
+ require 'axlsx/workbook/worksheet/icon_set.rb'
11
+ require 'axlsx/workbook/worksheet/conditional_formatting.rb'
12
+ require 'axlsx/workbook/worksheet/conditional_formatting_rule.rb'
7
13
  require 'axlsx/workbook/worksheet/row.rb'
8
14
  require 'axlsx/workbook/worksheet/col.rb'
9
15
  require 'axlsx/workbook/worksheet/worksheet.rb'
@@ -0,0 +1,62 @@
1
+ module Axlsx
2
+ # Conditional Format Value Object
3
+ # Describes the values of the interpolation points in a gradient scale. This object is used by ColorScale, DataBar and IconSet classes
4
+ #
5
+ # @note The recommended way to manage these rules is via Worksheet#add_conditional_formatting
6
+ # @see Worksheet#add_conditional_formatting
7
+ # @see ConditionalFormattingRule#initialize
8
+ #
9
+ class Cfvo
10
+
11
+ # Type (ST_CfvoType)
12
+ # The type of this conditional formatting value object. options are num, percent, max, min, formula and percentile
13
+ # @return [Symbol]
14
+ attr_reader :type
15
+
16
+
17
+ # Type (xsd:boolean)
18
+ # For icon sets, determines whether this threshold value uses the greater than or equal to operator. 0 indicates 'greater than' is used instead of 'greater than or equal to'.
19
+ # The default value is true
20
+ # @return [Boolean]
21
+ attr_reader :gte
22
+
23
+
24
+ # Type (ST_Xstring)
25
+ # The value of the conditional formatting object
26
+ # This library will accept any value so long as it supports to_s
27
+ attr_reader :val
28
+
29
+ # Creates a new Cfvo object
30
+ # @option options [Symbol] type The type of conditional formatting value object
31
+ # @option options [Boolean] gte threshold value usage indicator
32
+ # @option options [String] val The value of the conditional formatting object
33
+ def initialize(options={})
34
+ @gte = true
35
+ options.each do |o|
36
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
37
+ end
38
+ end
39
+
40
+ # @see type
41
+ def type=(v); Axlsx::validate_conditional_formatting_value_object_type(v); @type = v end
42
+
43
+ # @see gte
44
+ def gte=(v); Axlsx::validate_boolean(v); @gte = v end
45
+
46
+ # @see val
47
+ def val=(v)
48
+ raise ArgumentError, "#{v.inspect} must respond to to_s" unless v.respond_to?(:to_s)
49
+ @val = v.to_s
50
+ end
51
+
52
+ # serialize the Csvo object
53
+ # @param [String] str
54
+ # @return [String]
55
+ def to_xml_string(str = '')
56
+ str << '<cfvo '
57
+ str << instance_values.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ')
58
+ str << ' />'
59
+ end
60
+
61
+ end
62
+ end
File without changes
@@ -0,0 +1,76 @@
1
+ module Axlsx
2
+ # Conditional Format Rule color scale object
3
+ # Describes a gradated color scale in this conditional formatting rule.
4
+
5
+ # @note The recommended way to manage these rules is via Worksheet#add_conditional_formatting
6
+ # @see Worksheet#add_conditional_formatting
7
+ # @see ConditionalFormattingRule#initialize
8
+ class ColorScale
9
+
10
+ # A simple typed list of cfvos
11
+ # @return [SimpleTypedList]
12
+ # @see Cfvo
13
+ attr_reader :value_objects
14
+
15
+ # A simple types list of colors
16
+ # @return [SimpleTypedList]
17
+ # @see Color
18
+ attr_reader :colors
19
+
20
+ # creates a new ColorScale object.
21
+ # This method will yield it self so you can alter the properites of the defauls conditional formating value object (cfvo and colors
22
+ # Two value objects and two colors are created on initialization and cannot be deleted.
23
+ # @see Cfvo
24
+ # @see Color
25
+ def initialize
26
+ initialize_value_objects
27
+ initialize_colors
28
+ yield self if block_given?
29
+ end
30
+
31
+ # adds a new cfvo / color pair to the color scale and returns a hash containing
32
+ # a reference to the newly created cfvo and color objects so you can alter the default properties.
33
+ # @return [Hash] a hash with :cfvo and :color keys referencing the newly added objects.
34
+ def add(options={})
35
+ @value_objects << Cfvo.new(:type => options[:type] || :min, :val => options[:val] || 0)
36
+ @colors << Color.new(:rgb => options[:color] || "FF000000")
37
+ {:cfvo => @value_objects.last, :color => @colors.last}
38
+ end
39
+
40
+
41
+ # removes the cfvo and color pair at the index specified.
42
+ # @param [Integer] index The index of the cfvo and color object to delete
43
+ # @note you cannot remove the first two cfvo and color pairs
44
+ def delete_at(index=2)
45
+ @value_objects.delete_at index
46
+ @colors.delete_at index
47
+ end
48
+
49
+ # Serialize this color_scale object data to an xml string
50
+ # @param [String] str
51
+ # @return [String]
52
+ def to_xml_string(str = '')
53
+ str << '<colorScale>'
54
+ @value_objects.each { |cfvo| cfvo.to_xml_string(str) }
55
+ @colors.each { |color| color.to_xml_string(str) }
56
+ str << '</colorScale>'
57
+ end
58
+
59
+ private
60
+
61
+ # creates the initial cfvo objects
62
+ def initialize_value_objects
63
+ @value_objects = SimpleTypedList.new Cfvo
64
+ @value_objects.concat [Cfvo.new(:type => :min, :val => 0), Cfvo.new(:type => :max, :val => 0)]
65
+ @value_objects.lock
66
+ end
67
+
68
+ # creates the initial color objects
69
+ def initialize_colors
70
+ @colors = SimpleTypedList.new Color
71
+ @colors.concat [Color.new(:rgb => "FFFF0000"), Color.new(:rgb => "FF0000FF")]
72
+ @colors.lock
73
+ end
74
+
75
+ end
76
+ end