write_xlsx 0.62.0 → 0.64.0

Sign up to get free protection for your applications and to get access to all the features.
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