lib/write_xlsx/chart.rb in write_xlsx-0.70.0 vs lib/write_xlsx/chart.rb in write_xlsx-0.71.0
- old
+ new
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
require 'write_xlsx/package/xml_writer_simple'
require 'write_xlsx/utility'
require 'write_xlsx/chart/axis'
+require 'write_xlsx/chart/caption'
+require 'write_xlsx/chart/series'
module Writexlsx
class Table
include Writexlsx::Utility
@@ -31,471 +33,10 @@
def attributes
['val', 1]
end
end
- # ==SYNOPSIS
- #
- # To create a simple Excel file with a chart using WriteXLSX:
- #
- # require 'rubygems'
- # require 'write_xlsx'
- #
- # workbook = WriteXLSX.new('chart.xlsx')
- # worksheet = workbook.add_worksheet
- #
- # # Add the worksheet data the chart refers to.
- # data = [
- # [ 'Category', 2, 3, 4, 5, 6, 7 ],
- # [ 'Value', 1, 4, 5, 2, 1, 5 ]
- # ]
- #
- # worksheet.write( 'A1', data )
- #
- # # Add a worksheet chart.
- # chart = workbook.add_chart( type => 'column' )
- #
- # # Configure the chart.
- # chart.add_series(
- # :categories => '=Sheet1!$A$2:$A$7',
- # :values => '=Sheet1!$B$2:$B$7'
- # )
- #
- # workbook.close
- #
- # ==DESCRIPTION
- #
- # The Chart is an abstract base class for modules that implement
- # charts in WriteXLSX. The information below is applicable to all of
- # the available subclasses.
- #
- # The Chart isn't used directly. A chart object is created via
- # the {WriteXLXS#add_chart()}
- # method where the chart type is specified:
- #
- # chart = workbook.add_chart( :type => 'column' )
- #
- # Currently the supported chart types are:
- #
- # ===area
- # Creates an Area (filled line) style chart. See Writexlsx::Chart::Area.
- #
- # ===bar
- # Creates a Bar style (transposed histogram) chart. See Writexlsx::Chart::Bar.
- #
- # ===column
- # Creates a Column style (histogram) chart. See Writexlsx::Chart::Column.
- #
- # ===line
- # Creates a Line style chart. See Writexlsx::Chart::Line.
- #
- # ===pie
- # Creates a Pie style chart. See Writexlsx::Chart::Pie.
- #
- # ===scatter
- # Creates a Scatter style chart. See Writexlsx::Chart::Scatter.
- #
- # ===stock
- # Creates a Stock style chart. See Writexlsx::Chart::Stock.
- #
- # ===radar
- # Creates a Radar style chart. See Writexlsx::Chart::Radar.
- #
- # Chart subtypes are also supported in some cases:
- #
- # workbook.add_chart(:type => 'bar', :subtype => 'stacked')
- #
- # The currently available subtypes are:
- #
- # area
- # stacked
- # percent_stacked
- #
- # bar
- # stacked
- # percent_stacked
- #
- # column
- # stacked
- # percent_stacked
- #
- # scatter
- # straight_with_markers
- # straight
- # smooth_with_markers
- # smooth
- #
- # radar
- # with_markers
- # filled
- #
- # ==CHART FORMATTING
- #
- # The following chart formatting properties can be set for any chart object
- # that they apply to (and that are supported by WriteXLSX) such
- # as chart lines, column fill areas, plot area borders, markers and other
- # chart elements documented above.
- #
- # line
- # border
- # fill
- # marker
- # trendline
- # data_labels
- #
- # Chart formatting properties are generally set using hash refs.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { color => 'blue' }
- # )
- #
- # In some cases the format properties can be nested. For example a marker
- # may contain border and fill sub-properties.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { color => 'blue' },
- # :marker => {
- # :type => 'square',
- # :size => 5,
- # :border => { color => 'red' },
- # :fill => { color => 'yellow' }
- # }
- # )
- #
- # ===Line
- #
- # The line format is used to specify properties of line objects that appear
- # in a chart such as a plotted line on a chart or a border.
- #
- # The following properties can be set for line formats in a chart.
- #
- # none
- # color
- # width
- # dash_type
- # The none property is uses to turn the line off (it is always on by default
- # except in Scatter charts). This is useful if you wish to plot a series
- # with markers but without a line.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { none => 1 }
- # )
- # The color property sets the color of the line.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { color => 'red' }
- # )
- # The available colors are shown in the main WriteXLSX documentation.
- # It is also possible to set the color of a line with a HTML style RGB color:
- #
- # chart.add_series(
- # :line => { color => '#FF0000' }
- # )
- # The width property sets the width of the line. It should be specified
- # in increments of 0.25 of a point as in Excel.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { width => 3.25 }
- # )
- # The dash_type property sets the dash style of the line.
- #
- # chart->add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => { dash_type => 'dash_dot' }
- # )
- # The following dash_type values are available. They are shown in the
- # order that they appear in the Excel dialog.
- #
- # solid
- # round_dot
- # square_dot
- # dash
- # dash_dot
- # long_dash
- # long_dash_dot
- # long_dash_dot_dot
- # The default line style is solid.
- #
- # More than one line property can be specified at time:
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :line => {
- # :color => 'red',
- # :width => 1.25,
- # :dash_type => 'square_dot'
- # }
- # )
- # ===Border
- #
- # The border property is a synonym for line.
- #
- # It can be used as a descriptive substitute for line in chart types such
- # as Bar and Column that have a border and fill style rather than a line
- # style. In general chart objects with a border property will also have a
- # fill property.
- #
- # ===Fill
- #
- # The fill format is used to specify filled areas of chart objects such
- # as the interior of a column or the background of the chart itself.
- #
- # The following properties can be set for fill formats in a chart.
- #
- # none
- # color
- # The none property is uses to turn the fill property off (it is
- # generally on by default).
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :fill => { none => 1 }
- # )
- # The color property sets the color of the fill area.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :fill => { color => 'red' }
- # )
- # The available colors are shown in the main WriteXLSX documentation.
- # It is also possible to set the color of a fill with a HTML style RGB color:
- #
- # chart.add_series(
- # :fill => { color => '#FF0000' }
- # )
- # The fill format is generally used in conjunction with a border format
- # which has the same properties as a line format.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :border => { color => 'red' },
- # :fill => { color => 'yellow' }
- # )
- # ===Marker
- #
- # The marker format specifies the properties of the markers used to
- # distinguish series on a chart. In general only Line and Scatter
- # chart types and trendlines use markers.
- #
- # The following properties can be set for marker formats in a chart.
- #
- # type
- # size
- # border
- # fill
- # The type property sets the type of marker that is used with a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { type => 'diamond' }
- # )
- # The following type properties can be set for marker formats in a chart.
- # These are shown in the same order as in the Excel format dialog.
- #
- # automatic
- # none
- # square
- # diamond
- # triangle
- # x
- # star
- # short_dash
- # long_dash
- # circle
- # plus
- # The automatic type is a special case which turns on a marker using the
- # default marker style for the particular series number.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { type => 'automatic' }
- # )
- # If automatic is on then other marker properties such as size,
- # border or fill cannot be set.
- #
- # The size property sets the size of the marker and is generally used in
- # conjunction with type.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { type => 'diamond', size => 7 }
- # )
- # Nested border and fill properties can also be set for a marker.
- # These have the same sub-properties as shown above.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => {
- # :type => 'square',
- # :size => 5,
- # :border => { color => 'red' },
- # :fill => { color => 'yellow' }
- # }
- # )
- # ===Trendline
- #
- # A trendline can be added to a chart series to indicate trends in the data
- # such as a moving average or a polynomial fit.
- #
- # The following properties can be set for trendline formats in a chart.
- #
- # type
- # order (for polynomial trends)
- # period (for moving average)
- # forward (for all except moving average)
- # backward (for all except moving average)
- # name
- # line
- # The type property sets the type of trendline in the series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => { type => 'linear' }
- # )
- # The available trendline types are:
- #
- # exponential
- # linear
- # log
- # moving_average
- # polynomial
- # power
- # A polynomial trendline can also specify the order of the polynomial.
- # The default value is 2.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'polynomial',
- # :order => 3
- # }
- # )
- # A moving_average trendline can also the period of the moving average.
- # The default value is 2.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'moving_average',
- # :period => 3
- # }
- # )
- # The forward and backward properties set the forecast period of the
- # trendline.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :forward => 0.5,
- # :backward => 0.5
- # }
- # )
- # The name property sets an optional name for the trendline that will
- # appear in the chart legend. If it isn't specified the Excel default
- # name will be displayed. This is usually a combination of the trendline
- # type and the series name.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :name => 'Interpolated trend'
- # }
- # )
- # Several of these properties can be set in one go:
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :name => 'My trend name',
- # :forward => 0.5,
- # :backward => 0.5,
- # :line => {
- # :color => 'red',
- # :width => 1,
- # :dash_type => 'long_dash'
- # }
- # }
- # )
- # Trendlines cannot be added to series in a stacked chart or pie chart or
- # (when implemented) to 3-D, radar, surface, or doughnut charts.
- #
- # ==Data Labels
- #
- # Data labels can be added to a chart series to indicate the values of
- # the plotted data points.
- #
- # The following properties can be set for data_labels formats in a chart.
- #
- # :value
- # :category
- # :series_name
- # :position
- # :leader_lines
- # :percentage
- #
- # The value property turns on the Value data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1 }
- # )
- # The category property turns on the Category Name data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :category => 1 }
- # )
- # The series_name property turns on the Series Name data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :series_name => 1 }
- # )
- # The C<position> property is used to position the data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1, :position => 'center' }
- # )
- #
- # Valid positions are:
- #
- # :center
- # :right
- # :left
- # :top
- # :bottom
- # :above # Same as top
- # :below # Same as bottom
- # :inside_end # Pie chart mainly.
- # :outside_end # Pie chart mainly.
- # :best_fit # Pie chart mainly.
- #
- # The C<percentage> property is used to turn on the I<Percentage>
- # for the data label for a series. It is mainly used for pie charts.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :percentage => 1 }
- # )
- #
- # The C<leader_lines> property is used to turn on I<Leader Lines>
- # for the data label for a series. It is mainly used for pie charts.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1, :leader_lines => 1 }
- # )
- #
class Chart
include Writexlsx::Utility
attr_accessor :id, :name # :nodoc:
attr_writer :index, :palette, :protection # :nodoc:
@@ -558,14 +99,15 @@
@horiz_cat_axis = 0
@horiz_val_axis = 1
@protection = 0
@chartarea = {}
@plotarea = {}
- @x_axis = Axis.new
- @y_axis = Axis.new
- @x2_axis = Axis.new
- @y2_axis = Axis.new
+ @title = Caption.new(self)
+ @x_axis = Axis.new(self)
+ @y_axis = Axis.new(self)
+ @x2_axis = Axis.new(self)
+ @y2_axis = Axis.new(self)
@name = ''
@show_blanks = 'gap'
@show_hidden_data = false
@show_crosses = true
@width = 480
@@ -618,920 +160,100 @@
end
#
# Add a series and it's properties to a chart.
#
- # In an Excel chart a "series" is a collection of information such as
- # values, x-axis labels and the formatting that define which data is
- # plotted.
- #
- # With a WriteXLSX chart object the add_series() method is used to
- # set the properties for a series:
- #
- # chart.add_series(
- # :categories => '=Sheet1!$A$2:$A$10', # Optional.
- # :values => '=Sheet1!$B$2:$B$10', # Required.
- # :line => { :color => 'blue' }
- # )
- #
- # The properties that can be set are:
- #
- # ===:values
- # This is the most important property of a series and must be set
- # for every chart object. It links the chart with the worksheet data
- # that it displays. A formula or array ref can be used for the
- # data range, see below.
- #
- # ===:categories
- # This sets the chart category labels. The category is more or less
- # the same as the X-axis. In most chart types the categories property
- # is optional and the chart will just assume a sequential series
- # from 1 .. n.
- #
- # ===:name
- # Set the name for the series. The name is displayed in the chart
- # legend and in the formula bar. The name property is optional and
- # if it isn't supplied it will default to Series 1 .. n.
- #
- # ===:line
- # Set the properties of the series line type such as colour and
- # width. See the "CHART FORMATTING" section below.
- #
- # ===:border
- # Set the border properties of the series such as colour and style.
- # See the "CHART FORMATTING" section below.
- #
- # ===:fill
- # Set the fill properties of the series such as colour. See the
- # "CHART FORMATTING"
- # section below.
- #
- # ==:marker
- # Set the properties of the series marker such as style and color.
- # See the "CHART FORMATTING" section below.
- #
- # ===:trendline
- # Set the properties of the series trendline such as linear,
- # polynomial and moving average types. See the "CHART FORMATTING"
- # section below.
- #
- # ===:data_labels
- # Set data labels for the series. See the "CHART FORMATTING"
- # section below.
- #
- # ===:invert_if_negative
- # Invert the fill colour for negative values. Usually only applicable
- # to column and bar charts.
- #
- # ===:overlap
- # Set the overlap between series in a Bar/Column chart. The range is
- # <tt>+/- 100</tt>. Default is 0.
- #
- # :overlap => 20
- #
- # Note, it is only necessary to apply this property to one series of the chart.
- #
- # ===:gap
- # Set the gap between series in a Bar/Column chart. The range is
- # <tt>0 to 500</tt>. Default is 150.
- #
- # :gap => 200,
- #
- # Note, it is only necessary to apply this property to one series of the
- # chart.
- #
- # The categories and values can take either a range formula such
- # as <tt>=Sheet1!$A$2:$A$7</tt> or, more usefully when generating the range
- # programmatically, an array ref with zero indexed row/column values:
- #
- # [ sheetname, row_start, row_end, col_start, col_end ]
- #
- # The following are equivalent:
- #
- # chart.add_series( categories => '=Sheet1!$A$2:$A$7' ) # Same as ...
- # chart.add_series( categories => [ 'Sheet1', 1, 6, 0, 0 ] ) # Zero-indexed.
- #
- # You can add more than one series to a chart. In fact, some chart
- # types such as stock require it. The series numbering and order in
- # the Excel chart will be the same as the order in which that are added
- # in WriteXLSX.
- #
- # # Add the first series.
- # chart.add_series(
- # :categories => '=Sheet1!$A$2:$A$7',
- # :values => '=Sheet1!$B$2:$B$7',
- # :name => 'Test data series 1'
- # )
- #
- # # Add another series. Same categories. Different range values.
- # chart.add_series(
- # :categories => '=Sheet1!$A$2:$A$7',
- # :values => '=Sheet1!$C$2:$C$7',
- # :name => 'Test data series 2'
- # )
- #
- # ==SERIES OPTIONS
- #
- # This section details the following properties of add_series() in more
- # detail:
- #
- # marker
- # trendline
- # y_error_bars
- # x_error_bars
- # data_labels
- # points
- #
- # ===Marker
- #
- # The marker format specifies the properties of the markers used to
- # distinguish series on a chart. In general only Line and Scatter chart
- # types and trendlines use markers.
- #
- # The following properties can be set for marker formats in a chart.
- #
- # type
- # size
- # border
- # fill
- #
- # The type property sets the type of marker that is used with a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { :type => 'diamond' }
- # )
- #
- # The following type properties can be set for marker formats in a chart.
- # These are shown in the same order as in the Excel format dialog.
- #
- # automatic
- # none
- # square
- # diamond
- # triangle
- # x
- # star
- # short_dash
- # long_dash
- # circle
- # plus
- #
- # The automatic type is a special case which turns on a marker using the
- # default marker style for the particular series number.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { :type => 'automatic' }
- # )
- #
- # If automatic is on then other marker properties such as size, border or
- # fill cannot be set.
- #
- # The size property sets the size of the marker and is generally used in
- # conjunction with type.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => { :type => 'diamond', :size => 7 }
- # )
- #
- # Nested border and fill properties can also be set for a marker. See the
- # "CHART FORMATTING"
- # section below.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :marker => {
- # :type => 'square',
- # :size => 5,
- # :border => { :color => 'red' },
- # :fill => { :color => 'yellow' }
- # }
- # )
- #
- # ===Trendline
- #
- # A trendline can be added to a chart series to indicate trends in the data
- # such as a moving average or a polynomial fit.
- #
- # The following properties can be set for trendlines in a chart series.
- #
- # type
- # order (for polynomial trends)
- # period (for moving average)
- # forward (for all except moving average)
- # backward (for all except moving average)
- # name
- # line
- #
- # The type property sets the type of trendline in the series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => { :type => 'linear' }
- # )
- #
- # The available trendline types are:
- #
- # exponential
- # linear
- # log
- # moving_average
- # polynomial
- # power
- #
- # A polynomial trendline can also specify the order of the polynomial.
- # The default value is 2.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'polynomial',
- # :order => 3
- # }
- # )
- #
- # A moving_average trendline can also specify the period of the moving
- # average. The default value is 2.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'moving_average',
- # :period => 3,
- # }
- # )
- #
- # The forward and backward properties set the forecast period of the
- # trendline.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :forward => 0.5,
- # :backward => 0.5
- # }
- # )
- #
- # The name property sets an optional name for the trendline that will
- # appear in the chart legend. If it isn't specified the Excel default
- # name will be displayed. This is usually a combination of the
- # trendline type and the series name.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :name => 'Interpolated trend'
- # }
- # )
- #
- # Several of these properties can be set in one go:
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :trendline => {
- # :type => 'linear',
- # :name => 'My trend name',
- # :forward => 0.5,
- # :backward => 0.5,
- # :line => {
- # :color => 'red',
- # :width => 1,
- # :dash_type => 'long_dash'
- # }
- # }
- # )
- #
- # Trendlines cannot be added to series in a stacked chart or pie chart,
- # radar chart or (when implemented) to 3D, surface, or doughnut charts.
- #
- # ===Error Bars
- #
- # Error bars can be added to a chart series to indicate error bounds in the
- # data. The error bars can be vertical y_error_bars (the most common type)
- # or horizontal x_error_bars (for Bar and Scatter charts only).
- #
- # The following properties can be set for error bars in a chart series.
- #
- # type
- # value (for all types except standard error)
- # direction
- # end_style
- # line
- #
- # The type property sets the type of error bars in the series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :y_error_bars => { :type => 'standard_error' }
- # )
- #
- # The available error bars types are available:
- #
- # fixed
- # percentage
- # standard_deviation
- # standard_error
- #
- # Note, the "custom" error bars type is not supported.
- #
- # All error bar types, except for standard_error must also have a value
- # associated with it for the error bounds:
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :y_error_bars => {
- # :type => 'percentage',
- # :value => 5
- # }
- # )
- #
- # The direction property sets the direction of the error bars. It should
- # be one of the following:
- #
- # plus # Positive direction only.
- # minus # Negative direction only.
- # both # Plus and minus directions, The default.
- #
- # The end_style property sets the style of the error bar end cap. The
- # options are 1 (the default) or 0 (for no end cap):
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :y_error_bars => {
- # :type => 'fixed',
- # :value => 2,
- # :end_style => 0,
- # :direction => 'minus'
- # }
- # )
- #
- # ===Data Labels
- #
- # Data labels can be added to a chart series to indicate the values of the
- # plotted data points.
- #
- # The following properties can be set for data_labels formats in a chart.
- #
- # value
- # category
- # series_name
- # position
- # leader_lines
- # percentage
- #
- # The value property turns on the Value data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1 }
- # )
- # The category property turns on the Category Name data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :category => 1 }
- # )
- #
- # The series_name property turns on the Series Name data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :series_name => 1 }
- # )
- #
- # The position property is used to position the data label for a series.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1, :position => 'center' },
- # )
- #
- # Valid positions are:
- #
- # center
- # right
- # left
- # top
- # bottom
- # above # Same as top
- # below # Same as bottom
- # inside_end # Pie chart mainly.
- # outside_end # Pie chart mainly.
- # best_fit # Pie chart mainly.
- #
- # The percentage property is used to turn on the display of data labels as
- # a Percentage for a series. It is mainly used for pie charts.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :percentage => 1 }
- # )
- #
- # The leader_lines property is used to turn on Leader Lines for the data
- # label for a series. It is mainly used for pie charts.
- #
- # chart.add_series(
- # :values => '=Sheet1!$B$1:$B$5',
- # :data_labels => { :value => 1, :leader_lines => 1 }
- # )
- #
- # Note: Even when leader lines are turned on they aren't automatically
- # visible in Excel or Excel::Writer::XLSX. Due to an Excel limitation
- # (or design) leader lines only appear if the data label is moved
- # manually or if the data labels are very close and need to be adjusted
- # automatically.
- #
- # ===Points
- #
- # In general formatting is applied to an entire series in a chart. However,
- # it is occasionally required to format individual points in a series. In
- # particular this is required for Pie charts where each segment is
- # represented by a point.
- #
- # In these cases it is possible to use the points property of add_series():
- #
- # chart.add_series(
- # :values => '=Sheet1!$A$1:$A$3',
- # :points => [
- # { :fill => { :color => '#FF0000' } },
- # { :fill => { ?color => '#CC0000' } },
- # { :fill => { :color => '#990000' } }
- # ]
- # )
- #
- # The points property takes an array ref of format options (see the
- # "CHART FORMATTING"
- # section below). To assign default properties to points in a series pass
- # nil values in the array ref:
- #
- # # Format point 3 of 3 only.
- # chart.add_series(
- # :values => '=Sheet1!$A$1:$A$3',
- # :points => [
- # nil,
- # nil,
- # { :fill => { :color => '#990000' } }
- # ]
- # )
- #
- # # Format the first point only.
- # chart.add_series(
- # :values => '=Sheet1!$A$1:$A$3',
- # :points => [ { :fill => { :color => '#FF0000' } } ]
- # )
def add_series(params)
# Check that the required input has been specified.
unless params.has_key?(:values)
raise "Must specify ':values' in add_series"
end
if @requires_category != 0 && !params.has_key?(:categories)
raise "Must specify ':categories' in add_series for this chart type"
end
- # Convert aref params into a formula string.
- values = aref_to_formula(params[:values])
- categories = aref_to_formula(params[:categories])
+ @series << Series.new(self, params)
- # Switch name and name_formula parameters if required.
- name, name_formula = process_names(params[:name], params[:name_formula])
-
- # Get an id for the data equivalent to the range formula.
- cat_id = get_data_id(categories, params[:categories_data])
- val_id = get_data_id(values, params[:values_data])
- name_id = get_data_id(name_formula, params[:name_data])
-
- # Set the line properties for the series.
- line = line_properties(params[:line])
-
- # Allow 'border' as a synonym for 'line' in bar/column style charts.
- line = line_properties(params[:border]) if params[:border]
-
- # Set the fill properties for the series.
- fill = fill_properties(params[:fill])
-
- # Set the marker properties for the series.
- marker = marker_properties(params[:marker])
-
- # Set the trendline properties for the series.
- trendline = trendline_properties(params[:trendline])
-
- # Set the line smooth property for the series.
- smooth = params[:smooth]
-
- # Set the error bars properties for the series.
- y_error_bars = error_bars_properties(params[:y_error_bars])
- x_error_bars = error_bars_properties(params[:x_error_bars])
-
- # Set the point properties for the series.
- points = points_properties(params[:points])
-
- # Set the labels properties for the series.
- labels = labels_properties(params[:data_labels])
-
- # Set the "invert if negative" fill property.
- invert_if_neg = params[:invert_if_negative]
-
- # Set the gap for Bar/Column charts.
- if params[:gap]
- @series_gap = params[:gap]
- end
-
- # Set the overlap for Bar/Column charts.
- if params[:overlap]
- @series_overlap = params[:overlap]
- end
-
- # Set the secondary axis properties.
- x2_axis = params[:x2_axis]
- y2_axis = params[:y2_axis]
-
- # Add the user supplied data to the internal structures.
- @series << {
- :_values => values,
- :_categories => categories,
- :_name => name,
- :_name_formula => name_formula,
- :_name_id => name_id,
- :_val_data_id => val_id,
- :_cat_data_id => cat_id,
- :_line => line,
- :_fill => fill,
- :_marker => marker,
- :_trendline => trendline,
- :_smooth => smooth,
- :_labels => labels,
- :_invert_if_neg => invert_if_neg,
- :_x2_axis => x2_axis,
- :_y2_axis => y2_axis,
- :_points => points,
- :_error_bars => {
- :_x_error_bars => x_error_bars,
- :_y_error_bars => y_error_bars
- }
- }
+ # Set the gap and overlap for Bar/Column charts.
+ @series_gap = params[:gap] if params[:gap]
+ @series_overlap = params[:overlap] if params[:overlap]
end
#
- # Set the properties of the X-axis.
+ # Set the properties of the x-axis.
#
- # The set_x_axis() method is used to set properties of the X axis.
- #
- # chart.set_x_axis( :name => 'Quarterly results' )
- #
- # The properties that can be set are:
- #
- # :name
- # :min
- # :max
- # :minor_unit
- # :major_unit
- # :crossing
- # :reverse
- # :log_base
- # :label_position
- # :major_gridlines
- # :minor_gridlines
- # :visible
- #
- # These are explained below. Some properties are only applicable to value
- # or category axes, as indicated. See "Value and Category Axes" for an
- # explanation of Excel's distinction between the axis types.
- #
- # ====:name
- # Set the name (title or caption) for the axis. The name is displayed
- # below the X axis. The name property is optional. The default is to
- # have no axis name. (Applicable to category and value axes).
- #
- # chart.set_x_axis( :name => 'Quarterly results' )
- #
- # The name can also be a formula such as =Sheet1!$A$1.
- #
- # ====:min
- # Set the minimum value for the axis range.
- # (Applicable to value axes only).
- #
- # chart.set_x_axis( :min => 20 )
- # ====:max
- # Set the maximum value for the axis range.
- # (Applicable to value axes only).
- #
- # chart.set_x_axis( :max => 80 )
- # ====:minor_unit
- # Set the increment of the minor units in the axis range.
- # (Applicable to value axes only).
- #
- # chart.set_x_axis( :minor_unit => 0.4 )
- # ====:major_unit
- # Set the increment of the major units in the axis range.
- # (Applicable to value axes only).
- #
- # chart.set_x_axis( :major_unit => 2 )
- # ====:crossing
- # Set the position where the y axis will cross the x axis.
- # (Applicable to category and value axes).
- #
- # The crossing value can either be the string 'max' to set the crossing
- # at the maximum axis value or a numeric value.
- #
- # chart.set_x_axis( :crossing => 3 )
- # # or
- # chart.set_x_axis( :crossing => 'max' )
- # For category axes the numeric value must be an integer to represent
- # the category number that the axis crosses at. For value axes it can
- # have any value associated with the axis.
- #
- # If crossing is omitted (the default) the crossing will be set
- # automatically by Excel based on the chart data.
- #
- # ====:reverse
- # Reverse the order of the axis categories or values.
- # (Applicable to category and value axes).
- #
- # chart.set_x_axis( :reverse => 1 )
- # ====:log_base
- # Set the log base of the axis range.
- # (Applicable to value axes only).
- #
- # chart.set_x_axis( :log_base => 10 )
- # ====:label_position
- # Set the "Axis labels" position for the axis.
- # The following positions are available:
- #
- # next_to (the default)
- # high
- # low
- # none
- # More than one property can be set in a call to set_x_axis:
- #
- # chart.set_x_axis(
- # :name => 'Quarterly results',
- # :min => 10,
- # :max => 80
- # )
- #
- # ==CHART FONTS
- #
- # The following font properties can be set for any chart object that they
- # apply to (and that are supported by WriteXLSX) such as chart titles,
- # axis labels and axis numbering. They correspond to the equivalent
- # Worksheet cell Format object properties. See "FORMAT_METHODS" for more
- # information.
- #
- # name
- # size
- # bold
- # italic
- # underline
- # rotation
- # color
- #
- # The following explains the available font properties:
- #
- # ===name
- # Set the font name:
- #
- # chart.set_x_axis( :num_font => { :name => 'Arial' } )
- #
- # ===size
- # Set the font size:
- #
- # chart.set_x_axis( :num_font => { :name => 'Arial', :size => 10 } )
- #
- # ===bold
- # Set the font bold property, should be 0 or 1:
- #
- # chart.set_x_axis( :num_font => { :bold => 1 } )
- #
- # ===italic
- # Set the font italic property, should be 0 or 1:
- #
- # chart.set_x_axis( :num_font => { :italic => 1 } )
- #
- # ===underline
- # Set the font underline property, should be 0 or 1:
- #
- # chart.set_x_axis( :num_font => { :underline => 1 } )
- #
- # ===rotation
- # See the font rotation in the range -90 to 90:
- #
- # chart.set_x_axis(:num_font => { :rotation => 45 })
- #
- # This is useful for displaying large axis data such as dates in a more compact format.
- #
- # ===color
- # Set the font color property. Can be a color index, a color name or HTML
- # style RGB colour:
- #
- # chart.set_x_axis( :num_font => { :color => 'red' } )
- # chart.set_y_axis( :num_font => { :color => '#92D050' } )
- #
- # Here is an example of Font formatting in a Chart program:
- #
- # # Format the chart title.
- # chart.set_title(
- # :name => 'Sales Results Chart',
- # :name_font => {
- # :name => 'Calibri',
- # :color => 'yellow'
- # }
- # )
- #
- # # Format the X-axis.
- # chart.set_x_axis(
- # :name => 'Month',
- # :name_font => {
- # :name => 'Arial',
- # :color => '#92D050'
- # },
- # :num_font => {
- # :name => 'Courier New',
- # :color => '#00B0F0'
- # }
- # )
- #
- # # Format the Y-axis.
- # chart.set_y_axis(
- # :name => 'Sales (1000 units)',
- # :name_font => {
- # :name => 'Century',
- # :underline => 1,
- # :color => 'red'
- # },
- # :num_font => {
- # :bold => 1,
- # :italic => 1,
- # :color => '#7030A0'
- # }
- # )
def set_x_axis(params = {})
- @x_axis.merge_with_hash(self, params)
+ @x_axis.merge_with_hash(params)
end
#
# Set the properties of the Y-axis.
#
# The set_y_axis() method is used to set properties of the Y axis.
# The properties that can be set are the same as for set_x_axis,
#
def set_y_axis(params = {})
- @y_axis.merge_with_hash(self, params)
+ @y_axis.merge_with_hash(params)
end
#
# Set the properties of the secondary X-axis.
#
def set_x2_axis(params = {})
- @x2_axis.merge_with_hash(self, params)
+ @x2_axis.merge_with_hash(params)
end
#
# Set the properties of the secondary Y-axis.
#
def set_y2_axis(params = {})
- @y2_axis.merge_with_hash(self, params)
+ @y2_axis.merge_with_hash(params)
end
#
# Set the properties of the chart title.
#
- # The set_title() method is used to set properties of the chart title.
- #
- # chart.set_title( :name => 'Year End Results' )
- #
- # The properties that can be set are:
- #
- # ===:name
- # Set the name (title) for the chart. The name is displayed above the
- # chart. The name can also be a formula such as +=Sheet1!$A$1+. The name
- # property is optional. The default is to have no chart title.
- #
- # ===:name_font
- # Set the font properties for the chart title. See the "CHART FONTS" section.
- #
def set_title(params)
- name, name_formula = process_names(params[:name], params[:name_formula])
- data_id = get_data_id(name_formula, params[:data])
-
- @title_name = name
- @title_formula = name_formula
- @title_data_id = data_id
-
- # Set the font properties if present.
- @title_font = convert_font_args(params[:name_font])
+ @title.merge_with_hash(params)
end
#
# Set the properties of the chart legend.
#
- # The set_legend() method is used to set properties of the chart legend.
- #
- # chart.set_legend( :position => 'none' )
- #
- # The properties that can be set are:
- #
- # ===:position
- # Set the position of the chart legend.
- #
- # chart.set_legend( :position => 'bottom' )
- #
- # The default legend position is right. The available positions are:
- #
- # none
- # top
- # bottom
- # left
- # right
- # overlay_left
- # overlay_right
- #
- # ===:delete_series
- #
- # This allows you to remove 1 or more series from the the legend
- # (the series will still display on the chart). This property takes
- # an array ref as an argument and the series are zero indexed:
- #
- # # Delete/hide series index 0 and 2 from the legend.
- # chart.set_legend(:delete_series => [0, 2])
- #
def set_legend(params)
@legend_position = params[:position] || 'right'
@legend_delete_series = params[:delete_series]
end
#
# Set the properties of the chart plotarea.
#
- # The set_plotarea() method is used to set properties of the plot area
- # of a chart.
- #
- # This method isn't implemented yet and is only available in
- # writeexcel gem. However, it can be simulated using the
- # set_style() method.
- #
def set_plotarea(params)
# Convert the user defined properties to internal properties.
@plotarea = area_properties(params)
end
#
# Set the properties of the chart chartarea.
#
- # The set_chartarea() method is used to set the properties of the chart
- # area.
- #
- # chart.set_chartarea(
- # :border => { :none => 1 },
- # :fill => { :color => 'red' }
- # )
- #
- # The properties that can be set are:
- # ===:border
- # Set the border properties of the chartarea such as colour and style.
- # See the "CHART FORMATTING" section.
- # ===:fill
- # Set the fill properties of the plotarea such as colour. See the
- # "CHART FORMATTING" section.
- #
def set_chartarea(params)
# Convert the user defined properties to internal properties.
@chartarea = area_properties(params)
end
#
# Set on of the 42 built-in Excel chart styles. The default style is 2.
#
- # The set_style() method is used to set the style of the chart to one
- # of the 42 built-in styles available on the 'Design' tab in Excel:
- #
- # chart.set_style( 4 )
- #
- # The default style is 2.
- #
def set_style(style_id = 2)
style_id = 2 if style_id < 0 || style_id > 42
@style_id = style_id
end
#
# Set the option for displaying blank data in a chart. The default is 'gap'.
#
- # The show_blanks_as method controls how blank data is displayed in a chart.
- #
- # chart.show_blanks_as('span')
- #
- # The available options are:
- #
- # gap # Blank data is show as a gap. The default.
- # zero # Blank data is displayed as zero.
- # span # Blank data is connected with a line.
- #
def show_blanks_as(option)
return unless option
unless [:gap, :zero, :span].include?(option.to_sym)
raise "Unknown show_blanks_as() option '#{option}'\n"
@@ -1548,39 +270,10 @@
end
#
# Set dimensions for scale for the chart.
#
- # The set_size() method is used to set the dimensions of the chart.
- # The size properties that can be set are:
- #
- # width
- # height
- # x_scale
- # y_scale
- # x_offset
- # y_offset
- #
- # The width and height are in pixels. The default chart width is 480
- # pixels and the default height is 288 pixels. The size of the chart can
- # be modified by setting the width and height or by setting the :x_scale
- # and :y_scale:
- #
- # chart.set_size( :width => 720, :height => 576 )
- #
- # # Same as:
- #
- # chart.set_size( :x_scale => 1.5, :y_scale => 2 )
- #
- # The :x_offset and :y_offset position the top left corner of the chart
- # in the cell that it is inserted into.
- #
- # Note: the :x_scale, :y_scale, :x_offset and :y_offset parameters can also
- # be set via the insert_chart() method:
- #
- # worksheet.insert_chart( 'E2', chart, 2, 4, 1.5, 2 )
- #
def set_size(params = {})
@width = params[:width] if params[:width]
@height = params[:height] if params[:height]
@x_scale = params[:x_scale] if params[:x_scale]
@y_scale = params[:y_scale] if params[:y_scale]
@@ -1593,42 +286,17 @@
#
# The set_table method adds a data table below the horizontal axis with the
# data used to plot the chart.
#
- # chart.set_table
- #
- # The available options, with default values are:
- #
- # :vertical => true # Display vertical lines in the table.
- # :horizontal => true # Display horizontal lines in the table.
- # :outline => true # Display an outline in the table.
- # :show_keys => false # Show the legend keys with the table data.
- #
- # The data table can only be shown with Bar, Column, Line, Area and Stock charts.
- #
def set_table(params = {})
@table = Table.new(params)
end
#
# Set properties for the chart up-down bars.
#
- # The set_up_down_bars() method adds Up-Down bars to Line charts to
- # indicate the difference between the first and last data series.
- #
- # chart.set_up_down_bars
- # It is possible to format the up and down bars to add fill and border
- # properties if required. See the "CHART FORMATTING" section below.
- #
- # chart.set_up_down_bars(
- # :up => { :fill => { :color => 'green' } },
- # :down => { :fill => { :color => 'red' } }
- # )
- # Up-down bars can only be applied to Line charts and to Stock charts
- # (by default).
- #
def set_up_down_bars(params = {})
# Map border to line.
[:up, :down].each do |up_down|
if params[up_down]
params[up_down][:line] = params[up_down][:border] if params[up_down][:border]
@@ -1651,44 +319,20 @@
end
#
# Set properties for the chart drop lines.
#
- # The set_drop_lines() method adds Drop Lines to charts to show the
- # Category value of points in the data.
- #
- # chart.set_drop_lines
- #
- # It is possible to format the Drop Line line properties if required.
- # See the "CHART FORMATTING" section below.
- #
- # chart.set_drop_lines(:line => { :color => 'red', :dash_type => 'square_dot' } )
- #
- # Drop Lines are only available in Line, Area and Stock charts.
- #
def set_drop_lines(params = {})
# Set the drop line properties.
line = line_properties(params[:line])
@drop_lines = { :_line => line }
end
#
# Set properties for the chart high-low lines.
#
- # The set_high_low_lines() method adds High-Low lines to charts to show
- # the maximum and minimum values of points in a Category.
- #
- # chart.set_high_low_lines
- #
- # It is possible to format the High-Low Line line properties if required.
- # See the "CHART FORMATTING" section below.
- #
- # chart.set_high_low_lines( :line => { :color => 'red' } )
- #
- # High-Low Lines are only available in Line and Stock charts.
- #
def set_high_low_lines(params = {})
# Set the drop line properties.
line = line_properties(params[:line])
@hi_low_lines = { :_line => line }
@@ -1741,57 +385,10 @@
write_axis_ids(params)
end
end
#
- # Switch name and name_formula parameters if required.
- #
- def process_names(name = nil, name_formula = nil) # :nodoc:
- # Name looks like a formula, use it to set name_formula.
- if name && name =~ /^=[^!]+!\$/
- name_formula = name
- name = ''
- end
-
- [name, name_formula]
- end
-
- #
- # Assign an id to a each unique series formula or title/axis formula. Repeated
- # formulas such as for categories get the same id. If the series or title
- # has user specified data associated with it then that is also stored. This
- # data is used to populate cached Excel data when creating a chart.
- # If there is no user defined data then it will be populated by the parent
- # workbook in Workbook::_add_chart_data
- #
- def get_data_id(formula, data) # :nodoc:
- # Ignore series without a range formula.
- return unless formula
-
- # Strip the leading '=' from the formula.
- formula = formula.sub(/^=/, '')
-
- # Store the data id in a hash keyed by the formula and store the data
- # in a separate array with the same id.
- if !@formula_ids.has_key?(formula)
- # Haven't seen this formula before.
- id = @formula_data.size
-
- @formula_data << data
- @formula_ids[formula] = id
- else
- # Formula already seen. Return existing id.
- id = @formula_ids[formula]
-
- # Store user defined data if it isn't already there.
- @formula_data[id] = data unless @formula_data[id]
- end
-
- id
- end
-
- #
# Convert user defined font values into private hash values.
#
def convert_font_args(params)
return unless params
font = {
@@ -1848,10 +445,57 @@
line[:_defined] = 1
line
end
+ #
+ # Switch name and name_formula parameters if required.
+ #
+ def process_names(name = nil, name_formula = nil) # :nodoc:
+ # Name looks like a formula, use it to set name_formula.
+ if name && name =~ /^=[^!]+!\$/
+ name_formula = name
+ name = ''
+ end
+
+ [name, name_formula]
+ end
+
+ #
+ # Assign an id to a each unique series formula or title/axis formula. Repeated
+ # formulas such as for categories get the same id. If the series or title
+ # has user specified data associated with it then that is also stored. This
+ # data is used to populate cached Excel data when creating a chart.
+ # If there is no user defined data then it will be populated by the parent
+ # workbook in Workbook::_add_chart_data
+ #
+ def get_data_id(formula, data) # :nodoc:
+ # Ignore series without a range formula.
+ return unless formula
+
+ # Strip the leading '=' from the formula.
+ formula = formula.sub(/^=/, '')
+
+ # Store the data id in a hash keyed by the formula and store the data
+ # in a separate array with the same id.
+ if !@formula_ids.has_key?(formula)
+ # Haven't seen this formula before.
+ id = @formula_data.size
+
+ @formula_data << data
+ @formula_ids[formula] = id
+ else
+ # Formula already seen. Return existing id.
+ id = @formula_ids[formula]
+
+ # Store user defined data if it isn't already there.
+ @formula_data[id] = data unless @formula_data[id]
+ end
+
+ id
+ end
+
private
#
# retun primary/secondary series by :primary_axes flag
#
@@ -1862,19 +506,10 @@
secondary_axes_series
end
end
#
- # Convert and aref of row col values to a range formula.
- #
- def aref_to_formula(data) # :nodoc:
- # If it isn't an array ref it is probably a formula already.
- return data unless data.kind_of?(Array)
- xl_range_formula(*data)
- end
-
- #
# Find the overall type of the data associated with a series.
#
# TODO. Need to handle date type.
#
def get_data_type(data) # :nodoc:
@@ -1992,179 +627,10 @@
fill
end
#
- # Convert user defined marker properties to the structure required internally.
- #
- def marker_properties(marker) # :nodoc:
- return unless marker
-
- types = {
- :automatic => 'automatic',
- :none => 'none',
- :square => 'square',
- :diamond => 'diamond',
- :triangle => 'triangle',
- :x => 'x',
- :star => 'start',
- :dot => 'dot',
- :short_dash => 'dot',
- :dash => 'dash',
- :long_dash => 'dash',
- :circle => 'circle',
- :plus => 'plus',
- :picture => 'picture'
- }
-
- # Check for valid types.
- marker_type = marker[:type]
-
- if marker_type
- marker[:automatic] = 1 if marker_type == 'automatic'
- marker[:type] = value_or_raise(types, marker_type, 'maker type')
- end
-
- # Set the line properties for the marker..
- line = line_properties(marker[:line])
-
- # Allow 'border' as a synonym for 'line'.
- line = line_properties(marker[:border]) if marker[:border]
-
- # Set the fill properties for the marker.
- fill = fill_properties(marker[:fill])
-
- marker[:_line] = line
- marker[:_fill] = fill
-
- marker
- end
-
- #
- # Convert user defined trendline properties to the structure required internally.
- #
- def trendline_properties(trendline) # :nodoc:
- return unless trendline
-
- types = {
- :exponential => 'exp',
- :linear => 'linear',
- :log => 'log',
- :moving_average => 'movingAvg',
- :polynomial => 'poly',
- :power => 'power'
- }
-
- # Check the trendline type.
- trend_type = trendline[:type]
-
- trendline[:type] = value_or_raise(types, trend_type, 'trendline type')
-
- # Set the line properties for the trendline..
- line = line_properties(trendline[:line])
-
- # Allow 'border' as a synonym for 'line'.
- line = line_properties(trendline[:border]) if trendline[:border]
-
- # Set the fill properties for the trendline.
- fill = fill_properties(trendline[:fill])
-
- trendline[:_line] = line
- trendline[:_fill] = fill
-
- return trendline
- end
-
- #
- # Convert user defined error bars properties to structure required
- # internally.
- #
- def error_bars_properties(params = {})
- return if !ptrue?(params) || params.empty?
-
- # Default values.
- error_bars = {
- :_type => 'fixedVal',
- :_value => 1,
- :_endcap => 1,
- :_direction => 'both'
- }
-
- types = {
- :fixed => 'fixedVal',
- :percentage => 'percentage',
- :standard_deviation => 'stdDev',
- :standard_error => 'stdErr'
- }
-
- # Check the error bars type.
- error_type = params[:type].to_sym
-
- if types.key?(error_type)
- error_bars[:_type] = types[error_type]
- else
- raise "Unknown error bars type '#{error_type}'\n"
- end
-
- # Set the value for error types that require it.
- if params.key?(:value)
- error_bars[:_value] = params[:value]
- end
-
- # Set the end-cap style.
- if params.key?(:end_style)
- error_bars[:_endcap] = params[:end_style]
- end
-
- # Set the error bar direction.
- if params.key?(:direction)
- if params[:direction] == 'minus'
- error_bars[:_direction] = 'minus'
- elsif params[:direction] == 'plus'
- error_bars[:_direction] = 'plus'
- else
- # Default to 'both'
- end
- end
-
- # Set the line properties for the error bars.
- error_bars[:_line] = line_properties(params[:line])
-
- error_bars
- end
-
- #
- # Convert user defined labels properties to the structure required internally.
- #
- def labels_properties(labels) # :nodoc:
- return nil unless labels
-
- position = labels[:position]
- if position.nil? || position.empty?
- labels.delete(:position)
- else
- # Map user defined label positions to Excel positions.
- positions = {
- :center => 'ctr',
- :right => 'r',
- :left => 'l',
- :top => 't',
- :above => 't',
- :bottom => 'b',
- :below => 'b',
- :inside_end => 'inEnd',
- :outside_end => 'outEnd',
- :best_fit => 'bestFit'
- }
-
- labels[:position] = value_or_raise(positions, position, 'label position')
- end
-
- labels
- end
-
- #
# Convert user defined area properties to the structure required internally.
#
def area_properties(arg) # :nodoc:
area = {}
@@ -2205,75 +671,50 @@
area[:_fill] = fill
return area
end
- #
- # Convert user defined points properties to structure required internally.
- #
- def points_properties(user_points = nil)
- return unless user_points
-
- points = []
- user_points.each do |user_point|
- if user_point
- # Set the lline properties for the point.
- line = line_properties(user_point[:line])
-
- # Allow 'border' as a synonym for 'line'.
- if user_point[:border]
- line = line_properties(user_point[:border])
- end
-
- # Set the fill properties for the chartarea.
- fill = fill_properties(user_point[:fill])
-
- point = {}
- point[:_line] = line
- point[:_fill] = fill
- end
- points << point
- end
- points
- end
-
def value_or_raise(hash, key, msg)
raise "Unknown #{msg} '#{key}'" unless hash[key.to_sym]
hash[key.to_sym]
end
#
# Returns series which use the primary axes.
#
def get_primary_axes_series
- @series.reject {|s| s[:_y2_axis]}
+ @series.reject {|s| s.y2_axis}
end
alias :primary_axes_series :get_primary_axes_series
#
# Returns series which use the secondary axes.
#
def get_secondary_axes_series
- @series.select {|s| s[:_y2_axis]}
+ @series.select {|s| s.y2_axis}
end
alias :secondary_axes_series :get_secondary_axes_series
#
# Add a unique ids for primary or secondary axis.
#
def add_axis_ids(params) # :nodoc:
+ if ptrue?(params[:primary_axes])
+ @axis_ids += ids
+ else
+ @axis2_ids += ids
+ end
+ end
+
+ def ids
chart_id = 1 + @id
axis_count = 1 + @axis2_ids.size + @axis_ids.size
id1 = sprintf('5%03d%04d', chart_id, axis_count)
id2 = sprintf('5%03d%04d', chart_id, axis_count + 1)
- if ptrue?(params[:primary_axes])
- @axis_ids << id1 << id2
- else
- @axis2_ids << id1 << id2
- end
+ [id1, id2]
end
#
# Get the font style attributes from a font hash.
#
@@ -2424,14 +865,14 @@
# Write the <c:chart> element.
#
def write_chart # :nodoc:
@writer.tag_elements('c:chart') do
# Write the chart title elements.
- if title = @title_formula
- write_title_formula(title, @title_data_id, nil, @title_font)
- elsif title = @title_name
- write_title_rich(title, nil, @title_font)
+ if @title.formula
+ write_title_formula(@title, nil)
+ elsif @title.name
+ write_title_rich(@title, nil)
end
# Write the c:plotArea element.
write_plot_area
# Write the c:legend element.
@@ -2529,34 +970,10 @@
#
def write_series(series) # :nodoc:
write_ser(series)
end
- def write_series_base
- # Write each series with subelements.
- index = 0
- @series.each do |series|
- write_ser(index, series)
- index += 1
- end
-
- # Write the c:marker element.
- write_marker_value
-
- # Write the c:overlap element
- # block given by Bar and Column
- yield
-
- # Generate the axis ids.
- add_axis_id
- add_axis_id
-
- # Write the c:axId element.
- write_axis_id(@axis_ids[0])
- write_axis_id(@axis_ids[1])
- end
-
#
# Write the <c:ser> element.
#
def write_ser(series) # :nodoc:
index = @series_index
@@ -2570,27 +987,27 @@
# Write the series name.
write_series_name(series)
# Write the c:spPr element.
write_sp_pr(series)
# Write the c:marker element.
- write_marker(series[:_marker])
+ write_marker(series.marker)
# Write the c:invertIfNegative element.
- write_c_invert_if_negative(series[:_invert_if_neg])
+ write_c_invert_if_negative(series.invert_if_neg)
# Write the c:dPt element.
- write_d_pt(series[:_points])
+ write_d_pt(series.points)
# Write the c:dLbls element.
- write_d_lbls(series[:_labels])
+ write_d_lbls(series.labels)
# Write the c:trendline element.
- write_trendline(series[:_trendline])
+ write_trendline(series.trendline)
# Write the c:errBars element.
- write_error_bars(series[:_error_bars])
+ write_error_bars(series.error_bars)
# Write the c:cat element.
write_cat(series)
# Write the c:val element.
write_val(series)
# Write the c:smooth element.
- write_c_smooth(series[:_smooth]) if ptrue?(@smooth_allowed)
+ write_c_smooth(series.smooth) if ptrue?(@smooth_allowed)
end
end
#
# Write the <c:idx> element.
@@ -2608,24 +1025,24 @@
#
# Write the series name.
#
def write_series_name(series) # :nodoc:
- if name = series[:_name_formula]
- write_tx_formula(name, series[:_name_id])
- elsif name = series[:_name]
- write_tx_value(name)
+ if series.name_formula
+ write_tx_formula(series.name_formula, series.name_id)
+ elsif series.name
+ write_tx_value(series.name)
end
end
#
# Write the <c:cat> element.
#
def write_cat(series) # :nodoc:
- formula = series[:_categories]
- data_id = series[:_cat_data_id]
+ formula = series.categories
+ data_id = series.cat_data_id
data = @formula_data[data_id] if data_id
# Ignore <c:cat> elements for charts without category values.
return unless formula
@@ -2647,11 +1064,11 @@
#
# Write the <c:val> element.
#
def write_val(series) # :nodoc:
- write_val_base(series[:_values], series[:_val_data_id], 'c:val')
+ write_val_base(series.values, series.val_data_id, 'c:val')
end
def write_val_base(formula, data_id, tag) # :nodoc:
data = @formula_data[data_id]
@@ -2762,14 +1179,14 @@
# Write the c:minorGridlines element.
write_minor_gridlines(x_axis.minor_gridlines)
# Write the axis title elements.
- if title = x_axis.formula
- write_title_formula(title, @x_axis.data_id, horiz, @x_axis.name_font)
- elsif title = x_axis.name
- write_title_rich(title, horiz, x_axis.name_font)
+ if x_axis.formula
+ write_title_formula(x_axis, horiz, @x_axis)
+ elsif x_axis.name
+ write_title_rich(x_axis, horiz)
end
# Write the c:numFmt element.
write_cat_number_format(x_axis)
@@ -2830,14 +1247,14 @@
# Write the c:minorGridlines element.
write_minor_gridlines(y_axis.minor_gridlines)
# Write the axis title elements.
- if title = y_axis.formula
- write_title_formula(title, y_axis.data_id, horiz, y_axis.name_font)
- elsif title = y_axis.name
- write_title_rich(title, horiz, y_axis.name_font)
+ if y_axis.formula
+ write_title_formula(y_axis, horiz)
+ elsif y_axis.name
+ write_title_rich(y_axis, horiz)
end
# Write the c:numberFormat element.
write_number_format(y_axis)
@@ -2900,14 +1317,14 @@
# Write the c:minorGridlines element.
write_minor_gridlines(x_axis.minor_gridlines)
# Write the axis title elements.
- if title = x_axis.formula
- write_title_formula(title, y_axis.data_id, horiz, x_axis.name_font)
- elsif title = x_axis.name
- write_title_rich(title, horiz, x_axis.name_font)
+ if x_axis.formula
+ write_title_formula(x_axis, horiz)
+ elsif x_axis.name
+ write_title_rich(x_axis, horiz)
end
# Write the c:numberFormat element.
write_number_format(x_axis)
@@ -2966,14 +1383,14 @@
# Write the c:minorGridlines element.
write_minor_gridlines(x_axis.minor_gridlines)
# Write the axis title elements.
- if title = x_axis.formula
- write_title_formula(title, x_axis.data_id, nil, x_axis.name_font)
- elsif title = x_axis.name
- write_title_rich(title, nil, x_axis.name_font)
+ if x_axis.formula
+ write_title_formula(x_axis, nil)
+ elsif x_axis.name
+ write_title_rich(x_axis, nil)
end
# Write the c:numFmt element.
write_number_format(x_axis)
# Write the c:majorTickMark element.
write_major_tick_mark(x_axis.major_tick_mark)
@@ -3369,38 +1786,38 @@
end
#
# Write the <c:title> element for a rich string.
#
- def write_title_rich(title, horiz = nil, font = nil) # :nodoc:
+ def write_title_rich(title, horiz = nil) # :nodoc:
@writer.tag_elements('c:title') do
# Write the c:tx element.
- write_tx_rich(title, horiz, font)
+ write_tx_rich(title, horiz)
# Write the c:layout element.
write_layout
end
end
#
# Write the <c:title> element for a rich string.
#
- def write_title_formula(title, data_id, horiz = nil, font = nil) # :nodoc:
+ def write_title_formula(title, horiz = nil, axis = nil) # :nodoc:
@writer.tag_elements('c:title') do
# Write the c:tx element.
- write_tx_formula(title, data_id)
+ write_tx_formula(title.formula, axis ? axis.data_id : title.data_id)
# Write the c:layout element.
write_layout
# Write the c:txPr element.
- write_tx_pr(horiz, font)
+ write_tx_pr(horiz, axis ? axis.name_font : title.name_font)
end
end
#
# Write the <c:tx> element.
#
- def write_tx_rich(title, horiz, font = nil) # :nodoc:
- @writer.tag_elements('c:tx') { write_rich(title, horiz, font) }
+ def write_tx_rich(title, horiz) # :nodoc:
+ @writer.tag_elements('c:tx') { write_rich(title, horiz) }
end
#
# Write the <c:tx> element with a simple value such as for series names.
#
@@ -3418,18 +1835,18 @@
end
#
# Write the <c:rich> element.
#
- def write_rich(title, horiz, font) # :nodoc:
+ def write_rich(title, horiz) # :nodoc:
@writer.tag_elements('c:rich') do
# Write the a:bodyPr element.
write_a_body_pr(horiz)
# Write the a:lstStyle element.
write_a_lst_style
# Write the a:p element.
- write_a_p_rich(title, font)
+ write_a_p_rich(title)
end
end
#
# Write the <a:bodyPr> element.
@@ -3468,16 +1885,16 @@
end
#
# Write the <a:p> element for rich string titles.
#
- def write_a_p_rich(title, font) # :nodoc:
+ def write_a_p_rich(title) # :nodoc:
@writer.tag_elements('a:p') do
# Write the a:pPr element.
- write_a_p_pr_rich(font)
+ write_a_p_pr_rich(title.name_font)
# Write the a:r element.
- write_a_r(title, font)
+ write_a_r(title)
end
end
#
# Write the <a:p> element for formula titles.
@@ -3523,16 +1940,16 @@
end
#
# Write the <a:r> element.
#
- def write_a_r(title, font) # :nodoc:
+ def write_a_r(title) # :nodoc:
@writer.tag_elements('a:r') do
# Write the a:rPr element.
- write_a_r_pr(font)
+ write_a_r_pr(title.name_font)
# Write the a:t element.
- write_a_t(title)
+ write_a_t(title.name)
end
end
#
# Write the <a:rPr> element.
@@ -3629,25 +2046,28 @@
#
# Write the <c:spPr> element.
#
def write_sp_pr(series) # :nodoc:
- return if (!series.has_key?(:_line) || !ptrue?(series[:_line][:_defined])) &&
- (!series.has_key?(:_fill) || !ptrue?(series[:_fill][:_defined]))
+ line = series.respond_to?(:line) ? series.line : series[:_line]
+ fill = series.respond_to?(:fill) ? series.fill : series[:_fill]
+ return if (!line || !ptrue?(line[:_defined])) &&
+ (!fill || !ptrue?(fill[:_defined]))
+
@writer.tag_elements('c:spPr') do
# Write the fill elements for solid charts such as pie and bar.
- if series[:_fill] && series[:_fill][:_defined] != 0
- if ptrue?(series[:_fill][:none])
+ if fill && fill[:_defined] != 0
+ if ptrue?(fill[:none])
# Write the a:noFill element.
write_a_no_fill
else
# Write the a:solidFill element.
- write_a_solid_fill(series[:_fill])
+ write_a_solid_fill(fill)
end
end
# Write the a:ln element.
- write_a_ln(series[:_line]) if series[:_line] && ptrue?(series[:_line][:_defined])
+ write_a_ln(line) if line && ptrue?(line[:_defined])
end
end
#
# Write the <a:ln> element.