From 24bb726fcdfb08cdac6c95668b0ea6ac6397c004 Mon Sep 17 00:00:00 2001 From: Petros Tsampoukas Date: Fri, 13 Nov 2015 18:16:09 +0200 Subject: [PATCH 1/4] Set luminance and text color for an axis --- lib/axlsx/drawing/axis.rb | 43 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) mode change 100644 => 100755 lib/axlsx/drawing/axis.rb diff --git a/lib/axlsx/drawing/axis.rb b/lib/axlsx/drawing/axis.rb old mode 100644 new mode 100755 index b2bb8fe7..67c3988b --- a/lib/axlsx/drawing/axis.rb +++ b/lib/axlsx/drawing/axis.rb @@ -76,6 +76,10 @@ def initialize(options={}) # @return [Boolean] attr_reader :gridlines + # specifies the gradient of the gridlines + # @return [Float] + attr_reader :gridlines_luminance + # specifies if gridlines should be shown in the chart # @return [Boolean] attr_reader :delete @@ -83,6 +87,10 @@ def initialize(options={}) # the title for the axis. This can be a cell or a fixed string. attr_reader :title + # Text color property + # @return [String] + attr_reader :text_color + # 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. @@ -116,6 +124,14 @@ def format_code=(v) Axlsx::validate_string(v); @format_code = v; end # default true def gridlines=(v) Axlsx::validate_boolean(v); @gridlines = v; end + # Specify the gridlines luminance + # must be a float in (0..1) + # default nil + def gridlines_luminance=(v) + DataTypeValidator.validate 'Axis.gridlines_luminance', Float, v + @gridlines_luminance = v + end + # Specify if axis should be removed from the chart # default false def delete=(v) Axlsx::validate_boolean(v); @delete = v; end @@ -146,6 +162,13 @@ def title=(v) end end + # Assigns a text color to the title + # colors should be in 6 character rbg format + def text_color=(v) + DataTypeValidator.validate 'Axis.text_color', String, v + @text_color = v + end + # Serializes the object # @param [String] str # @return [String] @@ -157,11 +180,23 @@ def to_xml_string(str = '') str << '' # TODO shape properties need to be extracted into a class if gridlines == false + # No gridlines str << '' str << '' str << '' str << '' str << '' + elsif !@gridlines_luminance.nil? then + # light gridlines + str << '' + str << '' + str << '' + str << '' + str << ('') + str << '' + str << '' + str << '' + str << '' end str << '' @title.to_xml_string(str) unless @title == nil @@ -180,7 +215,13 @@ def to_xml_string(str = '') str << '' end # some potential value in implementing this in full. Very detailed! - str << ('') + str << ('') + if @text_color.nil? then + str << '' + else + str << ('') + end + str << '' str << ('') str << ('') end From 894a2ea286024cf1c6aa0189a678890250b067db Mon Sep 17 00:00:00 2001 From: Petros Tsampoukas Date: Fri, 13 Nov 2015 18:22:27 +0200 Subject: [PATCH 2/4] Set the text color of a title --- lib/axlsx/drawing/title.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) mode change 100644 => 100755 lib/axlsx/drawing/title.rb diff --git a/lib/axlsx/drawing/title.rb b/lib/axlsx/drawing/title.rb old mode 100644 new mode 100755 index 7f2ff9f4..84a73e6d --- a/lib/axlsx/drawing/title.rb +++ b/lib/axlsx/drawing/title.rb @@ -11,6 +11,10 @@ class Title # @return [String] attr_reader :text_size + # Text color property + # @return [String] + attr_reader :text_color + # The cell that holds the text for the title. Setting this property will automatically update the text attribute. # @return [Cell] attr_reader :cell @@ -51,6 +55,13 @@ def cell=(v) v end + # Assigns a text color to the title + # colors should be in 6 character rbg format + def text_color=(v) + DataTypeValidator.validate 'Title.text_color', String, v + @text_color = v + end + # Not implemented at this time. #def layout=(v) DataTypeValidator.validate 'Title.layout', Layout, v; @layout = v; end #def overlay=(v) Axlsx::validate_boolean v; @overlay=v; end @@ -79,7 +90,15 @@ def to_xml_string(str = '') str << '' str << '' str << '' + if @text_color.nil? then str << ('') + else + str << ('') + str << '' + str << ('') + str << '' + str << '' + end str << ('' << @text.to_s << '') str << '' str << '' From 6057277d7a8473121ba63983913bd91d1e4c0a9b Mon Sep 17 00:00:00 2001 From: Petros Tsampoukas Date: Thu, 3 Dec 2015 16:44:37 +0200 Subject: [PATCH 3/4] Plot series on a secondary axis for line charts An example of the feature was added in basic_charts.rb. It also demonstrates the use of: - Text color - Title text color - Gridlines luminance --- examples/basic_charts.rb | 31 ++++++++++ lib/axlsx/drawing/axes.rb | 5 +- lib/axlsx/drawing/chart.rb | 0 lib/axlsx/drawing/line_chart.rb | 98 +++++++++++++++++++++++++++----- lib/axlsx/drawing/line_series.rb | 11 ++++ 5 files changed, 129 insertions(+), 16 deletions(-) mode change 100644 => 100755 examples/basic_charts.rb mode change 100644 => 100755 lib/axlsx/drawing/axes.rb mode change 100644 => 100755 lib/axlsx/drawing/chart.rb mode change 100644 => 100755 lib/axlsx/drawing/line_chart.rb mode change 100644 => 100755 lib/axlsx/drawing/line_series.rb diff --git a/examples/basic_charts.rb b/examples/basic_charts.rb old mode 100644 new mode 100755 index 097af57e..5aa0acb0 --- a/examples/basic_charts.rb +++ b/examples/basic_charts.rb @@ -54,5 +54,36 @@ end end +# secondary axis in line chart + wb.add_worksheet(:name => "Secondary axis") do |sheet| + sheet.add_row %w(first second) + 10.times do + sheet.add_row [ rand(24)+1, rand(24)*100+1] + end + sheet.add_chart(Axlsx::LineChart, :title => "Simple Line Chart", :rotX => 30, :rotY => 20) do |chart| + chart.start_at 0, 5 + chart.end_at 10, 25 + chart.add_series :data => sheet["A2:A11"], :title => sheet["A1"], :color => "5B9BD5", :show_marker => true, :smooth => true + chart.add_series :data => sheet["B2:B11"], :title => sheet["B1"], :color => "ED7D31", :on_primary_axis => false + + chart.catAxis.title = 'X Axis' + chart.valAxis.title = 'Primary Axis' + chart.secValAxis.title = "Secondary Axis" + + # Set the text color of the title + chart.catAxis.title.text_color = "404040" + chart.valAxis.title.text_color = "5B9BD5" + chart.secValAxis.title.text_color = "ED7D31" + + # Set the color of the axis values + chart.valAxis.text_color = "5B9BD5" + chart.secValAxis.text_color = "ED7D31" + + # Set the luminance + chart.catAxis.gridlines_luminance = 0.25 + chart.valAxis.gridlines_luminance = 0.25 + end + end + p.serialize('basic_charts.xlsx') diff --git a/lib/axlsx/drawing/axes.rb b/lib/axlsx/drawing/axes.rb old mode 100644 new mode 100755 index dff87a9b..25edd5aa --- a/lib/axlsx/drawing/axes.rb +++ b/lib/axlsx/drawing/axes.rb @@ -15,11 +15,12 @@ def initialize(options={}) end end - # [] provides assiciative access to a specic axis store in an axes + # [] provides associative access to a specic axis store in an axes # instance. # @return [Axis] def [](name) - axes.assoc(name)[1] + a = axes.assoc(name) + if a.nil? then nil else a[1] end end # Serializes the object diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb old mode 100644 new mode 100755 diff --git a/lib/axlsx/drawing/line_chart.rb b/lib/axlsx/drawing/line_chart.rb old mode 100644 new mode 100755 index a86355d5..1e60e1e3 --- a/lib/axlsx/drawing/line_chart.rb +++ b/lib/axlsx/drawing/line_chart.rb @@ -28,14 +28,28 @@ def cat_axis end alias :catAxis :cat_axis - # the category axis + # the values axis # @return [ValAxis] def val_axis axes[:val_axis] end alias :valAxis :val_axis - # must be one of [:percentStacked, :clustered, :standard, :stacked] + # the secondary category axis + # @return [sec_cat_axis] + def sec_cat_axis + axes[:sec_cat_axis] + end + alias :secCatAxis :sec_cat_axis + + # the secondary values axis + # @return [sec_val_axis] + def sec_val_axis + axes[:sec_val_axis] + end + alias :secValAxis :sec_val_axis + + # must be one of [:percentStacked, :clustered, :standard, :stacked] # @return [Symbol] attr_reader :grouping @@ -76,24 +90,80 @@ def node_name # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do - str << ("") - str << ('') - str << ('') - @series.each { |ser| ser.to_xml_string(str) } - @d_lbls.to_xml_string(str) if @d_lbls - yield if block_given? - axes.to_xml_string(str, :ids => true) - str << ("") - axes.to_xml_string(str) + if @series.all? {|s| s.on_primary_axis} then + # Only a primary val axis + super(str) do + str << ("") + str << ('') + str << ('') + @series.each { |ser| ser.to_xml_string(str) } + @d_lbls.to_xml_string(str) if @d_lbls + yield if block_given? + axes.to_xml_string(str, :ids => true) + str << ("") + axes.to_xml_string(str) + end + else + # Two value axes + super(str) do + # First axis + str << ("") + str << ('') + str << ('') + @series.select {|s| s.on_primary_axis}.each { |s| s.to_xml_string(str) } + @d_lbls.to_xml_string(str) if @d_lbls + yield if block_given? + str << ('') + str << ('') + str << ("") + + # Secondary axis + str << ("") + str << ('') + str << ('') + @series.select {|s| !s.on_primary_axis}.each { |s| s.to_xml_string(str) } + @d_lbls.to_xml_string(str) if @d_lbls + yield if block_given? + str << ('') + str << ('') + str << ("") + + # The axes + axes.to_xml_string(str) + end end end # The axes for this chart. LineCharts have a category and value - # axis. + # axis. If any series is on the secondary axis we will have two + # category and two value axes. # @return [Axes] def axes - @axes ||= Axes.new(:cat_axis => CatAxis, :val_axis => ValAxis) + if @axes.nil? then + # add the normal axes + @axes = Axes.new(:cat_axis => CatAxis, :val_axis => ValAxis) + + # add the secondary axes if needed + if @series.any? {|s| !s.on_primary_axis} then + if @axes[:sec_cat_axis].nil? then + @axes.add_axis(:sec_cat_axis, Axlsx::CatAxis) + sec_cat_axis = @axes[:sec_cat_axis] + sec_cat_axis.ax_pos = :b + sec_cat_axis.delete = 1 + sec_cat_axis.gridlines = false + end + if @axes[:sec_val_axis].nil? then + @axes.add_axis(:sec_val_axis, Axlsx::ValAxis) + sec_val_axis = @axes[:sec_val_axis] + sec_val_axis.ax_pos = :r + sec_val_axis.gridlines = false + sec_val_axis.crosses = :max + end + end + end + + # return + @axes end end end diff --git a/lib/axlsx/drawing/line_series.rb b/lib/axlsx/drawing/line_series.rb old mode 100644 new mode 100755 index 666e67c8..da380221 --- a/lib/axlsx/drawing/line_series.rb +++ b/lib/axlsx/drawing/line_series.rb @@ -31,6 +31,10 @@ class LineSeries < Series # @return [Boolean] attr_reader :smooth + # on primary or secondary axis + # @return [Boolean] + attr_reader :on_primary_axis + # Creates a new series # @option options [Array, SimpleTypedList] data # @option options [Array, SimpleTypedList] labels @@ -39,6 +43,7 @@ def initialize(chart, options={}) @show_marker = false @marker_symbol = options[:marker_symbol] ? options[:marker_symbol] : :default @smooth = false + @on_primary_axis = true @labels, @data = nil, nil super(chart, options) @labels = AxDataSource.new(:data => options[:labels]) unless options[:labels].nil? @@ -68,6 +73,12 @@ def smooth=(v) @smooth = v end + # is it on the primary axis? + def on_primary_axis=(v) + Axlsx::validate_boolean(v) + @on_primary_axis = v + end + # Serializes the object # @param [String] str # @return [String] From ce8114934631ab97ee457e55c5cfea53c2255ea5 Mon Sep 17 00:00:00 2001 From: Petros Tsampoukas Date: Thu, 3 Dec 2015 16:53:23 +0200 Subject: [PATCH 4/4] Create a chart without rounded corners --- lib/axlsx/drawing/chart.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index de87b91a..aaa688e7 100755 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -23,6 +23,7 @@ def initialize(frame, options={}) @show_legend = true @legend_position = :r @display_blanks_as = :gap + @rounded_corners = true @series_type = Series @title = Title.new @bg_color = nil @@ -98,6 +99,11 @@ def vary_colors=(v) Axlsx::validate_boolean(v); @vary_colors = v; end # @return [String] attr_reader :bg_color + # Use rounded corners for the chart? + # It defaults to true + # @return [Boolean] + attr_reader :rounded_corners + # The relationship object for this chart. # @return [Relationship] def relationship @@ -178,6 +184,11 @@ def bg_color=(v) @bg_color = v end + # Should the chart have rounded corners? + # @param [Boolean] v + # @return [Boolean] + def rounded_corners=(v) Axlsx::validate_boolean(v); @rounded_corners = v; end + # Serializes the object # @param [String] str # @return [String] @@ -185,6 +196,7 @@ def to_xml_string(str = '') str << '' str << ('') str << ('') + str << '' if !@rounded_corners str << ('') str << '' @title.to_xml_string str