lib/write_xlsx/chart.rb in write_xlsx-0.75.0 vs lib/write_xlsx/chart.rb in write_xlsx-0.76.0
- old
+ new
@@ -33,10 +33,108 @@
def attributes
[ ['val', 1] ]
end
end
+ class ChartArea
+ include Writexlsx::Utility
+
+ attr_reader :line, :fill, :layout
+
+ def initialize(params = {})
+ @layout = layout_properties(params[:layout])
+
+ # Allow 'border' as a synonym for 'line'.
+ border = params_to_border(params)
+
+ # Set the line properties for the chartarea.
+ @line = border ? line_properties(border) : line_properties(params[:line])
+
+ # Map deprecated Spreadsheet::WriteExcel fill colour.
+ fill = params[:color] ? { :color => params[:color] } : params[:fill]
+ @fill = fill_properties(fill)
+ end
+
+ private
+
+ def params_to_border(params)
+ line_weight = params[:line_weight]
+
+ # Map deprecated Spreadsheet::WriteExcel line_weight.
+ border = params[:border]
+ border = { :width => swe_line_weight(line_weight) } if line_weight
+
+ # Map deprecated Spreadsheet::WriteExcel line_pattern.
+ if params[:line_pattern]
+ pattern = swe_line_pattern(params[:line_pattern])
+ if pattern == 'none'
+ border = { :none => 1 }
+ else
+ border[:dash_type] = pattern
+ end
+ end
+
+ # Map deprecated Spreadsheet::WriteExcel line colour.
+ border[:color] = params[:line_color] if params[:line_color]
+ border
+ end
+
+ #
+ # Get the Spreadsheet::WriteExcel line pattern for backward compatibility.
+ #
+ def swe_line_pattern(val)
+ swe_line_pattern_hash[numeric_or_downcase(val)] || 'solid'
+ end
+
+ def swe_line_pattern_hash
+ {
+ 0 => 'solid',
+ 1 => 'dash',
+ 2 => 'dot',
+ 3 => 'dash_dot',
+ 4 => 'long_dash_dot_dot',
+ 5 => 'none',
+ 6 => 'solid',
+ 7 => 'solid',
+ 8 => 'solid',
+ 'solid' => 'solid',
+ 'dash' => 'dash',
+ 'dot' => 'dot',
+ 'dash-dot' => 'dash_dot',
+ 'dash-dot-dot' => 'long_dash_dot_dot',
+ 'none' => 'none',
+ 'dark-gray' => 'solid',
+ 'medium-gray' => 'solid',
+ 'light-gray' => 'solid'
+ }
+ end
+
+ #
+ # Get the Spreadsheet::WriteExcel line weight for backward compatibility.
+ #
+ def swe_line_weight(val)
+ swe_line_weight_hash[numeric_or_downcase(val)] || 1
+ end
+
+ def swe_line_weight_hash
+ {
+ 1 => 0.25,
+ 2 => 1,
+ 3 => 2,
+ 4 => 3,
+ 'hairline' => 0.25,
+ 'narrow' => 1,
+ 'medium' => 2,
+ 'wide' => 3
+ }
+ end
+
+ def numeric_or_downcase(val)
+ val.respond_to?(:coerce) ? val : val.downcase
+ end
+ end
+
class Chart
include Writexlsx::Utility
attr_accessor :id, :name # :nodoc:
attr_writer :index, :palette, :protection # :nodoc:
@@ -79,49 +177,23 @@
def initialize(subtype) # :nodoc:
@writer = Package::XMLWriterSimple.new
@subtype = subtype
@sheet_type = 0x0200
- @orientation = 0x0
@series = []
@embedded = 0
@id = ''
@series_index = 0
@style_id = 2
- @axis_ids = []
- @axis2_ids = []
- @cat_has_num_fmt = false
- @requires_category = 0
- @legend_position = 'right'
- @cat_axis_position = 'b'
- @val_axis_position = 'l'
@formula_ids = {}
@formula_data = []
- @horiz_cat_axis = 0
- @horiz_val_axis = 1
@protection = 0
- @chartarea = {}
- @plotarea = {}
+ @chartarea = ChartArea.new
+ @plotarea = ChartArea.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
- @height = 288
- @x_scale = 1
- @y_scale = 1
- @x_offset = 0
- @y_offset = 0
@table = nil
- @smooth_allowed = 0
- @cross_between = 'between'
-
set_default_properties
end
def set_xml_writer(filename) # :nodoc:
@writer.set_xml_writer(filename)
@@ -172,34 +244,38 @@
#
# Set the properties of the x-axis.
#
def set_x_axis(params = {})
+ @date_category = true if ptrue?(params[:date_axis])
@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 = {})
+ @date_category = true if ptrue?(params[:date_axis])
@y_axis.merge_with_hash(params)
end
#
# Set the properties of the secondary X-axis.
#
def set_x2_axis(params = {})
+ @date_category = true if ptrue?(params[:date_axis])
@x2_axis.merge_with_hash(params)
end
#
# Set the properties of the secondary Y-axis.
#
def set_y2_axis(params = {})
+ @date_category = true if ptrue?(params[:date_axis])
@y2_axis.merge_with_hash(params)
end
#
# Set the properties of the chart title.
@@ -227,19 +303,19 @@
#
# Set the properties of the chart plotarea.
#
def set_plotarea(params)
# Convert the user defined properties to internal properties.
- @plotarea = area_properties(params)
+ @plotarea = ChartArea.new(params)
end
#
# Set the properties of the chart chartarea.
#
def set_chartarea(params)
# Convert the user defined properties to internal properties.
- @chartarea = area_properties(params)
+ @chartarea = ChartArea.new(params)
end
#
# Set on of the 42 built-in Excel chart styles. The default style is 2.
#
@@ -304,39 +380,27 @@
end
end
# Set the up and down bar properties.
@up_down_bars = {
- :_up => {
- :_line => line_properties(params[:up][:line]),
- :_fill => line_properties(params[:up][:fill])
- },
- :_down => {
- :_line => line_properties(params[:down][:line]),
- :_fill => line_properties(params[:down][:fill])
- }
+ :_up => Chartline.new(params[:up]),
+ :_down => Chartline.new(params[:down])
}
end
#
# Set properties for the chart drop lines.
#
def set_drop_lines(params = {})
- # Set the drop line properties.
- line = line_properties(params[:line])
-
- @drop_lines = { :_line => line }
+ @drop_lines = Chartline.new(params)
end
#
# Set properties for the chart high-low lines.
#
def set_high_low_lines(params = {})
- # Set the drop line properties.
- line = line_properties(params[:line])
-
- @hi_low_lines = { :_line => line }
+ @hi_low_lines = Chartline.new(params)
end
#
# Setup the default configuration data for an embedded chart.
#
@@ -388,11 +452,25 @@
#
# Convert user defined font values into private hash values.
#
def convert_font_args(params)
return unless params
- font = {
+ font = params_to_font(params)
+
+ # Convert font size units.
+ font[:_size] *= 100 if font[:_size] && font[:_size] != 0
+
+ # Convert rotation into 60,000ths of a degree.
+ if ptrue?(font[:_rotation])
+ font[:_rotation] = 60_000 * font[:_rotation].to_i
+ end
+
+ font
+ end
+
+ def params_to_font(params)
+ {
:_name => params[:name],
:_color => params[:color],
:_size => params[:size],
:_bold => params[:bold],
:_italic => params[:italic],
@@ -400,20 +478,10 @@
:_pitch_family => params[:pitch_family],
:_charset => params[:charset],
:_baseline => params[:baseline] || 0,
:_rotation => params[:rotation]
}
-
- # Convert font size units.
- font[:_size] *= 100 if font[:_size] && font[:_size] != 0
-
- # Convert rotation into 60,000ths of a degree.
- if ptrue?(font[:_rotation])
- font[:_rotation] = 60_000 * font[:_rotation].to_i
- end
-
- font
end
#
# Switch name and name_formula parameters if required.
#
@@ -433,61 +501,66 @@
# 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
+ def data_id(full_formula, data) # :nodoc:
+ return unless full_formula
# Strip the leading '=' from the formula.
- formula = formula.sub(/^=/, '')
+ formula = full_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
+ if @formula_ids.has_key?(formula)
# 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]
+ @formula_data[id] ||= data
+ else
+ # Haven't seen this formula before.
+ id = @formula_ids[formula] = @formula_data.size
+ @formula_data << data
end
id
end
- #
- # Convert user defined layout properties to the format required internally.
- #
- def layout_properties(args, is_text = false)
- return unless ptrue?(args)
+ private
- properties = is_text ? [:x, :y] : [:x, :y, :width, :height]
+ def axis_setup
+ @axis_ids = []
+ @axis2_ids = []
+ @cat_has_num_fmt = false
+ @requires_category = 0
+ @cat_axis_position = 'b'
+ @val_axis_position = 'l'
+ @horiz_cat_axis = 0
+ @horiz_val_axis = 1
+ @x_axis = Axis.new(self)
+ @y_axis = Axis.new(self)
+ @x2_axis = Axis.new(self)
+ @y2_axis = Axis.new(self)
+ end
- # Check for valid properties.
- allowable = Hash.new
- allowable[properties.size] = nil
-
- # Set the layout properties
- layout = Hash.new
- properties.each do |property|
- value = args[property]
- # Convert to the format used by Excel for easier testing.
- layout[property] = sprintf("%.17g", value)
- end
-
- layout
+ def display_setup
+ @orientation = 0x0
+ @width = 480
+ @height = 288
+ @x_scale = 1
+ @y_scale = 1
+ @x_offset = 0
+ @y_offset = 0
+ @legend_position = 'right'
+ @smooth_allowed = 0
+ @cross_between = 'between'
+ @date_category = false
+ @show_blanks = 'gap'
+ @show_hidden_data = false
+ @show_crosses = true
end
- private
-
#
# retun primary/secondary series by :primary_axes flag
#
def axes_series(params)
if params[:primary_axes] != 0
@@ -518,158 +591,22 @@
end
#
# Convert the user specified colour index or string to a rgb colour.
#
- def get_color(color) # :nodoc:
- # Convert a HTML style #RRGGBB color.
- if color and color =~ /^#[0-9a-fA-F]{6}$/
- color = color.sub(/^#/, '')
- return color.upcase
+ def color(color_code) # :nodoc:
+ if color_code and color_code =~ /^#[0-9a-fA-F]{6}$/
+ # Convert a HTML style #RRGGBB color.
+ color_code.sub(/^#/, '').upcase
+ else
+ index = Format.color(color_code)
+ raise "Unknown color '#{color_code}' used in chart formatting." unless index
+ palette_color(index)
end
-
- index = Format.get_color(color)
-
- # Set undefined colors to black.
- unless index
- index = 0x08
- raise "Unknown color '#{color}' used in chart formatting."
- end
-
- get_palette_color(index)
end
#
- # Convert from an Excel internal colour index to a XML style #RRGGBB index
- # based on the default or user defined values in the Workbook palette.
- # Note: This version doesn't add an alpha channel.
- #
- def get_palette_color(index) # :nodoc:
- palette = @palette
-
- # Adjust the colour index.
- index -= 8
-
- # Palette is passed in from the Workbook class.
- rgb = palette[index]
-
- sprintf("%02X%02X%02X", *rgb)
- end
-
- #
- # Get the Spreadsheet::WriteExcel line pattern for backward compatibility.
- #
- def get_swe_line_pattern(val)
- value = val.downcase
- default = 'solid'
-
- patterns = {
- 0 => 'solid',
- 1 => 'dash',
- 2 => 'dot',
- 3 => 'dash_dot',
- 4 => 'long_dash_dot_dot',
- 5 => 'none',
- 6 => 'solid',
- 7 => 'solid',
- 8 => 'solid',
- 'solid' => 'solid',
- 'dash' => 'dash',
- 'dot' => 'dot',
- 'dash-dot' => 'dash_dot',
- 'dash-dot-dot' => 'long_dash_dot_dot',
- 'none' => 'none',
- 'dark-gray' => 'solid',
- 'medium-gray' => 'solid',
- 'light-gray' => 'solid'
- }
-
- patterns[value] || default
- end
-
- #
- # Get the Spreadsheet::WriteExcel line weight for backward compatibility.
- #
- def get_swe_line_weight(val)
- value = val.downcase
- default = 1
-
- weights = {
- 1 => 0.25,
- 2 => 1,
- 3 => 2,
- 4 => 3,
- 'hairline' => 0.25,
- 'narrow' => 1,
- 'medium' => 2,
- 'wide' => 3
- }
-
- weights[value] || default
- end
-
- #
- # Convert user defined fill properties to the structure required internally.
- #
- def fill_properties(fill) # :nodoc:
- return { :_defined => 0 } unless fill
-
- fill[:_defined] = 1
-
- fill
- end
-
- #
- # Convert user defined area properties to the structure required internally.
- #
- def area_properties(arg) # :nodoc:
- area = {}
-
- # Map deprecated Spreadsheet::WriteExcel fill colour.
- arg[:fill] = { :color => arg[:color] } if arg[:color]
-
- # Map deprecated Spreadsheet::WriteExcel line_weight.
- if arg[:line_weight]
- width = get_swe_line_weight(arg[:line_weight])
- arg[:border] = { :width => width }
- end
-
- # Map deprecated Spreadsheet::WriteExcel line_pattern.
- if arg[:line_pattern]
- pattern = get_swe_line_pattern(arg[:line_pattern])
- if pattern == 'none'
- arg[:border] = { :none => 1 }
- else
- arg[:border][:dash_type] = pattern
- end
- end
-
- # Map deprecated Spreadsheet::WriteExcel line colour.
- arg[:border][:color] = arg[:line_color] if arg[:line_color]
-
- # Handle Excel::Writer::XLSX style properties.
-
- # Set the line properties for the chartarea.
- line = line_properties(arg[:line])
-
- # Allow 'border' as a synonym for 'line'.
- line = line_properties(arg[:border]) if (arg[:border])
-
- # Set the fill properties for the chartarea.
- fill = fill_properties(arg[:fill])
-
- # Set the plotarea layout.
- layout = layout_properties(arg[:layout])
-
- area[:_line] = line
- area[:_fill] = fill
- area[:_layout] = layout
-
- return area
- end
-
- #
# Returns series which use the primary axes.
#
def get_primary_axes_series
@series.reject {|s| s.y2_axis}
end
@@ -738,42 +675,59 @@
end
#
# Setup the default properties for a chart.
#
def set_default_properties # :nodoc:
- # Set the default axis properties.
- @x_axis.defaults = {
+ display_setup
+ axis_setup
+ set_axis_defaults
+
+ set_x_axis
+ set_y_axis
+
+ set_x2_axis
+ set_y2_axis
+ end
+
+ def set_axis_defaults
+ @x_axis.defaults = x_axis_defaults
+ @y_axis.defaults = y_axis_defaults
+ @x2_axis.defaults = x2_axis_defaults
+ @y2_axis.defaults = y2_axis_defaults
+ end
+
+ def x_axis_defaults
+ {
:num_format => 'General',
:major_gridlines => { :visible => 0 }
}
+ end
- @y_axis.defaults = {
+ def y_axis_defaults
+ {
:num_format => 'General',
:major_gridlines => { :visible => 1 }
}
+ end
- @x2_axis.defaults = {
+ def x2_axis_defaults
+ {
:num_format => 'General',
:label_position => 'none',
:crossing => 'max',
:visible => 0
}
+ end
- @y2_axis.defaults = {
+ def y2_axis_defaults
+ {
:num_format => 'General',
:major_gridlines => { :visible => 0 },
:position => 'right',
:visible => 1
}
-
- set_x_axis
- set_y_axis
-
- set_x2_axis
- set_y2_axis
end
-
#
# Write the <c:chartSpace> element.
#
def write_chart_space # :nodoc:
@writer.tag_elements('c:chartSpace', chart_space_attributes) do
@@ -844,57 +798,56 @@
end
#
# Write the <c:plotArea> element.
#
-
def write_plot_area # :nodoc:
- write_plot_area_base
- end
-
- def write_plot_area_base(type = nil) # :nodoc:
@writer.tag_elements('c:plotArea') do
# Write the c:layout element.
- write_layout(@plotarea[:_layout], 'plot')
+ write_layout(@plotarea.layout, 'plot')
# Write the subclass chart type elements for primary and secondary axes.
write_chart_type(:primary_axes => 1)
write_chart_type(:primary_axes => 0)
- # Write the c:catAx elements for series using primary axes.
+ # Write the category and value elements for the primary axes.
params = {
:x_axis => @x_axis,
:y_axis => @y_axis,
:axis_ids => @axis_ids
}
- write_cat_or_date_axis(params, type)
+
+ if @date_category
+ write_date_axis(params)
+ else
+ write_cat_axis(params)
+ end
+
write_val_axis(params)
- # Write c:valAx and c:catAx elements for series using secondary axes.
+ # Write the category and value elements for the secondary axes.
params = {
:x_axis => @x2_axis,
:y_axis => @y2_axis,
:axis_ids => @axis2_ids
}
+
write_val_axis(params)
- write_cat_or_date_axis(params, type)
+ if @date_category
+ write_date_axis(params)
+ else
+ write_cat_axis(params)
+ end
+
# Write the c:dTable element.
write_d_table
# Write the c:spPr element for the plotarea formatting.
write_sp_pr(@plotarea)
end
end
- def write_cat_or_date_axis(params, type)
- if type == :stock
- write_date_axis(params)
- else
- write_cat_axis(params)
- end
- end
-
#
# Write the <c:layout> element.
#
def write_layout(layout = nil, type = nil) # :nodoc:
tag = 'c:layout'
@@ -966,11 +919,11 @@
# Write the c:spPr element.
write_sp_pr(series)
# Write the c:marker element.
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_negative)
# Write the c:dPt element.
write_d_pt(series.points)
# Write the c:dLbls element.
write_d_lbls(series.labels)
# Write the c:trendline element.
@@ -1201,33 +1154,24 @@
end
#
# Write the <c:valAx> element. Usually the Y axis.
#
- # TODO. Maybe should have a _write_cat_val_axis method as well for scatter.
- #
- def write_val_axis(params, cat = false) # :nodoc:
+ def write_val_axis(params)
axis_ids = params[:axis_ids]
- position = params[:position] || @val_axis_position
- horiz = @horiz_val_axis
- if cat
- x_axis = params[:y_axis]
- y_axis = params[:x_axis]
- axis_ids_0 = axis_ids[1]
- axis_ids_1 = axis_ids[0]
- else
- x_axis = params[:x_axis]
- y_axis = params[:y_axis]
- axis_ids_0 = axis_ids[0]
- axis_ids_1 = axis_ids[1]
- end
-
return unless axis_ids && !axis_ids.empty?
- # OVerwrite the default axis position with a user supplied value.
- position = y_axis.position || position
+ x_axis = params[:x_axis]
+ y_axis = params[:y_axis]
+ axis_ids_0 = axis_ids[0]
+ axis_ids_1 = axis_ids[1]
+ position = y_axis.position || params[:position] || @val_axis_position
+ write_val_axis_base(x_axis, y_axis, axis_ids_0, axis_ids_1, position)
+ end
+
+ def write_val_axis_base(x_axis, y_axis, axis_ids_0, axis_ids_1, position) # :nodoc:
@writer.tag_elements('c:valAx') do
write_axis_id(axis_ids_1)
# Write the c:scaling element.
write_scaling_with_param(y_axis)
@@ -1243,13 +1187,13 @@
# Write the c:minorGridlines element.
write_minor_gridlines(y_axis.minor_gridlines)
# Write the axis title elements.
if y_axis.formula
- write_title_formula(y_axis, horiz, nil, y_axis.layout)
+ write_title_formula(y_axis, @horiz_val_axis, nil, y_axis.layout)
elsif y_axis.name
- write_title_rich(y_axis, horiz, y_axis.layout)
+ write_title_rich(y_axis, @horiz_val_axis, y_axis.layout)
end
# Write the c:numberFormat element.
write_number_format(y_axis)
@@ -1277,20 +1221,10 @@
write_c_minor_unit(y_axis.minor_unit)
end
end
#
- # Write the <c:valAx> element.
- # This is for the second valAx in scatter plots.
- #
- # Usually the X axis.
- #
- def write_cat_val_axis(params) # :nodoc:
- write_val_axis(params, true)
- end
-
- #
# Write the <c:dateAx> element. Usually the X axis.
#
def write_date_axis(params) # :nodoc:
x_axis = params[:x_axis]
y_axis = params[:y_axis]
@@ -1348,19 +1282,15 @@
# Write the c:tickLblSkip element.
write_tick_lbl_skip(x_axis.interval_unit)
# Write the c:majorUnit element.
write_c_major_unit(x_axis.major_unit)
# Write the c:majorTimeUnit element.
- if !x_axis.major_unit.nil?
- write_c_major_time_unit(x_axis.major_unit_type)
- end
+ write_c_major_time_unit(x_axis.major_unit_type) if x_axis.major_unit
# Write the c:minorUnit element.
write_c_minor_unit(x_axis.minor_unit)
# Write the c:minorTimeUnit element.
- if !x_axis.minor_unit.nil?
- write_c_minor_time_unit(x_axis.minor_unit_type)
- end
+ write_c_minor_time_unit(x_axis.minor_unit_type) if x_axis.minor_unit
end
end
def write_crossing(crossing)
# Note, the category crossing comes from the value axis.
@@ -1417,22 +1347,18 @@
#
# Write the <c:max> element.
#
def write_c_max(max = nil) # :nodoc:
- return if max.nil?
-
- @writer.empty_tag('c:max', [ ['val', max] ])
+ @writer.empty_tag('c:max', [ ['val', max] ]) if max
end
#
# Write the <c:min> element.
#
def write_c_min(min = nil) # :nodoc:
- return if min.nil?
-
- @writer.empty_tag('c:min', [ ['val', min] ])
+ @writer.empty_tag('c:min', [ ['val', min] ]) if min
end
#
# Write the <c:axPos> element.
#
@@ -1548,12 +1474,18 @@
def write_minor_gridlines(gridlines) # :nodoc:
write_gridlines_base('c:minorGridlines', gridlines)
end
def write_gridlines_base(tag, gridlines) # :nodoc:
+ return unless gridlines
return if gridlines.respond_to?(:[]) and !ptrue?(gridlines[:_visible])
- write_lines_base(tag, gridlines)
+
+ if gridlines.line_defined?
+ @writer.tag_elements(tag) { write_sp_pr(gridlines) }
+ else
+ @writer.empty_tag(tag)
+ end
end
#
# Write the <c:crossBetween> element.
#
@@ -1601,53 +1533,38 @@
#
# Write the <c:legend> element.
#
def write_legend # :nodoc:
- position = @legend_position
- overlay = false
+ position = @legend_position.sub(/^overlay_/, '')
+ return if position == 'none' || (not position_allowed.has_key?(position))
- if @legend_delete_series && @legend_delete_series.kind_of?(Array)
- @delete_series = @legend_delete_series
- end
-
- if position =~ /^overlay_/
- position.sub!(/^overlay_/, '')
- overlay = true if position
- end
-
- allowed = {
- 'right' => 'r',
- 'left' => 'l',
- 'top' => 't',
- 'bottom' => 'b'
- }
-
- return if position == 'none'
- return unless allowed.has_key?(position)
-
- position = allowed[position]
-
+ @delete_series = @legend_delete_series if @legend_delete_series.kind_of?(Array)
@writer.tag_elements('c:legend') do
# Write the c:legendPos element.
- write_legend_pos(position)
+ write_legend_pos(position_allowed[position])
# Remove series labels from the legend.
- @delete_series.each do |index|
- # Write the c:legendEntry element.
- write_legend_entry(index)
- end if @delete_series
+ # Write the c:legendEntry element.
+ @delete_series.each { |i| write_legend_entry(i) } if @delete_series
# Write the c:layout element.
write_layout(@legend_layout, 'legend')
# Write the c:txPr element.
- if ptrue?(@legend_font)
- write_tx_pr(nil, @legend_font)
- end
+ write_tx_pr(nil, @legend_font) if ptrue?(@legend_font)
# Write the c:overlay element.
- write_overlay if overlay
+ write_overlay if @legend_position =~ /^overlay_/
end
end
+ def position_allowed
+ {
+ 'right' => 'r',
+ 'left' => 'l',
+ 'top' => 't',
+ 'bottom' => 'b'
+ }
+ end
+
#
# Write the <c:legendPos> element.
#
def write_legend_pos(val) # :nodoc:
@writer.empty_tag('c:legendPos', [ ['val', val] ])
@@ -1960,17 +1877,17 @@
#
def write_marker(marker = nil) # :nodoc:
marker ||= @default_marker
return unless ptrue?(marker)
- return if ptrue?(marker[:automatic])
+ return if ptrue?(marker.automatic?)
@writer.tag_elements('c:marker') do
# Write the c:symbol element.
- write_symbol(marker[:type])
+ write_symbol(marker.type)
# Write the c:size element.
- size = marker[:size]
+ size = marker.size
write_marker_size(size) if ptrue?(size)
# Write the c:spPr element.
write_sp_pr(marker)
end
end
@@ -2000,12 +1917,12 @@
#
# Write the <c:spPr> element.
#
def write_sp_pr(series) # :nodoc:
- line = series.respond_to?(:line) ? series.line : series[:_line]
- fill = series.respond_to?(:fill) ? series.fill : series[:_fill]
+ line = series.line
+ fill = series.fill
return if (!line || !ptrue?(line[:_defined])) &&
(!fill || !ptrue?(fill[:_defined]))
@writer.tag_elements('c:spPr') do
@@ -2029,11 +1946,12 @@
#
def write_a_ln(line) # :nodoc:
attributes = []
# Add the line width as an attribute.
- if width = line[:width]
+ if line[:width]
+ width = line[:width]
# Round width to nearest 0.25, like Excel.
width = ((width + 0.125) * 4).to_i / 4.0
# Convert to internal units.
width = (0.5 + (12700 * width)).to_i
@@ -2049,13 +1967,13 @@
elsif ptrue?(line[:color])
# Write the a:solidFill element.
write_a_solid_fill(line)
end
# Write the line/dash type.
- if type = line[:dash_type]
+ if line[:dash_type]
# Write the a:prstDash element.
- write_a_prst_dash(type)
+ write_a_prst_dash(line[:dash_type])
end
end
end
#
@@ -2068,16 +1986,12 @@
#
# Write the <a:solidFill> element.
#
def write_a_solid_fill(line) # :nodoc:
@writer.tag_elements('a:solidFill') do
- if line[:color]
- color = get_color(line[:color])
-
- # Write the a:srgbClr element.
- write_a_srgb_clr(color)
- end
+ # Write the a:srgbClr element.
+ write_a_srgb_clr(color(line[:color])) if line[:color]
end
end
#
# Write the <a:srgbClr> element.
@@ -2099,23 +2013,23 @@
def write_trendline(trendline) # :nodoc:
return unless trendline
@writer.tag_elements('c:trendline') do
# Write the c:name element.
- write_name(trendline[:name])
+ write_name(trendline.name)
# Write the c:spPr element.
write_sp_pr(trendline)
# Write the c:trendlineType element.
- write_trendline_type(trendline[:type])
+ write_trendline_type(trendline.type)
# Write the c:order element for polynomial trendlines.
- write_trendline_order(trendline[:order]) if trendline[:type] == 'poly'
+ write_trendline_order(trendline.order) if trendline.type == 'poly'
# Write the c:period element for moving average trendlines.
- write_period(trendline[:period]) if trendline[:type] == 'movingAvg'
+ write_period(trendline.period) if trendline.type == 'movingAvg'
# Write the c:forward element.
- write_forward(trendline[:forward])
+ write_forward(trendline.forward)
# Write the c:backward element.
- write_backward(trendline[:backward])
+ write_backward(trendline.backward)
end
end
#
# Write the <c:trendlineType> element.
@@ -2167,27 +2081,24 @@
#
# Write the <c:hiLowLines> element.
#
def write_hi_low_lines # :nodoc:
- write_lines_base('c:hiLowLines', @hi_low_lines)
+ write_lines_base(@hi_low_lines, 'c:hiLowLines')
end
#
# Write the <c:dropLines> elent.
#
def write_drop_lines
- write_lines_base('c:dropLines', @drop_lines)
+ write_lines_base(@drop_lines, 'c:dropLines')
end
- #
- # used from write_drop_lines and write_hi_low_lines
- #
- def write_lines_base(tag, lines)
+ def write_lines_base(lines, tag)
return unless lines
- if lines[:_line] && ptrue?(lines[:_line][:_defined])
+ if lines.line_defined?
@writer.tag_elements(tag) { write_sp_pr(lines) }
else
@writer.empty_tag(tag)
end
end
@@ -2444,29 +2355,29 @@
@writer.tag_elements('c:errBars') do
# Write the c:errDir element.
write_err_dir(direction)
# Write the c:errBarType element.
- write_err_bar_type(error_bars[:_direction])
+ write_err_bar_type(error_bars.direction)
# Write the c:errValType element.
- write_err_val_type(error_bars[:_type])
+ write_err_val_type(error_bars.type)
- unless ptrue?(error_bars[:_endcap])
+ unless ptrue?(error_bars.endcap)
# Write the c:noEndCap element.
write_no_end_cap
end
- case error_bars[:_type]
+ case error_bars.type
when 'stdErr'
# Don't need to write a c:errValType tag.
when 'cust'
# Write the custom error tags.
write_custom_error(error_bars)
else
# Write the c:val element.
- write_error_val(error_bars[:_value])
+ write_error_val(error_bars.value)
end
# Write the c:spPr element.
write_sp_pr(error_bars)
end
@@ -2509,30 +2420,30 @@
#
# Write the custom error bars type.
#
def write_custom_error(error_bars)
- if ptrue?(error_bars[:_plus_values])
- # Write the c:plus element.
- @writer.tag_elements('c:plus') do
- if error_bars[:_plus_values] =~ /^=/ # '=Sheet1!$A$1:$A$5'
- write_num_ref(error_bars[:_plus_values], error_bars[:_plus_data], 'num')
- else # [1, 2, 3]
- write_num_lit(error_bars[:_plus_values])
- end
- end
- # Write the c:minus element.
- @writer.tag_elements('c:minus') do
- if error_bars[:_minus_values] =~ /^=/ # '=Sheet1!$A$1:$A$5'
- write_num_ref(error_bars[:_minus_values], error_bars[:_minus_data], 'num')
- else # [1, 2, 3]
- write_num_lit(error_bars[:_minus_values])
- end
- end
+ if ptrue?(error_bars.plus_values)
+ write_custom_error_base('c:plus', error_bars.plus_values, error_bars.plus_data)
+ write_custom_error_base('c:minus', error_bars.minus_values, error_bars.minus_data)
end
end
+ def write_custom_error_base(tag, values, data)
+ @writer.tag_elements(tag) do
+ write_num_ref_or_lit(values, data)
+ end
+ end
+
+ def write_num_ref_or_lit(values, data)
+ if values =~ /^=/ # '=Sheet1!$A$1:$A$5'
+ write_num_ref(values, data, 'num')
+ else # [1, 2, 3]
+ write_num_lit(values)
+ end
+ end
+
#
# Write the <c:upDownBars> element.
#
def write_up_down_bars
return unless ptrue?(@up_down_bars)
@@ -2582,10 +2493,10 @@
@writer.empty_tag('c:smooth', attributes)
end
def write_bars_base(tag, format)
- if ptrue?(format[:_line][:_defined]) || ptrue?(format[:_fill][:_defined])
+ if format.line_defined? || format.fill_defined?
@writer.tag_elements(tag) { write_sp_pr(format) }
else
@writer.empty_tag(tag)
end
end