axlsx 1.1.1 → 1.1.2

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.
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