write_xlsx 0.62.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. data/README.rdoc +14 -1
  2. data/examples/chart_data_tools.rb +215 -0
  3. data/examples/chart_pie.rb +36 -5
  4. data/examples/sparklines2.rb +1 -1
  5. data/examples/tab_colors.rb +3 -3
  6. data/lib/write_xlsx/chart.rb +559 -516
  7. data/lib/write_xlsx/chart/area.rb +4 -1
  8. data/lib/write_xlsx/chart/axis.rb +132 -0
  9. data/lib/write_xlsx/chart/bar.rb +17 -9
  10. data/lib/write_xlsx/chart/column.rb +9 -1
  11. data/lib/write_xlsx/chart/line.rb +24 -0
  12. data/lib/write_xlsx/chart/radar.rb +2 -2
  13. data/lib/write_xlsx/chart/scatter.rb +19 -0
  14. data/lib/write_xlsx/chart/stock.rb +10 -3
  15. data/lib/write_xlsx/drawing.rb +43 -44
  16. data/lib/write_xlsx/package/vml.rb +21 -14
  17. data/lib/write_xlsx/shape.rb +173 -22
  18. data/lib/write_xlsx/sparkline.rb +524 -0
  19. data/lib/write_xlsx/version.rb +1 -1
  20. data/lib/write_xlsx/workbook.rb +183 -115
  21. data/lib/write_xlsx/worksheet.rb +821 -1073
  22. data/lib/write_xlsx/worksheet/cell_data.rb +132 -0
  23. data/lib/write_xlsx/worksheet/print_style.rb +51 -0
  24. data/test/chart/test_add_series.rb +31 -6
  25. data/test/chart/test_write_d_lbls.rb +18 -18
  26. data/test/chart/test_write_number_format.rb +20 -24
  27. data/test/drawing/test_drawing_shape_01.rb +1 -1
  28. data/test/drawing/test_drawing_shape_02.rb +2 -2
  29. data/test/drawing/test_drawing_shape_03.rb +5 -5
  30. data/test/drawing/test_drawing_shape_04.rb +3 -3
  31. data/test/drawing/test_drawing_shape_05.rb +4 -4
  32. data/test/drawing/test_drawing_shape_07.rb +2 -2
  33. data/test/perl_output/chart_data_tools.xlsx +0 -0
  34. data/test/perl_output/chart_pie.xlsx +0 -0
  35. data/test/regression/disabled_test_vml04.rb +2 -2
  36. data/test/regression/test_chart_drop_lines01.rb +46 -0
  37. data/test/regression/test_chart_drop_lines02.rb +51 -0
  38. data/test/regression/test_chart_drop_lines03.rb +46 -0
  39. data/test/regression/test_chart_drop_lines04.rb +64 -0
  40. data/test/regression/test_chart_errorbars01.rb +47 -0
  41. data/test/regression/test_chart_errorbars02.rb +57 -0
  42. data/test/regression/test_chart_errorbars03.rb +53 -0
  43. data/test/regression/test_chart_errorbars04.rb +48 -0
  44. data/test/regression/test_chart_errorbars05.rb +47 -0
  45. data/test/regression/test_chart_errorbars06.rb +47 -0
  46. data/test/regression/test_chart_errorbars07.rb +66 -0
  47. data/test/regression/test_chart_font02.rb +1 -1
  48. data/test/regression/test_chart_font06.rb +1 -1
  49. data/test/regression/test_chart_gridlines04.rb +2 -1
  50. data/test/regression/test_chart_gridlines08.rb +2 -1
  51. data/test/regression/test_chart_points01.rb +37 -0
  52. data/test/regression/test_chart_points02.rb +40 -0
  53. data/test/regression/test_chart_points03.rb +42 -0
  54. data/test/regression/test_chart_points04.rb +52 -0
  55. data/test/regression/test_chart_points05.rb +49 -0
  56. data/test/regression/test_chart_points06.rb +49 -0
  57. data/test/regression/test_chartsheet05.rb +1 -1
  58. data/test/regression/test_chartsheet06.rb +1 -1
  59. data/test/regression/test_comment01.rb +1 -1
  60. data/test/regression/test_comment02.rb +1 -1
  61. data/test/regression/test_comment03.rb +1 -1
  62. data/test/regression/test_comment04.rb +2 -2
  63. data/test/regression/test_comment06.rb +1 -1
  64. data/test/regression/test_comment07.rb +1 -1
  65. data/test/regression/test_comment08.rb +1 -1
  66. data/test/regression/test_comment09.rb +1 -1
  67. data/test/regression/test_comment10.rb +1 -1
  68. data/test/regression/test_default_row04.rb +1 -1
  69. data/test/regression/test_escapes02.rb +1 -1
  70. data/test/regression/test_hyperlink15.rb +2 -2
  71. data/test/regression/test_shape_connect01.rb +6 -6
  72. data/test/regression/test_shape_connect02.rb +6 -6
  73. data/test/regression/test_shape_connect03.rb +11 -11
  74. data/test/regression/test_shape_connect04.rb +10 -10
  75. data/test/regression/test_shape_scale01.rb +2 -2
  76. data/test/regression/test_shape_stencil01.rb +3 -3
  77. data/test/regression/test_tab_color01.rb +1 -1
  78. data/test/regression/test_table04.rb +1 -1
  79. data/test/regression/test_table05.rb +1 -1
  80. data/test/regression/test_table06.rb +1 -1
  81. data/test/regression/test_vml01.rb +1 -1
  82. data/test/regression/test_vml02.rb +1 -1
  83. data/test/regression/test_vml03.rb +2 -2
  84. data/test/regression/xlsx_files/chart_drop_lines01.xlsx +0 -0
  85. data/test/regression/xlsx_files/chart_drop_lines02.xlsx +0 -0
  86. data/test/regression/xlsx_files/chart_drop_lines03.xlsx +0 -0
  87. data/test/regression/xlsx_files/chart_drop_lines04.xlsx +0 -0
  88. data/test/regression/xlsx_files/chart_errorbars01.xlsx +0 -0
  89. data/test/regression/xlsx_files/chart_errorbars02.xlsx +0 -0
  90. data/test/regression/xlsx_files/chart_errorbars03.xlsx +0 -0
  91. data/test/regression/xlsx_files/chart_errorbars04.xlsx +0 -0
  92. data/test/regression/xlsx_files/chart_errorbars05.xlsx +0 -0
  93. data/test/regression/xlsx_files/chart_errorbars06.xlsx +0 -0
  94. data/test/regression/xlsx_files/chart_errorbars07.xlsx +0 -0
  95. data/test/regression/xlsx_files/chart_points01.xlsx +0 -0
  96. data/test/regression/xlsx_files/chart_points02.xlsx +0 -0
  97. data/test/regression/xlsx_files/chart_points03.xlsx +0 -0
  98. data/test/regression/xlsx_files/chart_points04.xlsx +0 -0
  99. data/test/regression/xlsx_files/chart_points05.xlsx +0 -0
  100. data/test/regression/xlsx_files/chart_points06.xlsx +0 -0
  101. data/test/regression/xlsx_files/chart_stock02.xlsx +0 -0
  102. data/test/test_example_match.rb +278 -57
  103. data/test/worksheet/test_convert_date_time_02.rb +427 -433
  104. data/test/worksheet/test_convert_date_time_03.rb +1 -1
  105. data/test/worksheet/test_write_sheet_pr.rb +2 -2
  106. data/test/worksheet/test_write_sheet_view1.rb +2 -2
  107. metadata +80 -10
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = write_xlsx
2
2
 
3
- gem to create a new file in the Excel 2007+ XLSX format, and you can use the same interface as writeexcel gem. write_xlsx is converted from Perl's module Excel::Writer::XLSX-0.62, https://github.com/jmcnamara/excel-writer-xlsx .
3
+ gem to create a new file in the Excel 2007+ XLSX format, and you can use the same interface as writeexcel gem. write_xlsx is converted from Perl's module Excel::Writer::XLSX-0.63, https://github.com/jmcnamara/excel-writer-xlsx .
4
4
 
5
5
  == Description
6
6
 
@@ -75,6 +75,19 @@ the first worksheet in an Excel XML spreadsheet called ruby.xlsx:
75
75
  workbook.close
76
76
 
77
77
  == Recent change
78
+ 2013-03-05 v0.64.0
79
+ Added the option to format individual points in a chart series.
80
+ This allows Pie chart segments to be formatted.
81
+
82
+
83
+ 2013-03-05 v0.63.0
84
+ Added Chart data tools such as:
85
+ Error Bars
86
+ Up-Down Bars
87
+ High-Low Lines
88
+ Drop Lines.
89
+ See the chart_data_tools.rb example.
90
+
78
91
  2013-02-24 v0.62.0
79
92
  Added option for adding a data table to a Chart X-axis.
80
93
  See output from chart_data_table.rb example.
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #######################################################################
5
+ #
6
+ # A demo of an various Excel chart data tools that are available via
7
+ # an WriteXLSX chart.
8
+ #
9
+ # These include, Trendlines, Data Labels, Error Bars, Drop Lines,
10
+ # High-Low Lines and Up-Down Bars.
11
+ #
12
+ # reverse ('(c)'), December 2012, John McNamara, jmcnamara@cpan.org
13
+ # convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
14
+ #
15
+
16
+ require 'rubygems'
17
+ require 'write_xlsx'
18
+
19
+ # Create a new workbook called simple.xls and add a worksheet
20
+ workbook = WriteXLSX.new('chart_data_tools.xlsx')
21
+ worksheet = workbook.add_worksheet
22
+ bold = workbook.add_format(:bold => 1)
23
+
24
+ # Add the worksheet data that the charts will refer to.
25
+ headings = [ 'Number', 'Data 1', 'Data 2' ]
26
+ data = [
27
+ [ 2, 3, 4, 5, 6, 7 ],
28
+ [ 10, 40, 50, 20, 10, 50 ],
29
+ [ 30, 60, 70, 50, 40, 30 ]
30
+
31
+ ]
32
+
33
+ worksheet.write('A1', headings, bold)
34
+ worksheet.write('A2', data)
35
+
36
+
37
+ #######################################################################
38
+ #
39
+ # Trendline example.
40
+ #
41
+
42
+ # Create a Line chart.
43
+ chart1 = workbook.add_chart(:type => 'line', :embedded => 1)
44
+
45
+ # Configure the first series with a polynomial trendline.
46
+ chart1.add_series(
47
+ :categories => '=Sheet1!$A$2:$A$7',
48
+ :values => '=Sheet1!$B$2:$B$7',
49
+ :trendline => {
50
+ :type => 'polynomial',
51
+ :order => 3,
52
+ },
53
+ )
54
+
55
+ # Configure the second series with a moving average trendline.
56
+ chart1.add_series(
57
+ :categories => '=Sheet1!$A$2:$A$7',
58
+ :values => '=Sheet1!$C$2:$C$7',
59
+ :trendline => { :type => 'linear' },
60
+ )
61
+
62
+ # Add a chart title. and some axis labels.
63
+ chart1.set_title(:name => 'Chart with Trendlines')
64
+
65
+ # Insert the chart into the worksheet (with an offset).
66
+ worksheet.insert_chart('D2', chart1, 25, 10)
67
+
68
+
69
+ #######################################################################
70
+ #
71
+ # Data Labels and Markers example.
72
+ #
73
+
74
+ # Create a Line chart.
75
+ chart2 = workbook.add_chart(:type => 'line', :embedded => 1)
76
+
77
+ # Configure the first series.
78
+ chart2.add_series(
79
+ :categories => '=Sheet1!$A$2:$A$7',
80
+ :values => '=Sheet1!$B$2:$B$7',
81
+ :data_labels => { :value => 1 },
82
+ :marker => { :type => 'automatic' },
83
+ )
84
+
85
+ # Configure the second series.
86
+ chart2.add_series(
87
+ :categories => '=Sheet1!$A$2:$A$7',
88
+ :values => '=Sheet1!$C$2:$C$7',
89
+ )
90
+
91
+ # Add a chart title. and some axis labels.
92
+ chart2.set_title(:name => 'Chart with Data Labels and Markers')
93
+
94
+ # Insert the chart into the worksheet (with an offset).
95
+ worksheet.insert_chart('D18', chart2, 25, 10)
96
+
97
+
98
+ #######################################################################
99
+ #
100
+ # Error Bars example.
101
+ #
102
+
103
+ # Create a Line chart.
104
+ chart3 = workbook.add_chart(:type => 'line', :embedded => 1)
105
+
106
+ # Configure the first series.
107
+ chart3.add_series(
108
+ :categories => '=Sheet1!$A$2:$A$7',
109
+ :values => '=Sheet1!$B$2:$B$7',
110
+ :y_error_bars => { :type => 'standard_error' },
111
+ )
112
+
113
+ # Configure the second series.
114
+ chart3.add_series(
115
+ :categories => '=Sheet1!$A$2:$A$7',
116
+ :values => '=Sheet1!$C$2:$C$7',
117
+ )
118
+
119
+ # Add a chart title. and some axis labels.
120
+ chart3.set_title(:name => 'Chart with Error Bars')
121
+
122
+ # Insert the chart into the worksheet (with an offset).
123
+ worksheet.insert_chart('D34', chart3, 25, 10)
124
+
125
+
126
+ #######################################################################
127
+ #
128
+ # Up-Down Bars example.
129
+ #
130
+
131
+ # Create a Line chart.
132
+ chart4 = workbook.add_chart(:type => 'line', :embedded => 1)
133
+
134
+ # Add the Up-Down Bars.
135
+ chart4.set_up_down_bars
136
+
137
+ # Configure the first series.
138
+ chart4.add_series(
139
+ :categories => '=Sheet1!$A$2:$A$7',
140
+ :values => '=Sheet1!$B$2:$B$7',
141
+ )
142
+
143
+ # Configure the second series.
144
+ chart4.add_series(
145
+ :categories => '=Sheet1!$A$2:$A$7',
146
+ :values => '=Sheet1!$C$2:$C$7',
147
+ )
148
+
149
+ # Add a chart title. and some axis labels.
150
+ chart4.set_title(:name => 'Chart with Up-Down Bars')
151
+
152
+ # Insert the chart into the worksheet (with an offset).
153
+ worksheet.insert_chart('D50', chart4, 25, 10)
154
+
155
+
156
+ #######################################################################
157
+ #
158
+ # High-Low Lines example.
159
+ #
160
+
161
+ # Create a Line chart.
162
+ chart5 = workbook.add_chart(:type => 'line', :embedded => 1)
163
+
164
+ # Add the High-Low lines.
165
+ chart5.set_high_low_lines
166
+
167
+ # Configure the first series.
168
+ chart5.add_series(
169
+ :categories => '=Sheet1!$A$2:$A$7',
170
+ :values => '=Sheet1!$B$2:$B$7',
171
+ )
172
+
173
+ # Configure the second series.
174
+ chart5.add_series(
175
+ :categories => '=Sheet1!$A$2:$A$7',
176
+ :values => '=Sheet1!$C$2:$C$7',
177
+ )
178
+
179
+ # Add a chart title. and some axis labels.
180
+ chart5.set_title(:name => 'Chart with High-Low Lines')
181
+
182
+ # Insert the chart into the worksheet (with an offset).
183
+ worksheet.insert_chart('D66', chart5, 25, 10)
184
+
185
+
186
+ #######################################################################
187
+ #
188
+ # Drop Lines example.
189
+ #
190
+
191
+ # Create a Line chart.
192
+ chart6 = workbook.add_chart(:type => 'line', :embedded => 1)
193
+
194
+ # Add Drop Lines.
195
+ chart6.set_drop_lines
196
+
197
+ # Configure the first series.
198
+ chart6.add_series(
199
+ :categories => '=Sheet1!$A$2:$A$7',
200
+ :values => '=Sheet1!$B$2:$B$7',
201
+ )
202
+
203
+ # Configure the second series.
204
+ chart6.add_series(
205
+ :categories => '=Sheet1!$A$2:$A$7',
206
+ :values => '=Sheet1!$C$2:$C$7',
207
+ )
208
+
209
+ # Add a chart title. and some axis labels.
210
+ chart6.set_title(:name => 'Chart with Drop Lines')
211
+
212
+ # Insert the chart into the worksheet (with an offset).
213
+ worksheet.insert_chart('D82', chart6, 25, 10)
214
+
215
+ workbook.close
@@ -5,6 +5,12 @@
5
5
  #
6
6
  # A demo of a Pie chart in Excel::Writer::XLSX.
7
7
  #
8
+ # The demo also shows how to set segment colours. It is possible to
9
+ # define chart colors for most types of WrtieXLSX charts
10
+ # via the add_series() method. However, Pie charts are a special case
11
+ # since each segment is represented as a point so it is necessary to
12
+ # assign formatting to each point in the series.
13
+ #
8
14
  # reverse(c), March 2011, John McNamara, jmcnamara@cpan.org
9
15
  # convert to ruby by Hideo NAKAMURA, cxn03651@msj.biglobe.ne.jp
10
16
  #
@@ -27,23 +33,48 @@
27
33
  worksheet.write('A2', data)
28
34
 
29
35
  # Create a new chart object. In this case an embedded chart.
30
- chart = workbook.add_chart(:type => 'pie', :embedded => 1)
36
+ chart1 = workbook.add_chart(:type => 'pie', :embedded => 1)
31
37
 
32
38
  # Configure the series. Note the use of the array ref to define ranges:
33
39
  # [ $sheetname, $row_start, $row_end, $col_start, $col_end ].
34
- chart.add_series(
40
+ # See below for an alternative syntax.
41
+ chart1.add_series(
35
42
  :name => 'Pie sales data',
36
43
  :categories => [ 'Sheet1', 1, 3, 0, 0 ],
37
44
  :values => [ 'Sheet1', 1, 3, 1, 1 ]
38
45
  )
39
46
 
40
47
  # Add a title.
41
- chart.set_title(:name => 'Popular Pie Types')
48
+ chart1.set_title(:name => 'Popular Pie Types')
42
49
 
43
50
  # Set an Excel chart style. Blue colors with white outline and shadow.
44
- chart.set_style(10)
51
+ chart1.set_style(10)
45
52
 
46
53
  # Insert the chart into the worksheet (with an offset).
47
- worksheet.insert_chart('C2', chart, 25, 10)
54
+ worksheet.insert_chart('C2', chart1, 25, 10)
55
+
56
+ #
57
+ # Create a Pie chart with user defined segment colors.
58
+ #
59
+
60
+ # Create an example Pie chart like above.
61
+ chart2 = workbook.add_chart(:type => 'pie', :embedded => 1)
62
+
63
+ # Configure the series and add user defined segment colours.
64
+ chart2.add_series(
65
+ :name => 'Pie sales data',
66
+ :categories => '=Sheet1!$A$2:$A$4',
67
+ :values => '=Sheet1!$B$2:$B$4',
68
+ :points => [
69
+ { :fill => { :color => '#5ABA10' } },
70
+ { :fill => { :color => '#FE110E' } },
71
+ { :fill => { :color => '#CA5C05' } }
72
+ ]
73
+ )
74
+
75
+ # Add a title.
76
+ chart2.set_title(:name => 'Pie Chart with user defined colors')
77
+
78
+ worksheet.insert_chart('C18', chart2, 25, 10)
48
79
 
49
80
  workbook.close
@@ -25,7 +25,7 @@
25
25
  # Set the columns widths to make the output clearer.
26
26
  worksheet1.set_column('A:A', 14)
27
27
  worksheet1.set_column('B:B', 50)
28
- worksheet1.set_zoom(150)
28
+ worksheet1.zoom = 150
29
29
 
30
30
  # Headings.
31
31
  worksheet1.write('A1', 'Sparkline', bold)
@@ -19,8 +19,8 @@
19
19
  worksheet4 = workbook.add_worksheet
20
20
 
21
21
  # Worksheet1 will have the default tab colour.
22
- worksheet2.set_tab_color('red')
23
- worksheet3.set_tab_color('green')
24
- worksheet4.set_tab_color(0x35) # Orange
22
+ worksheet2.tab_color = 'red'
23
+ worksheet3.tab_color = 'green'
24
+ worksheet4.tab_color = 0x35 # Orange
25
25
 
26
26
  workbook.close
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'write_xlsx/package/xml_writer_simple'
3
3
  require 'write_xlsx/utility'
4
+ require 'write_xlsx/chart/axis'
4
5
 
5
6
  module Writexlsx
6
7
  class Table
@@ -468,7 +469,7 @@ class Chart
468
469
  attr_writer :index, :palette, :protection # :nodoc:
469
470
  attr_reader :embedded, :formula_ids, :formula_data # :nodoc:
470
471
  attr_reader :x_scale, :y_scale, :x_offset, :y_offset # :nodoc:
471
- attr_reader :width, :height
472
+ attr_reader :width, :height # :nodoc:
472
473
 
473
474
  #
474
475
  # Factory method for returning chart objects based on their class type.
@@ -527,10 +528,10 @@ def initialize(subtype) # :nodoc:
527
528
  @protection = 0
528
529
  @chartarea = {}
529
530
  @plotarea = {}
530
- @x_axis = {}
531
- @y_axis = {}
532
- @x2_axis = {}
533
- @y2_axis = {}
531
+ @x_axis = Axis.new
532
+ @y_axis = Axis.new
533
+ @x2_axis = Axis.new
534
+ @y2_axis = Axis.new
534
535
  @name = ''
535
536
  @show_blanks = 'gap'
536
537
  @show_hidden_data = false
@@ -699,22 +700,29 @@ def add_series(params)
699
700
  name_id = get_data_id(name_formula, params[:name_data])
700
701
 
701
702
  # Set the line properties for the series.
702
- line = get_line_properties(params[:line])
703
+ line = line_properties(params[:line])
703
704
 
704
705
  # Allow 'border' as a synonym for 'line' in bar/column style charts.
705
- line = get_line_properties(params[:border]) if params[:border]
706
+ line = line_properties(params[:border]) if params[:border]
706
707
 
707
708
  # Set the fill properties for the series.
708
- fill = get_fill_properties(params[:fill])
709
+ fill = fill_properties(params[:fill])
709
710
 
710
711
  # Set the marker properties for the series.
711
- marker = get_marker_properties(params[:marker])
712
+ marker = marker_properties(params[:marker])
712
713
 
713
714
  # Set the trendline properties for the series.
714
- trendline = get_trendline_properties(params[:trendline])
715
+ trendline = trendline_properties(params[:trendline])
716
+
717
+ # Set the error bars properties for the series.
718
+ y_error_bars = error_bars_properties(params[:y_error_bars])
719
+ x_error_bars = error_bars_properties(params[:x_error_bars])
720
+
721
+ # Set the point properties for the series.
722
+ points = points_properties(params[:points])
715
723
 
716
724
  # Set the labels properties for the series.
717
- labels = get_labels_properties(params[:data_labels])
725
+ labels = labels_properties(params[:data_labels])
718
726
 
719
727
  # Set the "invert if negative" fill property.
720
728
  invert_if_neg = params[:invert_if_negative]
@@ -739,7 +747,12 @@ def add_series(params)
739
747
  :_labels => labels,
740
748
  :_invert_if_neg => invert_if_neg,
741
749
  :_x2_axis => x2_axis,
742
- :_y2_axis => y2_axis
750
+ :_y2_axis => y2_axis,
751
+ :_points => points,
752
+ :_error_bars => {
753
+ :_x_error_bars => x_error_bars,
754
+ :_y_error_bars => y_error_bars
755
+ }
743
756
  }
744
757
  end
745
758
 
@@ -842,7 +855,7 @@ def add_series(params)
842
855
  # )
843
856
  #
844
857
  def set_x_axis(params = {})
845
- @x_axis = convert_axis_args(@x_axis, params)
858
+ @x_axis.merge_with_hash(self, params)
846
859
  end
847
860
 
848
861
  #
@@ -852,21 +865,21 @@ def set_x_axis(params = {})
852
865
  # The properties that can be set are the same as for set_x_axis,
853
866
  #
854
867
  def set_y_axis(params = {})
855
- @y_axis = convert_axis_args(@y_axis, params)
868
+ @y_axis.merge_with_hash(self, params)
856
869
  end
857
870
 
858
871
  #
859
872
  # Set the properties of the secondary X-axis.
860
873
  #
861
874
  def set_x2_axis(params = {})
862
- @x2_axis = convert_axis_args(@x2_axis, params)
875
+ @x2_axis.merge_with_hash(self, params)
863
876
  end
864
877
 
865
878
  #
866
879
  # Set the properties of the secondary Y-axis.
867
880
  #
868
881
  def set_y2_axis(params = {})
869
- @y2_axis = convert_axis_args(@y2_axis, params)
882
+ @y2_axis.merge_with_hash(self, params)
870
883
  end
871
884
 
872
885
  #
@@ -884,7 +897,6 @@ def set_y2_axis(params = {})
884
897
  #
885
898
  def set_title(params)
886
899
  name, name_formula = process_names(params[:name], params[:name_formula])
887
-
888
900
  data_id = get_data_id(name_formula, params[:data])
889
901
 
890
902
  @title_name = name
@@ -941,7 +953,7 @@ def set_legend(params)
941
953
  #
942
954
  def set_plotarea(params)
943
955
  # Convert the user defined properties to internal properties.
944
- @plotarea = get_area_properties(params)
956
+ @plotarea = area_properties(params)
945
957
  end
946
958
 
947
959
  #
@@ -956,7 +968,7 @@ def set_plotarea(params)
956
968
  #
957
969
  def set_chartarea(params)
958
970
  # Convert the user defined properties to internal properties.
959
- @chartarea = get_area_properties(params)
971
+ @chartarea = area_properties(params)
960
972
  end
961
973
 
962
974
  #
@@ -1036,6 +1048,52 @@ def set_table(params = {})
1036
1048
  @table = Table.new(params)
1037
1049
  end
1038
1050
 
1051
+ #
1052
+ # Set properties for the chart up-down bars.
1053
+ #
1054
+ def set_up_down_bars(params = {})
1055
+ # Map border to line.
1056
+ [:up, :down].each do |up_down|
1057
+ if params[up_down]
1058
+ params[up_down][:line] = params[up_down][:border] if params[up_down][:border]
1059
+ else
1060
+ params[up_down] = {}
1061
+ end
1062
+ end
1063
+
1064
+ # Set the up and down bar properties.
1065
+ @up_down_bars = {
1066
+ :_up => {
1067
+ :_line => line_properties(params[:up][:line]),
1068
+ :_fill => line_properties(params[:up][:fill])
1069
+ },
1070
+ :_down => {
1071
+ :_line => line_properties(params[:down][:line]),
1072
+ :_fill => line_properties(params[:down][:fill])
1073
+ }
1074
+ }
1075
+ end
1076
+
1077
+ #
1078
+ # Set properties for the chart drop lines.
1079
+ #
1080
+ def set_drop_lines(params = {})
1081
+ # Set the drop line properties.
1082
+ line = line_properties(params[:line])
1083
+
1084
+ @drop_lines = { :_line => line }
1085
+ end
1086
+
1087
+ #
1088
+ # Set properties for the chart high-low lines.
1089
+ #
1090
+ def set_high_low_lines(params = {})
1091
+ # Set the drop line properties.
1092
+ line = line_properties(params[:line])
1093
+
1094
+ @hi_low_lines = { :_line => line }
1095
+ end
1096
+
1039
1097
  #
1040
1098
  # Setup the default configuration data for an embedded chart.
1041
1099
  #
@@ -1076,67 +1134,51 @@ def write_bar_chart(params) # :nodoc:
1076
1134
  end
1077
1135
  end
1078
1136
 
1079
- private
1080
-
1081
1137
  #
1082
- # retun primary/secondary series by :primary_axes flag
1138
+ # Switch name and name_formula parameters if required.
1083
1139
  #
1084
- def axes_series(params)
1085
- if params[:primary_axes] != 0
1086
- primary_axes_series
1087
- else
1088
- secondary_axes_series
1140
+ def process_names(name = nil, name_formula = nil) # :nodoc:
1141
+ # Name looks like a formula, use it to set name_formula.
1142
+ if name && name =~ /^=[^!]+!\$/
1143
+ name_formula = name
1144
+ name = ''
1089
1145
  end
1146
+
1147
+ [name, name_formula]
1090
1148
  end
1091
1149
 
1092
1150
  #
1093
- # Convert user defined axis values into private hash values.
1151
+ # Assign an id to a each unique series formula or title/axis formula. Repeated
1152
+ # formulas such as for categories get the same id. If the series or title
1153
+ # has user specified data associated with it then that is also stored. This
1154
+ # data is used to populate cached Excel data when creating a chart.
1155
+ # If there is no user defined data then it will be populated by the parent
1156
+ # workbook in Workbook::_add_chart_data
1094
1157
  #
1095
- def convert_axis_args(axis, params) # :nodoc:
1096
- arg = (axis[:_defaults] || {}).merge(params)
1097
- name, name_formula = process_names(arg[:name], arg[:name_formula])
1158
+ def get_data_id(formula, data) # :nodoc:
1159
+ # Ignore series without a range formula.
1160
+ return unless formula
1098
1161
 
1099
- data_id = get_data_id(name_formula, arg[:data])
1162
+ # Strip the leading '=' from the formula.
1163
+ formula = formula.sub(/^=/, '')
1100
1164
 
1101
- axis = {
1102
- :_defaults => axis[:_defaults],
1103
- :_name => name,
1104
- :_formula => name_formula,
1105
- :_data_id => data_id,
1106
- :_reverse => arg[:reverse],
1107
- :_min => arg[:min],
1108
- :_max => arg[:max],
1109
- :_minor_unit => arg[:minor_unit],
1110
- :_major_unit => arg[:major_unit],
1111
- :_minor_unit_type => arg[:minor_unit_type],
1112
- :_major_unit_type => arg[:major_unit_type],
1113
- :_log_base => arg[:log_base],
1114
- :_crossing => arg[:crossing],
1115
- :_position => arg[:position],
1116
- :_label_position => arg[:label_position],
1117
- :_num_format => arg[:num_format],
1118
- :_num_format_linked => arg[:num_format_linked],
1119
- :_visible => arg[:visible] || 1
1120
- }
1165
+ # Store the data id in a hash keyed by the formula and store the data
1166
+ # in a separate array with the same id.
1167
+ if !@formula_ids.has_key?(formula)
1168
+ # Haven't seen this formula before.
1169
+ id = @formula_data.size
1121
1170
 
1122
- # Map major_gridlines properties.
1123
- if arg[:major_gridlines] && ptrue?(arg[:major_gridlines][:visible])
1124
- axis[:_major_gridlines] = get_gridline_properties(arg[:major_gridlines])
1125
- end
1171
+ @formula_data << data
1172
+ @formula_ids[formula] = id
1173
+ else
1174
+ # Formula already seen. Return existing id.
1175
+ id = @formula_ids[formula]
1126
1176
 
1127
- # Map minor_gridlines properties.
1128
- if arg[:minor_gridlines] && ptrue?(arg[:minor_gridlines][:visible])
1129
- axis[:_minor_gridlines] = get_gridline_properties(arg[:minor_gridlines])
1177
+ # Store user defined data if it isn't already there.
1178
+ @formula_data[id] = data unless @formula_data[id]
1130
1179
  end
1131
1180
 
1132
- # Only use the first letter of bottom, top, left or right.
1133
- axis[:_position] = axis[:_position].downcase[0, 1] if axis[:_position]
1134
-
1135
- # Set the font properties if present.
1136
- axis[:_num_font] = convert_font_args(arg[:num_font])
1137
- axis[:_name_font] = convert_font_args(arg[:name_font])
1138
-
1139
- axis
1181
+ id
1140
1182
  end
1141
1183
 
1142
1184
  #
@@ -1163,25 +1205,57 @@ def convert_font_args(params)
1163
1205
  end
1164
1206
 
1165
1207
  #
1166
- # Convert and aref of row col values to a range formula.
1208
+ # Convert user defined line properties to the structure required internally.
1167
1209
  #
1168
- def aref_to_formula(data) # :nodoc:
1169
- # If it isn't an array ref it is probably a formula already.
1170
- return data unless data.kind_of?(Array)
1171
- xl_range_formula(*data)
1210
+ def line_properties(line) # :nodoc:
1211
+ return { :_defined => 0 } unless line
1212
+
1213
+ dash_types = {
1214
+ :solid => 'solid',
1215
+ :round_dot => 'sysDot',
1216
+ :square_dot => 'sysDash',
1217
+ :dash => 'dash',
1218
+ :dash_dot => 'dashDot',
1219
+ :long_dash => 'lgDash',
1220
+ :long_dash_dot => 'lgDashDot',
1221
+ :long_dash_dot_dot => 'lgDashDotDot',
1222
+ :dot => 'dot',
1223
+ :system_dash_dot => 'sysDashDot',
1224
+ :system_dash_dot_dot => 'sysDashDotDot'
1225
+ }
1226
+
1227
+ # Check the dash type.
1228
+ dash_type = line[:dash_type]
1229
+
1230
+ if dash_type
1231
+ line[:dash_type] = value_or_raise(dash_types, dash_type, 'dash type')
1232
+ end
1233
+
1234
+ line[:_defined] = 1
1235
+
1236
+ line
1172
1237
  end
1173
1238
 
1239
+ private
1240
+
1174
1241
  #
1175
- # Switch name and name_formula parameters if required.
1242
+ # retun primary/secondary series by :primary_axes flag
1176
1243
  #
1177
- def process_names(name = nil, name_formula = nil) # :nodoc:
1178
- # Name looks like a formula, use it to set name_formula.
1179
- if name && name =~ /^=[^!]+!\$/
1180
- name_formula = name
1181
- name = ''
1244
+ def axes_series(params)
1245
+ if params[:primary_axes] != 0
1246
+ primary_axes_series
1247
+ else
1248
+ secondary_axes_series
1182
1249
  end
1250
+ end
1183
1251
 
1184
- [name, name_formula]
1252
+ #
1253
+ # Convert and aref of row col values to a range formula.
1254
+ #
1255
+ def aref_to_formula(data) # :nodoc:
1256
+ # If it isn't an array ref it is probably a formula already.
1257
+ return data unless data.kind_of?(Array)
1258
+ xl_range_formula(*data)
1185
1259
  end
1186
1260
 
1187
1261
  #
@@ -1204,41 +1278,6 @@ def get_data_type(data) # :nodoc:
1204
1278
  'num'
1205
1279
  end
1206
1280
 
1207
- #
1208
- # Assign an id to a each unique series formula or title/axis formula. Repeated
1209
- # formulas such as for categories get the same id. If the series or title
1210
- # has user specified data associated with it then that is also stored. This
1211
- # data is used to populate cached Excel data when creating a chart.
1212
- # If there is no user defined data then it will be populated by the parent
1213
- # workbook in Workbook::_add_chart_data
1214
- #
1215
- def get_data_id(formula, data) # :nodoc:
1216
- # Ignore series without a range formula.
1217
- return unless formula
1218
-
1219
- # Strip the leading '=' from the formula.
1220
- formula = formula.sub(/^=/, '')
1221
-
1222
- # Store the data id in a hash keyed by the formula and store the data
1223
- # in a separate array with the same id.
1224
- if !@formula_ids.has_key?(formula)
1225
- # Haven't seen this formula before.
1226
- id = @formula_data.size
1227
-
1228
- @formula_data << data
1229
- @formula_ids[formula] = id
1230
- else
1231
- # Formula already seen. Return existing id.
1232
- id = @formula_ids[formula]
1233
-
1234
- # Store user defined data if it isn't already there.
1235
- @formula_data[id] = data unless @formula_data[id]
1236
- end
1237
-
1238
- id
1239
- end
1240
-
1241
-
1242
1281
  #
1243
1282
  # Convert the user specified colour index or string to a rgb colour.
1244
1283
  #
@@ -1329,42 +1368,10 @@ def get_swe_line_weight(val)
1329
1368
  weights[value] || default
1330
1369
  end
1331
1370
 
1332
- #
1333
- # Convert user defined line properties to the structure required internally.
1334
- #
1335
- def get_line_properties(line) # :nodoc:
1336
- return { :_defined => 0 } unless line
1337
-
1338
- dash_types = {
1339
- :solid => 'solid',
1340
- :round_dot => 'sysDot',
1341
- :square_dot => 'sysDash',
1342
- :dash => 'dash',
1343
- :dash_dot => 'dashDot',
1344
- :long_dash => 'lgDash',
1345
- :long_dash_dot => 'lgDashDot',
1346
- :long_dash_dot_dot => 'lgDashDotDot',
1347
- :dot => 'dot',
1348
- :system_dash_dot => 'sysDashDot',
1349
- :system_dash_dot_dot => 'sysDashDotDot'
1350
- }
1351
-
1352
- # Check the dash type.
1353
- dash_type = line[:dash_type]
1354
-
1355
- if dash_type
1356
- line[:dash_type] = value_or_raise(dash_types, dash_type, 'dash type')
1357
- end
1358
-
1359
- line[:_defined] = 1
1360
-
1361
- line
1362
- end
1363
-
1364
1371
  #
1365
1372
  # Convert user defined fill properties to the structure required internally.
1366
1373
  #
1367
- def get_fill_properties(fill) # :nodoc:
1374
+ def fill_properties(fill) # :nodoc:
1368
1375
  return { :_defined => 0 } unless fill
1369
1376
 
1370
1377
  fill[:_defined] = 1
@@ -1375,7 +1382,7 @@ def get_fill_properties(fill) # :nodoc:
1375
1382
  #
1376
1383
  # Convert user defined marker properties to the structure required internally.
1377
1384
  #
1378
- def get_marker_properties(marker) # :nodoc:
1385
+ def marker_properties(marker) # :nodoc:
1379
1386
  return unless marker
1380
1387
 
1381
1388
  types = {
@@ -1404,13 +1411,13 @@ def get_marker_properties(marker) # :nodoc:
1404
1411
  end
1405
1412
 
1406
1413
  # Set the line properties for the marker..
1407
- line = get_line_properties(marker[:line])
1414
+ line = line_properties(marker[:line])
1408
1415
 
1409
1416
  # Allow 'border' as a synonym for 'line'.
1410
- line = get_line_properties(marker[:border]) if marker[:border]
1417
+ line = line_properties(marker[:border]) if marker[:border]
1411
1418
 
1412
1419
  # Set the fill properties for the marker.
1413
- fill = get_fill_properties(marker[:fill])
1420
+ fill = fill_properties(marker[:fill])
1414
1421
 
1415
1422
  marker[:_line] = line
1416
1423
  marker[:_fill] = fill
@@ -1421,7 +1428,7 @@ def get_marker_properties(marker) # :nodoc:
1421
1428
  #
1422
1429
  # Convert user defined trendline properties to the structure required internally.
1423
1430
  #
1424
- def get_trendline_properties(trendline) # :nodoc:
1431
+ def trendline_properties(trendline) # :nodoc:
1425
1432
  return unless trendline
1426
1433
 
1427
1434
  types = {
@@ -1439,13 +1446,13 @@ def get_trendline_properties(trendline) # :nodoc:
1439
1446
  trendline[:type] = value_or_raise(types, trend_type, 'trendline type')
1440
1447
 
1441
1448
  # Set the line properties for the trendline..
1442
- line = get_line_properties(trendline[:line])
1449
+ line = line_properties(trendline[:line])
1443
1450
 
1444
1451
  # Allow 'border' as a synonym for 'line'.
1445
- line = get_line_properties(trendline[:border]) if trendline[:border]
1452
+ line = line_properties(trendline[:border]) if trendline[:border]
1446
1453
 
1447
1454
  # Set the fill properties for the trendline.
1448
- fill = get_fill_properties(trendline[:fill])
1455
+ fill = fill_properties(trendline[:fill])
1449
1456
 
1450
1457
  trendline[:_line] = line
1451
1458
  trendline[:_fill] = fill
@@ -1454,22 +1461,67 @@ def get_trendline_properties(trendline) # :nodoc:
1454
1461
  end
1455
1462
 
1456
1463
  #
1457
- # Convert user defined gridline properties to the structure required internally.
1464
+ # Convert user defined error bars properties to structure required
1465
+ # internally.
1458
1466
  #
1459
- def get_gridline_properties(args)
1460
- # Set the visible property for the gridline.
1461
- gridline = { :_visible => args[:visible] }
1467
+ def error_bars_properties(params = {})
1468
+ return if !ptrue?(params) || params.empty?
1469
+
1470
+ # Default values.
1471
+ error_bars = {
1472
+ :_type => 'fixedVal',
1473
+ :_value => 1,
1474
+ :_endcap => 1,
1475
+ :_direction => 'both'
1476
+ }
1477
+
1478
+ types = {
1479
+ :fixed => 'fixedVal',
1480
+ :percentage => 'percentage',
1481
+ :standard_deviation => 'stdDev',
1482
+ :standard_error => 'stdErr'
1483
+ }
1484
+
1485
+ # Check the error bars type.
1486
+ error_type = params[:type].to_sym
1487
+
1488
+ if types.key?(error_type)
1489
+ error_bars[:_type] = types[error_type]
1490
+ else
1491
+ raise "Unknown error bars type '#{error_type}'\n"
1492
+ end
1493
+
1494
+ # Set the value for error types that require it.
1495
+ if params.key?(:value)
1496
+ error_bars[:_value] = params[:value]
1497
+ end
1462
1498
 
1463
- # Set the line properties for the gridline.
1464
- gridline[:_line] = get_line_properties(args[:line])
1499
+ # Set the end-cap style.
1500
+ if params.key?(:end_style)
1501
+ error_bars[:_endcap] = params[:end_style]
1502
+ end
1465
1503
 
1466
- gridline
1504
+ # Set the error bar direction.
1505
+ if params.key?(:direction)
1506
+ if params[:direction] == 'minus'
1507
+ error_bars[:_direction] = 'minus'
1508
+ elsif params[:direction] == 'plus'
1509
+ error_bars[:_direction] = 'plus'
1510
+ else
1511
+ # Default to 'both'
1512
+ end
1513
+ end
1514
+
1515
+ # Set the line properties for the error bars.
1516
+ error_bars[:_line] = line_properties(params[:line])
1517
+
1518
+ error_bars
1467
1519
  end
1468
1520
 
1469
1521
  #
1470
1522
  # Convert user defined labels properties to the structure required internally.
1471
1523
  #
1472
- def get_labels_properties(labels) # :nodoc:
1524
+ def labels_properties(labels) # :nodoc:
1473
1525
  return nil unless labels
1474
1526
 
1475
1527
  position = labels[:position]
@@ -1499,7 +1551,7 @@ def get_labels_properties(labels) # :nodoc:
1499
1551
  #
1500
1552
  # Convert user defined area properties to the structure required internally.
1501
1553
  #
1502
- def get_area_properties(arg) # :nodoc:
1554
+ def area_properties(arg) # :nodoc:
1503
1555
  area = {}
1504
1556
 
1505
1557
  # Map deprecated Spreadsheet::WriteExcel fill colour.
@@ -1527,13 +1579,13 @@ def get_area_properties(arg) # :nodoc:
1527
1579
  # Handle Excel::Writer::XLSX style properties.
1528
1580
 
1529
1581
  # Set the line properties for the chartarea.
1530
- line = get_line_properties(arg[:line])
1582
+ line = line_properties(arg[:line])
1531
1583
 
1532
1584
  # Allow 'border' as a synonym for 'line'.
1533
- line = get_line_properties(arg[:border]) if (arg[:border])
1585
+ line = line_properties(arg[:border]) if (arg[:border])
1534
1586
 
1535
1587
  # Set the fill properties for the chartarea.
1536
- fill = get_fill_properties(arg[:fill])
1588
+ fill = fill_properties(arg[:fill])
1537
1589
 
1538
1590
  area[:_line] = line
1539
1591
  area[:_fill] = fill
@@ -1541,6 +1593,35 @@ def get_area_properties(arg) # :nodoc:
1541
1593
  return area
1542
1594
  end
1543
1595
 
1596
+ #
1597
+ # Convert user defined points properties to structure required internally.
1598
+ #
1599
+ def points_properties(user_points = nil)
1600
+ return unless user_points
1601
+
1602
+ points = []
1603
+ user_points.each do |user_point|
1604
+ if user_point
1605
+ # Set the lline properties for the point.
1606
+ line = line_properties(user_point[:line])
1607
+
1608
+ # Allow 'border' as a synonym for 'line'.
1609
+ if user_point[:border]
1610
+ line = line_properties(user_point[:border])
1611
+ end
1612
+
1613
+ # Set the fill properties for the chartarea.
1614
+ fill = fill_properties(user_point[:fill])
1615
+
1616
+ point = {}
1617
+ point[:_line] = line
1618
+ point[:_fill] = fill
1619
+ end
1620
+ points << point
1621
+ end
1622
+ points
1623
+ end
1624
+
1544
1625
  def value_or_raise(hash, key, msg)
1545
1626
  raise "Unknown #{msg} '#{key}'" unless hash[key.to_sym]
1546
1627
  hash[key.to_sym]
@@ -1613,24 +1694,24 @@ def get_font_latin_attributes(font)
1613
1694
  #
1614
1695
  def set_default_properties # :nodoc:
1615
1696
  # Set the default axis properties.
1616
- @x_axis[:_defaults] = {
1697
+ @x_axis.defaults = {
1617
1698
  :num_format => 'General',
1618
1699
  :major_gridlines => { :visible => 0 }
1619
1700
  }
1620
1701
 
1621
- @y_axis[:_defaults] = {
1702
+ @y_axis.defaults = {
1622
1703
  :num_format => 'General',
1623
1704
  :major_gridlines => { :visible => 1 }
1624
1705
  }
1625
1706
 
1626
- @x2_axis[:_defaults] = {
1707
+ @x2_axis.defaults = {
1627
1708
  :num_format => 'General',
1628
1709
  :label_position => 'none',
1629
1710
  :crossing => 'max',
1630
1711
  :visible => 0
1631
1712
  }
1632
1713
 
1633
- @y2_axis[:_defaults] = {
1714
+ @y2_axis.defaults = {
1634
1715
  :num_format => 'General',
1635
1716
  :major_gridlines => { :visible => 0 },
1636
1717
  :position => 'right',
@@ -1713,25 +1794,16 @@ def chart_space_attributes # :nodoc:
1713
1794
  # Write the <c:lang> element.
1714
1795
  #
1715
1796
  def write_lang # :nodoc:
1716
- val = 'en-US'
1717
-
1718
- attributes = ['val', val]
1719
-
1720
- @writer.empty_tag('c:lang', attributes)
1797
+ @writer.empty_tag('c:lang', ['val', 'en-US'])
1721
1798
  end
1722
1799
 
1723
1800
  #
1724
1801
  # Write the <c:style> element.
1725
1802
  #
1726
1803
  def write_style # :nodoc:
1727
- style_id = @style_id
1728
-
1729
- # Don't write an element for the default style, 2.
1730
- return if style_id == 2
1731
-
1732
- attributes = ['val', style_id]
1804
+ return if @style_id == 2
1733
1805
 
1734
- @writer.empty_tag('c:style', attributes)
1806
+ @writer.empty_tag('c:style', ['val', @style_id])
1735
1807
  end
1736
1808
 
1737
1809
  #
@@ -1762,14 +1834,9 @@ def write_chart # :nodoc:
1762
1834
  # Write the <c:dispBlanksAs> element.
1763
1835
  #
1764
1836
  def write_disp_blanks_as
1765
- val = @show_blanks
1837
+ return if @show_blanks == 'gap'
1766
1838
 
1767
- # Ignore the default value.
1768
- return if val == 'gap'
1769
-
1770
- attributes = ['val', val]
1771
-
1772
- @writer.empty_tag('c:dispBlanksAs', attributes)
1839
+ @writer.empty_tag('c:dispBlanksAs', ['val', @show_blanks])
1773
1840
  end
1774
1841
 
1775
1842
  #
@@ -1839,8 +1906,7 @@ def write_chart_type # :nodoc:
1839
1906
  # Write the <c:grouping> element.
1840
1907
  #
1841
1908
  def write_grouping(val) # :nodoc:
1842
- attributes = ['val', val]
1843
- @writer.empty_tag('c:grouping', attributes)
1909
+ @writer.empty_tag('c:grouping', ['val', val])
1844
1910
  end
1845
1911
 
1846
1912
  #
@@ -1894,10 +1960,14 @@ def write_ser(series) # :nodoc:
1894
1960
  write_marker(series[:_marker])
1895
1961
  # Write the c:invertIfNegative element.
1896
1962
  write_c_invert_if_negative(series[:_invert_if_neg])
1963
+ # Write the c:dPt element.
1964
+ write_d_pt(series[:_points])
1897
1965
  # Write the c:dLbls element.
1898
1966
  write_d_lbls(series[:_labels])
1899
1967
  # Write the c:trendline element.
1900
1968
  write_trendline(series[:_trendline])
1969
+ # Write the c:errBars element.
1970
+ write_error_bars(series[:_error_bars])
1901
1971
  # Write the c:cat element.
1902
1972
  write_cat(series)
1903
1973
  # Write the c:val element.
@@ -1909,18 +1979,14 @@ def write_ser(series) # :nodoc:
1909
1979
  # Write the <c:idx> element.
1910
1980
  #
1911
1981
  def write_idx(val) # :nodoc:
1912
- attributes = ['val', val]
1913
-
1914
- @writer.empty_tag('c:idx', attributes)
1982
+ @writer.empty_tag('c:idx', ['val', val])
1915
1983
  end
1916
1984
 
1917
1985
  #
1918
1986
  # Write the <c:order> element.
1919
1987
  #
1920
1988
  def write_order(val) # :nodoc:
1921
- attributes = ['val', val]
1922
-
1923
- @writer.empty_tag('c:order', attributes)
1989
+ @writer.empty_tag('c:order', ['val', val])
1924
1990
  end
1925
1991
 
1926
1992
  #
@@ -2043,9 +2109,7 @@ def write_axis_ids(params)
2043
2109
  # Write the <c:axId> element.
2044
2110
  #
2045
2111
  def write_axis_id(val) # :nodoc:
2046
- attributes = ['val', val]
2047
-
2048
- @writer.empty_tag('c:axId', attributes)
2112
+ @writer.empty_tag('c:axId', ['val', val])
2049
2113
  end
2050
2114
 
2051
2115
  #
@@ -2064,48 +2128,48 @@ def write_cat_axis(params) # :nodoc:
2064
2128
  horiz = @horiz_cat_axis
2065
2129
 
2066
2130
  # Overwrite the default axis position with a user supplied value.
2067
- position = x_axis[:_position] || position
2131
+ position = x_axis.position || position
2068
2132
 
2069
2133
  @writer.tag_elements('c:catAx') do
2070
2134
  write_axis_id(axis_ids[0])
2071
2135
  # Write the c:scaling element.
2072
- write_scaling(x_axis[:_reverse])
2136
+ write_scaling(x_axis.reverse)
2073
2137
 
2074
- write_delete(1) unless ptrue?(x_axis[:_visible])
2138
+ write_delete(1) unless ptrue?(x_axis.visible)
2075
2139
 
2076
2140
  # Write the c:axPos element.
2077
- write_axis_pos(position, y_axis[:_reverse])
2141
+ write_axis_pos(position, y_axis.reverse)
2078
2142
 
2079
2143
  # Write the c:majorGridlines element.
2080
- write_major_gridlines(x_axis[:_major_gridlines])
2144
+ write_major_gridlines(x_axis.major_gridlines)
2081
2145
 
2082
2146
  # Write the c:minorGridlines element.
2083
- write_minor_gridlines(x_axis[:_minor_gridlines])
2147
+ write_minor_gridlines(x_axis.minor_gridlines)
2084
2148
 
2085
2149
  # Write the axis title elements.
2086
- if title = x_axis[:_formula]
2087
- write_title_formula(title, @x_axis[:_data_id], horiz, @x_axis[:_name_font])
2088
- elsif title = x_axis[:_name]
2089
- write_title_rich(title, horiz, x_axis[:_name_font])
2150
+ if title = x_axis.formula
2151
+ write_title_formula(title, @x_axis.data_id, horiz, @x_axis.name_font)
2152
+ elsif title = x_axis.name
2153
+ write_title_rich(title, horiz, x_axis.name_font)
2090
2154
  end
2091
2155
 
2092
2156
  # Write the c:numFmt element.
2093
2157
  write_cat_number_format(x_axis)
2094
2158
 
2095
2159
  # Write the c:majorTickMark element.
2096
- write_major_tick_mark(x_axis[:_major_tick_mark])
2160
+ write_major_tick_mark(x_axis.major_tick_mark)
2097
2161
 
2098
2162
  # Write the c:tickLblPos element.
2099
- write_tick_label_pos(x_axis[:_label_position])
2163
+ write_tick_label_pos(x_axis.label_position)
2100
2164
 
2101
2165
  # Write the axis font elements.
2102
- write_axis_font(x_axis[:_num_font])
2166
+ write_axis_font(x_axis.num_font)
2103
2167
 
2104
2168
  # Write the c:crossAx element.
2105
2169
  write_cross_axis(axis_ids[1])
2106
2170
 
2107
- if @show_crosses || ptrue?(x_axis[:_visible])
2108
- write_crossing(y_axis[:_crossing])
2171
+ if @show_crosses || ptrue?(x_axis.visible)
2172
+ write_crossing(y_axis.crossing)
2109
2173
  end
2110
2174
  # Write the c:auto element.
2111
2175
  write_auto(1)
@@ -2131,7 +2195,7 @@ def write_val_axis(params) # :nodoc:
2131
2195
  return unless axis_ids && !axis_ids.empty?
2132
2196
 
2133
2197
  # OVerwrite the default axis position with a user supplied value.
2134
- position = y_axis[:_position] || position
2198
+ position = y_axis.position || position
2135
2199
 
2136
2200
  @writer.tag_elements('c:valAx') do
2137
2201
  write_axis_id(axis_ids[1])
@@ -2139,49 +2203,49 @@ def write_val_axis(params) # :nodoc:
2139
2203
  # Write the c:scaling element.
2140
2204
  write_scaling_with_param(y_axis)
2141
2205
 
2142
- write_delete(1) unless ptrue?(y_axis[:_visible])
2206
+ write_delete(1) unless ptrue?(y_axis.visible)
2143
2207
 
2144
2208
  # Write the c:axPos element.
2145
- write_axis_pos(position, x_axis[:_reverse])
2209
+ write_axis_pos(position, x_axis.reverse)
2146
2210
 
2147
2211
  # Write the c:majorGridlines element.
2148
- write_major_gridlines(y_axis[:_major_gridlines])
2212
+ write_major_gridlines(y_axis.major_gridlines)
2149
2213
 
2150
2214
  # Write the c:minorGridlines element.
2151
- write_minor_gridlines(y_axis[:_minor_gridlines])
2215
+ write_minor_gridlines(y_axis.minor_gridlines)
2152
2216
 
2153
2217
  # Write the axis title elements.
2154
- if title = y_axis[:_formula]
2155
- write_title_formula(title, y_axis[:_data_id], horiz, y_axis[:_name_font])
2156
- elsif title = y_axis[:_name]
2157
- write_title_rich(title, horiz, y_axis[:_name_font])
2218
+ if title = y_axis.formula
2219
+ write_title_formula(title, y_axis.data_id, horiz, y_axis.name_font)
2220
+ elsif title = y_axis.name
2221
+ write_title_rich(title, horiz, y_axis.name_font)
2158
2222
  end
2159
2223
 
2160
2224
  # Write the c:numberFormat element.
2161
2225
  write_number_format(y_axis)
2162
2226
 
2163
2227
  # Write the c:majorTickMark element.
2164
- write_major_tick_mark(y_axis[:_major_tick_mark])
2228
+ write_major_tick_mark(y_axis.major_tick_mark)
2165
2229
 
2166
2230
  # Write the tickLblPos element.
2167
- write_tick_label_pos(y_axis[:_label_position])
2231
+ write_tick_label_pos(y_axis.label_position)
2168
2232
 
2169
2233
  # Write the axis font elements.
2170
- write_axis_font(y_axis[:_num_font])
2234
+ write_axis_font(y_axis.num_font)
2171
2235
 
2172
2236
  # Write the c:crossAx element.
2173
2237
  write_cross_axis(axis_ids[0])
2174
2238
 
2175
- write_crossing(x_axis[:_crossing])
2239
+ write_crossing(x_axis.crossing)
2176
2240
 
2177
2241
  # Write the c:crossBetween element.
2178
2242
  write_cross_between
2179
2243
 
2180
2244
  # Write the c:majorUnit element.
2181
- write_c_major_unit(y_axis[:_major_unit])
2245
+ write_c_major_unit(y_axis.major_unit)
2182
2246
 
2183
2247
  # Write the c:minorUnit element.
2184
- write_c_minor_unit(y_axis[:_minor_unit])
2248
+ write_c_minor_unit(y_axis.minor_unit)
2185
2249
  end
2186
2250
  end
2187
2251
 
@@ -2201,7 +2265,7 @@ def write_cat_val_axis(params) # :nodoc:
2201
2265
  return unless axis_ids && !axis_ids.empty?
2202
2266
 
2203
2267
  # Overwrite the default axis position with a user supplied value.
2204
- position = x_axis[:_position] || position
2268
+ position = x_axis.position || position
2205
2269
 
2206
2270
  @writer.tag_elements('c:valAx') do
2207
2271
  write_axis_id(axis_ids[0])
@@ -2209,89 +2273,49 @@ def write_cat_val_axis(params) # :nodoc:
2209
2273
  # Write the c:scaling element.
2210
2274
  write_scaling_with_param(x_axis)
2211
2275
 
2212
- write_delete(1) unless ptrue?(x_axis[:_visible])
2276
+ write_delete(1) unless ptrue?(x_axis.visible)
2213
2277
 
2214
2278
  # Write the c:axPos element.
2215
- write_axis_pos(position, y_axis[:_reverse])
2279
+ write_axis_pos(position, y_axis.reverse)
2216
2280
 
2217
2281
  # Write the c:majorGridlines element.
2218
- write_major_gridlines(x_axis[:_major_gridlines])
2282
+ write_major_gridlines(x_axis.major_gridlines)
2219
2283
 
2220
2284
  # Write the c:minorGridlines element.
2221
- write_minor_gridlines(x_axis[:_minor_gridlines])
2285
+ write_minor_gridlines(x_axis.minor_gridlines)
2222
2286
 
2223
2287
  # Write the axis title elements.
2224
- if title = x_axis[:_formula]
2225
- write_title_formula(title, y_axis[:_data_id], horiz, x_axis[:_name_font])
2226
- elsif title = x_axis[:_name]
2227
- write_title_rich(title, horiz, x_axis[:_name_font])
2288
+ if title = x_axis.formula
2289
+ write_title_formula(title, y_axis.data_id, horiz, x_axis.name_font)
2290
+ elsif title = x_axis.name
2291
+ write_title_rich(title, horiz, x_axis.name_font)
2228
2292
  end
2229
2293
 
2230
2294
  # Write the c:numberFormat element.
2231
2295
  write_number_format(x_axis)
2232
2296
 
2233
2297
  # Write the c:majorTickMark element.
2234
- write_major_tick_mark(x_axis[:_major_tick_mark])
2298
+ write_major_tick_mark(x_axis.major_tick_mark)
2235
2299
 
2236
2300
  # Write the c:tickLblPos element.
2237
- write_tick_label_pos(x_axis[:_label_position])
2301
+ write_tick_label_pos(x_axis.label_position)
2238
2302
 
2239
2303
  # Write the axis font elements.
2240
- write_axis_font(x_axis[:_num_font])
2304
+ write_axis_font(x_axis.num_font)
2241
2305
 
2242
2306
  # Write the c:crossAx element.
2243
2307
  write_cross_axis(axis_ids[1])
2244
2308
 
2245
- write_crossing(y_axis[:_crossing])
2309
+ write_crossing(y_axis.crossing)
2246
2310
 
2247
2311
  # Write the c:crossBetween element.
2248
2312
  write_cross_between
2249
2313
 
2250
2314
  # Write the c:majorUnit element.
2251
- write_c_major_unit(x_axis[:_major_unit])
2315
+ write_c_major_unit(x_axis.major_unit)
2252
2316
 
2253
2317
  # Write the c:minorunit element.
2254
- write_c_minor_unit(x_axis[:_minor_unit])
2255
- end
2256
- end
2257
-
2258
- def write_val_axis_common(position, hide_major_gridlines, params) # :nodoc:
2259
- position ||= @val_axis_position
2260
- horiz = @horiz_val_axis
2261
-
2262
- # Overwrite the default axis position with a user supplied value.
2263
- position = params[:axis_position] || position
2264
-
2265
- @writer.tag_elements('c:valAx') do
2266
- write_axis_id(params[:axis_id])
2267
- # Write the c:scaling element.
2268
- write_scaling_with_param(params[:scaling_axis])
2269
-
2270
- # Write the c:axPos element.
2271
- write_axis_pos(position, params[:axis_position_element])
2272
- # Write the c:majorGridlines element.
2273
- write_major_gridlines unless hide_major_gridlines
2274
- # Write the axis title elements.
2275
- if title = params[:title_axis][:_formula]
2276
- write_title_formula(title, @y_axis[:_data_id], horiz)
2277
- elsif title = params[:title_axis][:_name]
2278
- write_title_rich(title, horiz)
2279
- end
2280
- # Write the c:numberFormat element.
2281
- write_number_format
2282
- # Write the c:tickLblPos element.
2283
- write_tick_label_pos(params[:tick_label_pos])
2284
- # Write the c:crossAx element.
2285
- write_cross_axis(params[:cross_axis])
2286
-
2287
- write_crossing(params[:category_crossing])
2288
-
2289
- # Write the c:crossBetween element.
2290
- write_cross_between
2291
- # Write the c:majorUnit element.
2292
- write_c_major_unit(params[:major_unit])
2293
- # Write the c:minorUnit element.
2294
- write_c_minor_unit(params[:minor_unit])
2318
+ write_c_minor_unit(x_axis.minor_unit)
2295
2319
  end
2296
2320
  end
2297
2321
 
@@ -2308,44 +2332,44 @@ def write_date_axis(params) # :nodoc:
2308
2332
  position = @cat_axis_position
2309
2333
 
2310
2334
  # Overwrite the default axis position with a user supplied value.
2311
- position = x_axis[:_position] || position
2335
+ position = x_axis.position || position
2312
2336
 
2313
2337
  @writer.tag_elements('c:dateAx') do
2314
2338
  write_axis_id(axis_ids[0])
2315
2339
  # Write the c:scaling element.
2316
2340
  write_scaling_with_param(x_axis)
2317
2341
 
2318
- write_delete(1) unless ptrue?(x_axis[:_visible])
2342
+ write_delete(1) unless ptrue?(x_axis.visible)
2319
2343
 
2320
2344
  # Write the c:axPos element.
2321
- write_axis_pos(position, y_axis[:reverse])
2345
+ write_axis_pos(position, y_axis.reverse)
2322
2346
 
2323
2347
  # Write the c:majorGridlines element.
2324
- write_major_gridlines(x_axis[:_major_gridlines])
2348
+ write_major_gridlines(x_axis.major_gridlines)
2325
2349
 
2326
2350
  # Write the c:minorGridlines element.
2327
- write_minor_gridlines(x_axis[:_minor_gridlines])
2351
+ write_minor_gridlines(x_axis.minor_gridlines)
2328
2352
 
2329
2353
  # Write the axis title elements.
2330
- if title = x_axis[:_formula]
2331
- write_title_formula(title, x_axis[:_data_id], nil, x_axis[:_name_font])
2332
- elsif title = x_axis[:_name]
2333
- write_title_rich(title, nil, x_axis[:_name_font])
2354
+ if title = x_axis.formula
2355
+ write_title_formula(title, x_axis.data_id, nil, x_axis.name_font)
2356
+ elsif title = x_axis.name
2357
+ write_title_rich(title, nil, x_axis.name_font)
2334
2358
  end
2335
2359
  # Write the c:numFmt element.
2336
2360
  write_number_format(x_axis)
2337
2361
  # Write the c:majorTickMark element.
2338
- write_major_tick_mark(x_axis[:_major_tick_mark])
2362
+ write_major_tick_mark(x_axis.major_tick_mark)
2339
2363
 
2340
2364
  # Write the c:tickLblPos element.
2341
- write_tick_label_pos(x_axis[:_label_position])
2365
+ write_tick_label_pos(x_axis.label_position)
2342
2366
  # Write the font elements.
2343
- write_axis_font(x_axis[:_num_font])
2367
+ write_axis_font(x_axis.num_font)
2344
2368
  # Write the c:crossAx element.
2345
2369
  write_cross_axis(axis_ids[1])
2346
2370
 
2347
- if @show_crosses || ptrue?(x_axis[:_visible])
2348
- write_crossing(y_axis[:_crossing])
2371
+ if @show_crosses || ptrue?(x_axis.visible)
2372
+ write_crossing(y_axis.crossing)
2349
2373
  end
2350
2374
 
2351
2375
  # Write the c:auto element.
@@ -2353,16 +2377,16 @@ def write_date_axis(params) # :nodoc:
2353
2377
  # Write the c:labelOffset element.
2354
2378
  write_label_offset(100)
2355
2379
  # Write the c:majorUnit element.
2356
- write_c_major_unit(x_axis[:_major_unit])
2380
+ write_c_major_unit(x_axis.major_unit)
2357
2381
  # Write the c:majorTimeUnit element.
2358
- if !x_axis[:_major_unit].nil?
2359
- write_c_major_time_unit(x_axis[:_major_unit_type])
2382
+ if !x_axis.major_unit.nil?
2383
+ write_c_major_time_unit(x_axis.major_unit_type)
2360
2384
  end
2361
2385
  # Write the c:minorUnit element.
2362
- write_c_minor_unit(x_axis[:_minor_unit])
2386
+ write_c_minor_unit(x_axis.minor_unit)
2363
2387
  # Write the c:minorTimeUnit element.
2364
- if !x_axis[:_minor_unit].nil?
2365
- write_c_minor_time_unit(x_axis[:_minor_unit_type])
2388
+ if !x_axis.minor_unit.nil?
2389
+ write_c_minor_time_unit(x_axis.minor_unit_type)
2366
2390
  end
2367
2391
  end
2368
2392
  end
@@ -2380,10 +2404,10 @@ def write_crossing(crossing)
2380
2404
 
2381
2405
  def write_scaling_with_param(param)
2382
2406
  write_scaling(
2383
- param[:_reverse],
2384
- param[:_min],
2385
- param[:_max],
2386
- param[:_log_base]
2407
+ param.reverse,
2408
+ param.min,
2409
+ param.max,
2410
+ param.log_base
2387
2411
  )
2388
2412
  end
2389
2413
  #
@@ -2408,9 +2432,7 @@ def write_scaling(reverse, min = nil, max = nil, log_base = nil) # :nodoc:
2408
2432
  def write_c_log_base(val) # :nodoc:
2409
2433
  return unless ptrue?(val)
2410
2434
 
2411
- attributes = ['val', val]
2412
-
2413
- @writer.empty_tag('c:logBase', attributes)
2435
+ @writer.empty_tag('c:logBase', ['val', val])
2414
2436
  end
2415
2437
 
2416
2438
  #
@@ -2419,9 +2441,7 @@ def write_c_log_base(val) # :nodoc:
2419
2441
  def write_orientation(reverse = nil) # :nodoc:
2420
2442
  val = ptrue?(reverse) ? 'maxMin' : 'minMax'
2421
2443
 
2422
- attributes = ['val', val]
2423
-
2424
- @writer.empty_tag('c:orientation', attributes)
2444
+ @writer.empty_tag('c:orientation', ['val', val])
2425
2445
  end
2426
2446
 
2427
2447
  #
@@ -2430,9 +2450,7 @@ def write_orientation(reverse = nil) # :nodoc:
2430
2450
  def write_c_max(max = nil) # :nodoc:
2431
2451
  return if max.nil?
2432
2452
 
2433
- attributes = ['val', max]
2434
-
2435
- @writer.empty_tag('c:max', attributes)
2453
+ @writer.empty_tag('c:max', ['val', max])
2436
2454
  end
2437
2455
 
2438
2456
  #
@@ -2441,9 +2459,7 @@ def write_c_max(max = nil) # :nodoc:
2441
2459
  def write_c_min(min = nil) # :nodoc:
2442
2460
  return if min.nil?
2443
2461
 
2444
- attributes = ['val', min]
2445
-
2446
- @writer.empty_tag('c:min', attributes)
2462
+ @writer.empty_tag('c:min', ['val', min])
2447
2463
  end
2448
2464
 
2449
2465
  #
@@ -2455,9 +2471,7 @@ def write_axis_pos(val, reverse = false) # :nodoc:
2455
2471
  val = 't' if val == 'b'
2456
2472
  end
2457
2473
 
2458
- attributes = ['val', val]
2459
-
2460
- @writer.empty_tag('c:axPos', attributes)
2474
+ @writer.empty_tag('c:axPos', ['val', val])
2461
2475
  end
2462
2476
 
2463
2477
  #
@@ -2467,25 +2481,7 @@ def write_axis_pos(val, reverse = false) # :nodoc:
2467
2481
  #
2468
2482
 
2469
2483
  def write_number_format(axis) # :nodoc:
2470
- format_code = axis[:_num_format]
2471
- source_linked = 1
2472
-
2473
- # Check if a user defined number format has been set.
2474
- if axis[:_defaults] && format_code != axis[:_defaults][:num_format]
2475
- source_linked = 0
2476
- end
2477
-
2478
- # User override of sourceLinked.
2479
- if ptrue?(axis[:_num_format_linked])
2480
- source_linked = 1
2481
- end
2482
-
2483
- attributes = [
2484
- 'formatCode', format_code,
2485
- 'sourceLinked', source_linked
2486
- ]
2487
-
2488
- @writer.empty_tag('c:numFmt', attributes)
2484
+ axis.write_number_format(@writer)
2489
2485
  end
2490
2486
 
2491
2487
  #
@@ -2493,32 +2489,7 @@ def write_number_format(axis) # :nodoc:
2493
2489
  # don't always have a number format.
2494
2490
  #
2495
2491
  def write_cat_number_format(axis)
2496
- format_code = axis[:_num_format]
2497
- source_linked = 1
2498
- default_format = true
2499
-
2500
- # Check if a user defined number format has been set.
2501
- if axis[:_defaults] && format_code != axis[:_defaults][:num_format]
2502
- source_linked = 0
2503
- default_format = false
2504
- end
2505
-
2506
- # User override of linkedSource.
2507
- if axis[:_num_format_linked]
2508
- source_linked = 1
2509
- end
2510
-
2511
- # Skip if cat doesn't have a num format (unless it is non-default).
2512
- if !@cat_has_num_fmt && default_format
2513
- return ''
2514
- end
2515
-
2516
- attributes = [
2517
- 'formatCode', format_code,
2518
- 'sourceLinked', source_linked,
2519
- ]
2520
-
2521
- @writer.empty_tag('c:numFmt', attributes)
2492
+ axis.write_cat_number_format(@writer, @cat_has_num_fmt)
2522
2493
  end
2523
2494
 
2524
2495
  #
@@ -2527,9 +2498,7 @@ def write_cat_number_format(axis)
2527
2498
  def write_major_tick_mark(val)
2528
2499
  return unless ptrue?(val)
2529
2500
 
2530
- attributes = ['val', val]
2531
-
2532
- @writer.empty_tag('c:majorTickMark', attributes)
2501
+ @writer.empty_tag('c:majorTickMark', ['val', val])
2533
2502
  end
2534
2503
 
2535
2504
  #
@@ -2539,18 +2508,14 @@ def write_tick_label_pos(val) # :nodoc:
2539
2508
  val ||= 'nextTo'
2540
2509
  val = 'nextTo' if val == 'next_to'
2541
2510
 
2542
- attributes = ['val', val]
2543
-
2544
- @writer.empty_tag('c:tickLblPos', attributes)
2511
+ @writer.empty_tag('c:tickLblPos', ['val', val])
2545
2512
  end
2546
2513
 
2547
2514
  #
2548
2515
  # Write the <c:crossAx> element.
2549
2516
  #
2550
2517
  def write_cross_axis(val = 'autoZero') # :nodoc:
2551
- attributes = ['val', val]
2552
-
2553
- @writer.empty_tag('c:crossAx', attributes)
2518
+ @writer.empty_tag('c:crossAx', ['val', val])
2554
2519
  end
2555
2520
 
2556
2521
  #
@@ -2559,73 +2524,54 @@ def write_cross_axis(val = 'autoZero') # :nodoc:
2559
2524
  def write_crosses(val) # :nodoc:
2560
2525
  val ||= 'autoZero'
2561
2526
 
2562
- attributes = ['val', val]
2563
-
2564
- @writer.empty_tag('c:crosses', attributes)
2527
+ @writer.empty_tag('c:crosses', ['val', val])
2565
2528
  end
2566
2529
 
2567
2530
  #
2568
2531
  # Write the <c:crossesAt> element.
2569
2532
  #
2570
2533
  def write_c_crosses_at(val) # :nodoc:
2571
- attributes = ['val', val]
2572
-
2573
- @writer.empty_tag('c:crossesAt', attributes)
2534
+ @writer.empty_tag('c:crossesAt', ['val', val])
2574
2535
  end
2575
2536
 
2576
2537
  #
2577
2538
  # Write the <c:auto> element.
2578
2539
  #
2579
2540
  def write_auto(val) # :nodoc:
2580
- attributes = ['val', val]
2581
-
2582
- @writer.empty_tag('c:auto', attributes)
2541
+ @writer.empty_tag('c:auto', ['val', val])
2583
2542
  end
2584
2543
 
2585
2544
  #
2586
2545
  # Write the <c:labelAlign> element.
2587
2546
  #
2588
2547
  def write_label_align(val) # :nodoc:
2589
- attributes = ['val', val]
2590
-
2591
- @writer.empty_tag('c:lblAlgn', attributes)
2548
+ @writer.empty_tag('c:lblAlgn', ['val', val])
2592
2549
  end
2593
2550
 
2594
2551
  #
2595
2552
  # Write the <c:labelOffset> element.
2596
2553
  #
2597
2554
  def write_label_offset(val) # :nodoc:
2598
- attributes = ['val', val]
2599
-
2600
- @writer.empty_tag('c:lblOffset', attributes)
2555
+ @writer.empty_tag('c:lblOffset', ['val', val])
2601
2556
  end
2602
2557
 
2603
2558
  #
2604
2559
  # Write the <c:majorGridlines> element.
2605
2560
  #
2606
2561
  def write_major_gridlines(gridlines) # :nodoc:
2607
- write_gridlines_common(gridlines, 'c:majorGridlines')
2562
+ write_gridlines_base('c:majorGridlines', gridlines)
2608
2563
  end
2609
2564
 
2610
2565
  #
2611
2566
  # Write the <c:minorGridlines> element.
2612
2567
  #
2613
2568
  def write_minor_gridlines(gridlines) # :nodoc:
2614
- write_gridlines_common(gridlines, 'c:minorGridlines')
2569
+ write_gridlines_base('c:minorGridlines', gridlines)
2615
2570
  end
2616
2571
 
2617
- def write_gridlines_common(gridlines, tag) # :nodoc:
2618
- return unless gridlines
2619
- return unless ptrue?(gridlines[:_visible])
2620
-
2621
- if gridlines[:_line] && ptrue?(gridlines[:_line][:_defined])
2622
- @writer.tag_elements(tag) do
2623
- # Write the c:spPr element.
2624
- write_sp_pr(gridlines)
2625
- end
2626
- else
2627
- @writer.empty_tag(tag)
2628
- end
2572
+ def write_gridlines_base(tag, gridlines) # :nodoc:
2573
+ return if gridlines.respond_to?(:[]) and !ptrue?(gridlines[:_visible])
2574
+ write_lines_base(tag, gridlines)
2629
2575
  end
2630
2576
 
2631
2577
  #
@@ -2634,9 +2580,7 @@ def write_gridlines_common(gridlines, tag) # :nodoc:
2634
2580
  def write_cross_between # :nodoc:
2635
2581
  val = @cross_between || 'between'
2636
2582
 
2637
- attributes = ['val', val]
2638
-
2639
- @writer.empty_tag('c:crossBetween', attributes)
2583
+ @writer.empty_tag('c:crossBetween', ['val', val])
2640
2584
  end
2641
2585
 
2642
2586
  #
@@ -2645,9 +2589,7 @@ def write_cross_between # :nodoc:
2645
2589
  def write_c_major_unit(val = nil) # :nodoc:
2646
2590
  return unless val
2647
2591
 
2648
- attributes = ['val', val]
2649
-
2650
- @writer.empty_tag('c:majorUnit', attributes)
2592
+ @writer.empty_tag('c:majorUnit', ['val', val])
2651
2593
  end
2652
2594
 
2653
2595
  #
@@ -2656,9 +2598,7 @@ def write_c_major_unit(val = nil) # :nodoc:
2656
2598
  def write_c_minor_unit(val = nil) # :nodoc:
2657
2599
  return unless val
2658
2600
 
2659
- attributes = ['val', val]
2660
-
2661
- @writer.empty_tag('c:minorUnit', attributes)
2601
+ @writer.empty_tag('c:minorUnit', ['val', val])
2662
2602
  end
2663
2603
 
2664
2604
  #
@@ -2666,9 +2606,8 @@ def write_c_minor_unit(val = nil) # :nodoc:
2666
2606
  #
2667
2607
  def write_c_major_time_unit(val) # :nodoc:
2668
2608
  val ||= 'days'
2669
- attributes = ['val', val]
2670
2609
 
2671
- @writer.empty_tag('c:majorTimeUnit', attributes)
2610
+ @writer.empty_tag('c:majorTimeUnit', ['val', val])
2672
2611
  end
2673
2612
 
2674
2613
  #
@@ -2676,9 +2615,8 @@ def write_c_major_time_unit(val) # :nodoc:
2676
2615
  #
2677
2616
  def write_c_minor_time_unit(val) # :nodoc:
2678
2617
  val ||= 'days'
2679
- attributes = ['val', val]
2680
2618
 
2681
- @writer.empty_tag('c:minorTimeUnit', attributes)
2619
+ @writer.empty_tag('c:minorTimeUnit', ['val', val])
2682
2620
  end
2683
2621
 
2684
2622
  #
@@ -2728,9 +2666,7 @@ def write_legend # :nodoc:
2728
2666
  # Write the <c:legendPos> element.
2729
2667
  #
2730
2668
  def write_legend_pos(val) # :nodoc:
2731
- attributes = ['val', val]
2732
-
2733
- @writer.empty_tag('c:legendPos', attributes)
2669
+ @writer.empty_tag('c:legendPos', ['val', val])
2734
2670
  end
2735
2671
 
2736
2672
  #
@@ -2749,11 +2685,7 @@ def write_legend_entry(index) # :nodoc:
2749
2685
  # Write the <c:overlay> element.
2750
2686
  #
2751
2687
  def write_overlay # :nodoc:
2752
- val = 1
2753
-
2754
- attributes = ['val', val]
2755
-
2756
- @writer.empty_tag('c:overlay', attributes)
2688
+ @writer.empty_tag('c:overlay', ['val', 1])
2757
2689
  end
2758
2690
 
2759
2691
  #
@@ -2765,9 +2697,7 @@ def write_plot_vis_only # :nodoc:
2765
2697
  # Ignore this element if we are plotting hidden data.
2766
2698
  return if @show_hidden_data
2767
2699
 
2768
- attributes = ['val', val]
2769
-
2770
- @writer.empty_tag('c:plotVisOnly', attributes)
2700
+ @writer.empty_tag('c:plotVisOnly', ['val', val])
2771
2701
  end
2772
2702
 
2773
2703
  #
@@ -2960,11 +2890,7 @@ def write_a_def_rpr(font = nil) # :nodoc:
2960
2890
  # Write the <a:endParaRPr> element.
2961
2891
  #
2962
2892
  def write_a_end_para_rpr # :nodoc:
2963
- lang = 'en-US'
2964
-
2965
- attributes = ['lang', lang]
2966
-
2967
- @writer.empty_tag('a:endParaRPr', attributes)
2893
+ @writer.empty_tag('a:endParaRPr', ['lang', 'en-US'])
2968
2894
  end
2969
2895
 
2970
2896
  #
@@ -3053,31 +2979,23 @@ def write_marker(marker = nil) # :nodoc:
3053
2979
  # Write the <c:marker> element without a sub-element.
3054
2980
  #
3055
2981
  def write_marker_value # :nodoc:
3056
- style = @default_marker
2982
+ return unless @default_marker
3057
2983
 
3058
- return unless style
3059
-
3060
- attributes = ['val', 1]
3061
-
3062
- @writer.empty_tag('c:marker', attributes)
2984
+ @writer.empty_tag('c:marker', ['val', 1])
3063
2985
  end
3064
2986
 
3065
2987
  #
3066
2988
  # Write the <c:size> element.
3067
2989
  #
3068
2990
  def write_marker_size(val) # :nodoc:
3069
- attributes = ['val', val]
3070
-
3071
- @writer.empty_tag('c:size', attributes)
2991
+ @writer.empty_tag('c:size', ['val', val])
3072
2992
  end
3073
2993
 
3074
2994
  #
3075
2995
  # Write the <c:symbol> element.
3076
2996
  #
3077
2997
  def write_symbol(val) # :nodoc:
3078
- attributes = ['val', val]
3079
-
3080
- @writer.empty_tag('c:symbol', attributes)
2998
+ @writer.empty_tag('c:symbol', ['val', val])
3081
2999
  end
3082
3000
 
3083
3001
  #
@@ -3162,18 +3080,14 @@ def write_a_solid_fill(line) # :nodoc:
3162
3080
  # Write the <a:srgbClr> element.
3163
3081
  #
3164
3082
  def write_a_srgb_clr(val) # :nodoc:
3165
- attributes = ['val', val]
3166
-
3167
- @writer.empty_tag('a:srgbClr', attributes)
3083
+ @writer.empty_tag('a:srgbClr', ['val', val])
3168
3084
  end
3169
3085
 
3170
3086
  #
3171
3087
  # Write the <a:prstDash> element.
3172
3088
  #
3173
3089
  def write_a_prst_dash(val) # :nodoc:
3174
- attributes = ['val', val]
3175
-
3176
- @writer.empty_tag('a:prstDash', attributes)
3090
+ @writer.empty_tag('a:prstDash', ['val', val])
3177
3091
  end
3178
3092
 
3179
3093
  #
@@ -3204,9 +3118,7 @@ def write_trendline(trendline) # :nodoc:
3204
3118
  # Write the <c:trendlineType> element.
3205
3119
  #
3206
3120
  def write_trendline_type(val) # :nodoc:
3207
- attributes = ['val', val]
3208
-
3209
- @writer.empty_tag('c:trendlineType', attributes)
3121
+ @writer.empty_tag('c:trendlineType', ['val', val])
3210
3122
  end
3211
3123
 
3212
3124
  #
@@ -3222,18 +3134,14 @@ def write_name(data) # :nodoc:
3222
3134
  # Write the <c:order> element.
3223
3135
  #
3224
3136
  def write_trendline_order(val = 2) # :nodoc:
3225
- attributes = ['val', val]
3226
-
3227
- @writer.empty_tag('c:order', attributes)
3137
+ @writer.empty_tag('c:order', ['val', val])
3228
3138
  end
3229
3139
 
3230
3140
  #
3231
3141
  # Write the <c:period> element.
3232
3142
  #
3233
3143
  def write_period(val = 2) # :nodoc:
3234
- attributes = ['val', val]
3235
-
3236
- @writer.empty_tag('c:period', attributes)
3144
+ @writer.empty_tag('c:period', ['val', val])
3237
3145
  end
3238
3146
 
3239
3147
  #
@@ -3242,9 +3150,7 @@ def write_period(val = 2) # :nodoc:
3242
3150
  def write_forward(val) # :nodoc:
3243
3151
  return unless val
3244
3152
 
3245
- attributes = ['val', val]
3246
-
3247
- @writer.empty_tag('c:forward', attributes)
3153
+ @writer.empty_tag('c:forward', ['val', val])
3248
3154
  end
3249
3155
 
3250
3156
  #
@@ -3253,27 +3159,41 @@ def write_forward(val) # :nodoc:
3253
3159
  def write_backward(val) # :nodoc:
3254
3160
  return unless val
3255
3161
 
3256
- attributes = ['val', val]
3257
-
3258
- @writer.empty_tag('c:backward', attributes)
3162
+ @writer.empty_tag('c:backward', ['val', val])
3259
3163
  end
3260
3164
 
3261
3165
  #
3262
3166
  # Write the <c:hiLowLines> element.
3263
3167
  #
3264
3168
  def write_hi_low_lines # :nodoc:
3265
- @writer.empty_tag('c:hiLowLines')
3169
+ write_lines_base('c:hiLowLines', @hi_low_lines)
3266
3170
  end
3267
3171
 
3268
3172
  #
3269
- # Write the <c:overlap> element.
3173
+ # Write the <c:dropLines> elent.
3270
3174
  #
3271
- def write_overlap # :nodoc:
3272
- val = 100
3175
+ def write_drop_lines
3176
+ write_lines_base('c:dropLines', @drop_lines)
3177
+ end
3273
3178
 
3274
- attributes = ['val', val]
3179
+ #
3180
+ # used from write_drop_lines and write_hi_low_lines
3181
+ #
3182
+ def write_lines_base(tag, lines)
3183
+ return unless lines
3275
3184
 
3276
- @writer.empty_tag('c:overlap', attributes)
3185
+ if lines[:_line] && ptrue?(lines[:_line][:_defined])
3186
+ @writer.tag_elements(tag) { write_sp_pr(lines) }
3187
+ else
3188
+ @writer.empty_tag(tag)
3189
+ end
3190
+ end
3191
+
3192
+ #
3193
+ # Write the <c:overlap> element.
3194
+ #
3195
+ def write_overlap # :nodoc:
3196
+ @writer.empty_tag('c:overlap', ['val', 100])
3277
3197
  end
3278
3198
 
3279
3199
  #
@@ -3328,9 +3248,7 @@ def write_format_code(data) # :nodoc:
3328
3248
  # Write the <c:ptCount> element.
3329
3249
  #
3330
3250
  def write_pt_count(val) # :nodoc:
3331
- attributes = ['val', val]
3332
-
3333
- @writer.empty_tag('c:ptCount', attributes)
3251
+ @writer.empty_tag('c:ptCount', ['val', val])
3334
3252
  end
3335
3253
 
3336
3254
  #
@@ -3360,6 +3278,32 @@ def write_protection # :nodoc:
3360
3278
  @writer.empty_tag('c:protection')
3361
3279
  end
3362
3280
 
3281
+ #
3282
+ # Write the <c:dPt> elements.
3283
+ #
3284
+ def write_d_pt(points = nil)
3285
+ return unless ptrue?(points)
3286
+
3287
+ index = -1
3288
+ points.each do |point|
3289
+ index += 1
3290
+ next unless ptrue?(point)
3291
+
3292
+ write_d_pt_point(index, point)
3293
+ end
3294
+ end
3295
+
3296
+ #
3297
+ # Write an individual <c:dPt> element.
3298
+ #
3299
+ def write_d_pt_point(index, point)
3300
+ @writer.tag_elements('c:dPt') do
3301
+ # Write the c:idx element.
3302
+ write_idx(index)
3303
+ # Write the c:spPr element.
3304
+ write_sp_pr(point)
3305
+ end
3306
+ end
3363
3307
  #
3364
3308
  # Write the <c:dLbls> element.
3365
3309
  #
@@ -3386,86 +3330,58 @@ def write_d_lbls(labels) # :nodoc:
3386
3330
  # Write the <c:showVal> element.
3387
3331
  #
3388
3332
  def write_show_val # :nodoc:
3389
- val = 1
3390
-
3391
- attributes = ['val', val]
3392
-
3393
- @writer.empty_tag('c:showVal', attributes)
3333
+ @writer.empty_tag('c:showVal', ['val', 1])
3394
3334
  end
3395
3335
 
3396
3336
  #
3397
3337
  # Write the <c:showCatName> element.
3398
3338
  #
3399
3339
  def write_show_cat_name # :nodoc:
3400
- val = 1
3401
-
3402
- attributes = ['val', val]
3403
-
3404
- @writer.empty_tag('c:showCatName', attributes)
3340
+ @writer.empty_tag('c:showCatName', ['val', 1])
3405
3341
  end
3406
3342
 
3407
3343
  #
3408
3344
  # Write the <c:showSerName> element.
3409
3345
  #
3410
3346
  def write_show_ser_name # :nodoc:
3411
- val = 1
3412
-
3413
- attributes = ['val', val]
3414
-
3415
- @writer.empty_tag('c:showSerName', attributes)
3347
+ @writer.empty_tag('c:showSerName', ['val', 1])
3416
3348
  end
3417
3349
 
3418
3350
  #
3419
3351
  # Write the <c:showPercent> element.
3420
3352
  #
3421
3353
  def write_show_percent
3422
- val = 1
3423
-
3424
- attributes = ['val', val]
3425
-
3426
- @writer.empty_tag('c:showPercent', attributes)
3354
+ @writer.empty_tag('c:showPercent', ['val', 1])
3427
3355
  end
3428
3356
 
3429
3357
  #
3430
3358
  # Write the <c:showLeaderLines> element.
3431
3359
  #
3432
3360
  def write_show_leader_lines
3433
- val = 1
3434
-
3435
- attributes = ['val', val]
3436
-
3437
- @writer.empty_tag('c:showLeaderLines', attributes)
3361
+ @writer.empty_tag('c:showLeaderLines', ['val', 1])
3438
3362
  end
3439
3363
 
3440
3364
  #
3441
3365
  # Write the <c:dLblPos> element.
3442
3366
  #
3443
3367
  def write_d_lbl_pos(val)
3444
- attributes = ['val', val]
3445
-
3446
- @writer.empty_tag('c:dLblPos', attributes)
3368
+ @writer.empty_tag('c:dLblPos', ['val', val])
3447
3369
  end
3448
3370
 
3449
3371
  #
3450
3372
  # Write the <c:delete> element.
3451
3373
  #
3452
3374
  def write_delete(val) # :nodoc:
3453
- attributes = ['val', val]
3454
-
3455
- @writer.empty_tag('c:delete', attributes)
3375
+ @writer.empty_tag('c:delete', ['val', val])
3456
3376
  end
3457
3377
 
3458
3378
  #
3459
3379
  # Write the <c:invertIfNegative> element.
3460
3380
  #
3461
3381
  def write_c_invert_if_negative(invert = nil) # :nodoc:
3462
- val = 1
3463
-
3464
- return unless invert && invert != 0
3382
+ return unless ptrue?(invert)
3465
3383
 
3466
- attributes = ['val', val]
3467
-
3468
- @writer.empty_tag('c:invertIfNegative', attributes)
3384
+ @writer.empty_tag('c:invertIfNegative', ['val', 1])
3469
3385
  end
3470
3386
 
3471
3387
  #
@@ -3498,6 +3414,133 @@ def write_d_table
3498
3414
  @table.write_d_table(@writer) if @table
3499
3415
  end
3500
3416
 
3417
+ #
3418
+ # Write the X and Y error bars.
3419
+ #
3420
+ def write_error_bars(error_bars)
3421
+ return unless ptrue?(error_bars)
3422
+
3423
+ if error_bars[:_x_error_bars]
3424
+ write_err_bars('x', error_bars[:_x_error_bars])
3425
+ end
3426
+ if error_bars[:_y_error_bars]
3427
+ write_err_bars('y', error_bars[:_y_error_bars])
3428
+ end
3429
+ end
3430
+
3431
+ #
3432
+ # Write the <c:errBars> element.
3433
+ #
3434
+ def write_err_bars(direction, error_bars)
3435
+ return unless ptrue?(error_bars)
3436
+
3437
+ @writer.tag_elements('c:errBars') do
3438
+ # Write the c:errDir element.
3439
+ write_err_dir(direction)
3440
+
3441
+ # Write the c:errBarType element.
3442
+ write_err_bar_type(error_bars[:_direction])
3443
+
3444
+ # Write the c:errValType element.
3445
+ write_err_val_type(error_bars[:_type])
3446
+
3447
+ unless ptrue?(error_bars[:_endcap])
3448
+ # Write the c:noEndCap element.
3449
+ write_no_end_cap
3450
+ end
3451
+
3452
+ if error_bars[:_type] != 'stdErr'
3453
+ # Write the c:val element.
3454
+ write_error_val(error_bars[:_value])
3455
+ end
3456
+
3457
+ # Write the c:spPr element.
3458
+ write_sp_pr(error_bars)
3459
+ end
3460
+ end
3461
+
3462
+ #
3463
+ # Write the <c:errDir> element.
3464
+ #
3465
+ def write_err_dir(val)
3466
+ @writer.empty_tag('c:errDir', ['val', val])
3467
+ end
3468
+
3469
+ #
3470
+ # Write the <c:errBarType> element.
3471
+ #
3472
+ def write_err_bar_type(val)
3473
+ @writer.empty_tag('c:errBarType', ['val', val])
3474
+ end
3475
+
3476
+ #
3477
+ # Write the <c:errValType> element.
3478
+ #
3479
+ def write_err_val_type(val)
3480
+ @writer.empty_tag('c:errValType', ['val', val])
3481
+ end
3482
+
3483
+ #
3484
+ # Write the <c:noEndCap> element.
3485
+ #
3486
+ def write_no_end_cap
3487
+ @writer.empty_tag('c:noEndCap', ['val', 1])
3488
+ end
3489
+
3490
+ #
3491
+ # Write the <c:val> element.
3492
+ #
3493
+ def write_error_val(val)
3494
+ @writer.empty_tag('c:val', ['val', val])
3495
+ end
3496
+
3497
+ #
3498
+ # Write the <c:upDownBars> element.
3499
+ #
3500
+ def write_up_down_bars
3501
+ return unless ptrue?(@up_down_bars)
3502
+
3503
+ @writer.tag_elements('c:upDownBars') do
3504
+ # Write the c:gapWidth element.
3505
+ write_gap_width
3506
+
3507
+ # Write the c:upBars element.
3508
+ write_up_bars(@up_down_bars[:_up])
3509
+
3510
+ # Write the c:downBars element.
3511
+ write_down_bars(@up_down_bars[:_down])
3512
+ end
3513
+ end
3514
+
3515
+ #
3516
+ # Write the <c:gapWidth> element.
3517
+ #
3518
+ def write_gap_width
3519
+ @writer.empty_tag('c:gapWidth', ['val', 150])
3520
+ end
3521
+
3522
+ #
3523
+ # Write the <c:upBars> element.
3524
+ #
3525
+ def write_up_bars(format)
3526
+ write_bars_base('c:upBars', format)
3527
+ end
3528
+
3529
+ #
3530
+ # Write the <c:upBars> element.
3531
+ #
3532
+ def write_down_bars(format)
3533
+ write_bars_base('c:downBars', format)
3534
+ end
3535
+
3536
+ def write_bars_base(tag, format)
3537
+ if ptrue?(format[:_line][:_defined]) || ptrue?(format[:_fill][:_defined])
3538
+ @writer.tag_elements(tag) { write_sp_pr(format) }
3539
+ else
3540
+ @writer.empty_tag(tag)
3541
+ end
3542
+ end
3543
+
3501
3544
  def nil_or_max?(val) # :nodoc:
3502
3545
  val.nil? || val == 'max'
3503
3546
  end