write_xlsx 1.04.0 → 1.07.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Changes +19 -0
  4. data/README.md +1 -1
  5. data/examples/chart_data_labels.rb +320 -0
  6. data/lib/write_xlsx/chart.rb +152 -28
  7. data/lib/write_xlsx/chart/series.rb +100 -0
  8. data/lib/write_xlsx/utility.rb +4 -2
  9. data/lib/write_xlsx/version.rb +1 -1
  10. data/lib/write_xlsx/worksheet.rb +12 -6
  11. data/test/perl_output/chart_data_labels.xlsx +0 -0
  12. data/test/regression/test_array_formula04.rb +31 -0
  13. data/test/regression/test_chart_data_labels26.rb +44 -0
  14. data/test/regression/test_chart_data_labels27.rb +44 -0
  15. data/test/regression/test_chart_data_labels28.rb +52 -0
  16. data/test/regression/test_chart_data_labels29.rb +43 -0
  17. data/test/regression/test_chart_data_labels30.rb +46 -0
  18. data/test/regression/test_chart_data_labels31.rb +49 -0
  19. data/test/regression/test_chart_data_labels32.rb +54 -0
  20. data/test/regression/test_chart_data_labels33.rb +52 -0
  21. data/test/regression/test_chart_data_labels34.rb +54 -0
  22. data/test/regression/test_chart_data_labels35.rb +46 -0
  23. data/test/regression/test_chart_data_labels36.rb +54 -0
  24. data/test/regression/test_chart_data_labels37.rb +51 -0
  25. data/test/regression/test_chart_data_labels38.rb +54 -0
  26. data/test/regression/test_chart_data_labels39.rb +53 -0
  27. data/test/regression/test_chart_data_labels40.rb +53 -0
  28. data/test/regression/test_chart_data_labels41.rb +54 -0
  29. data/test/regression/test_chart_data_labels42.rb +58 -0
  30. data/test/regression/test_chart_data_labels43.rb +58 -0
  31. data/test/regression/test_chart_data_labels44.rb +56 -0
  32. data/test/regression/test_chart_data_labels45.rb +57 -0
  33. data/test/regression/test_chart_data_labels46.rb +61 -0
  34. data/test/regression/test_chart_data_labels47.rb +61 -0
  35. data/test/regression/xlsx_files/array_formula04.xlsx +0 -0
  36. data/test/regression/xlsx_files/chart_data_labels26.xlsx +0 -0
  37. data/test/regression/xlsx_files/chart_data_labels27.xlsx +0 -0
  38. data/test/regression/xlsx_files/chart_data_labels28.xlsx +0 -0
  39. data/test/regression/xlsx_files/chart_data_labels29.xlsx +0 -0
  40. data/test/regression/xlsx_files/chart_data_labels30.xlsx +0 -0
  41. data/test/regression/xlsx_files/chart_data_labels31.xlsx +0 -0
  42. data/test/regression/xlsx_files/chart_data_labels32.xlsx +0 -0
  43. data/test/regression/xlsx_files/chart_data_labels33.xlsx +0 -0
  44. data/test/regression/xlsx_files/chart_data_labels34.xlsx +0 -0
  45. data/test/regression/xlsx_files/chart_data_labels35.xlsx +0 -0
  46. data/test/regression/xlsx_files/chart_data_labels36.xlsx +0 -0
  47. data/test/regression/xlsx_files/chart_data_labels37.xlsx +0 -0
  48. data/test/regression/xlsx_files/chart_data_labels38.xlsx +0 -0
  49. data/test/regression/xlsx_files/chart_data_labels39.xlsx +0 -0
  50. data/test/regression/xlsx_files/chart_data_labels40.xlsx +0 -0
  51. data/test/regression/xlsx_files/chart_data_labels41.xlsx +0 -0
  52. data/test/regression/xlsx_files/chart_data_labels42.xlsx +0 -0
  53. data/test/regression/xlsx_files/chart_data_labels43.xlsx +0 -0
  54. data/test/regression/xlsx_files/chart_data_labels44.xlsx +0 -0
  55. data/test/regression/xlsx_files/chart_data_labels45.xlsx +0 -0
  56. data/test/regression/xlsx_files/chart_data_labels46.xlsx +0 -0
  57. data/test/regression/xlsx_files/chart_data_labels47.xlsx +0 -0
  58. data/test/test_example_match.rb +314 -1
  59. metadata +97 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c3893d317a3ab9f246b62c9d6b6b3a727abd9ab539da4edf52c4029f076d566
4
- data.tar.gz: 64861b9ce57ebd55ce67508b33be19705049a8db520edfacc1fd40d8547c2b9c
3
+ metadata.gz: 677847fdb975ab7253b3a5ed5f6aa779a9bbf2a459e941f5037b7d557e2abfe4
4
+ data.tar.gz: 4c4b0b03ce3b510a0ad6423c30a76fc778463afe92f992da52b49bbe65c7a1ac
5
5
  SHA512:
6
- metadata.gz: c3870b13ed05dca60597ecc86662d15d2ec143667e6ff29349c4409d2dd7966eb9f7246f14071a06524a15f5039cb8ec2d4c6c4fb99206b1377f452abe94eddc
7
- data.tar.gz: b776541fecba7724e59e5742939e331944ea9a08d87eba2528d29404f9f34bbab8a8abe548fd52735a15c72e42e54c54cc73ad5c06765521647771178229fab0
6
+ metadata.gz: b3f81d2d54e5f7a7170c34e7666f58c7f4f77b993ff3b95263327b0ff8edff5c9a0b1a6ea825ece5b43c5b1d2b91a6f01764237f22ee6442bd8c747de8e04150
7
+ data.tar.gz: 3e49064459345dbcc5d97fef0f8154159776e8361cb0709e8a4564f32dd062fe95b6e4f08976df81b5ac478a40287be9a33086726444af3c75d1cbeb5c869dc2
data/.travis.yml CHANGED
@@ -63,4 +63,3 @@ rvm:
63
63
  - 2.1.1
64
64
  - 2.1.0
65
65
  - 2.0.0
66
- - 1.9.3
data/Changes CHANGED
@@ -1,5 +1,24 @@
1
1
  Change history of write_xlsx rubygem.
2
2
 
3
+ 2021-02-17 v1.07.0
4
+
5
+ Added support for Border, Fill, Pattern and Gradient formatting to chart
6
+ data labels and chart custom data labels.
7
+
8
+
9
+ 2021-02-15 v1.06.0
10
+
11
+ Fix for issue where array formulas weren't included in the output file
12
+ for certain ranges/conditions.
13
+
14
+
15
+ 2021-02-15 v1.05.0
16
+
17
+ Added support for custom data labels in charts.
18
+
19
+ Remove ruby-1.9.3 travil CI check.
20
+
21
+
3
22
  2021-02-14 v1.04.0
4
23
 
5
24
  Added support for "stacked" and "percent_stacked" Line charts.
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  gem to create a new file in the Excel 2007+ XLSX format, and you can use the
7
7
  same interface as writeexcel gem. write_xlsx is converted from Perl's module
8
- [Excel::Writer::XLSX-1.04](https://github.com/jmcnamara/excel-writer-xlsx/tree/CPAN_1.04)
8
+ [Excel::Writer::XLSX-1.07](https://github.com/jmcnamara/excel-writer-xlsx/tree/CPAN_1.07)
9
9
 
10
10
  ## Description
11
11
 
@@ -0,0 +1,320 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #######################################################################
5
+ #
6
+ # A demo of an various Excel chart data label features that are available
7
+ # via an WriteXLSX chart.
8
+ #
9
+ # Copyright 2000-2020, John McNamara, jmcnamara@cpan.org
10
+ # convert to ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
11
+ #
12
+
13
+ require 'write_xlsx'
14
+
15
+ workbook = WriteXLSX.new('chart_data_labels.xlsx')
16
+ worksheet = workbook.add_worksheet
17
+ bold = workbook.add_format(:bold => 1)
18
+
19
+ # Add the worksheet data that the charts will refer to.
20
+ headings = ['Number', 'Data', 'Text']
21
+ data = [
22
+ [ 2, 3, 4, 5, 6, 7 ],
23
+ [20, 10, 20, 30, 40, 30 ],
24
+ ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
25
+ ]
26
+
27
+ worksheet.write('A1', headings, bold)
28
+ worksheet.write('A2', data)
29
+
30
+
31
+ #######################################################################
32
+ #
33
+ # Example with standard data labels.
34
+ #
35
+
36
+ # Create a Column chart.
37
+ chart1 = workbook.add_chart(:type => 'column', :embedded => 1)
38
+
39
+ # Configure the data series and add the data labels.
40
+ chart1.add_series(
41
+ :categories => '=Sheet1!$A$2:$A$7',
42
+ :values => '=Sheet1!$B$2:$B$7',
43
+ :data_labels => { :value => 1 }
44
+ )
45
+
46
+ # Add a chart title.
47
+ chart1.set_title(:name => 'Chart with standard data labels')
48
+
49
+ # Turn off the chart legend.
50
+ chart1.set_legend(:none => 1)
51
+
52
+ # Insert the chart into the worksheet (with an offset).
53
+ worksheet.insert_chart('D2', chart1, { :x_offset => 25, :y_offset => 10 })
54
+
55
+
56
+ #######################################################################
57
+ #
58
+ # Example with value and category data labels.
59
+ #
60
+
61
+ # Create a Column chart.
62
+ chart2 = workbook.add_chart(:type => 'column', :embedded => 1)
63
+
64
+ # Configure the data series and add the data labels.
65
+ chart2.add_series(
66
+ :categories => '=Sheet1!$A$2:$A$7',
67
+ :values => '=Sheet1!$B$2:$B$7',
68
+ :data_labels => { :value => 1, :category => 1 }
69
+ )
70
+
71
+ # Add a chart title.
72
+ chart2.set_title(:name => 'Category and Value data labels')
73
+
74
+ # Turn off the chart legend.
75
+ chart2.set_legend(:none => 1)
76
+
77
+ # Insert the chart into the worksheet (with an offset).
78
+ worksheet.insert_chart('D18', chart2, { :x_offset => 25, :y_offset => 10 })
79
+
80
+
81
+ #######################################################################
82
+ #
83
+ # Example with standard data labels with different font.
84
+ #
85
+
86
+ # Create a Column chart.
87
+ chart3 = workbook.add_chart(:type => 'column', :embedded => 1)
88
+
89
+ # Configure the data series and add the data labels.
90
+ chart3.add_series(
91
+ :categories => '=Sheet1!$A$2:$A$7',
92
+ :values => '=Sheet1!$B$2:$B$7',
93
+ :data_labels => { :value => 1,
94
+ :font => {:bold => 1,
95
+ :color => 'red',
96
+ :rotation => -30}
97
+ }
98
+ )
99
+
100
+ # Add a chart title.
101
+ chart3.set_title(:name => 'Data labels with user defined font')
102
+
103
+ # Turn off the chart legend.
104
+ chart3.set_legend(:none => 1)
105
+
106
+ # Insert the chart into the worksheet (with an offset).
107
+ worksheet.insert_chart('D34', chart3, { :x_offset => 25, :y_offset => 10 })
108
+
109
+
110
+ #######################################################################
111
+ #
112
+ # Example with custom string data labels.
113
+ #
114
+
115
+ # Create a Column chart.
116
+ chart4 = workbook.add_chart(:type => 'column', :embedded => 1)
117
+
118
+ # Configure the data series and add the data labels.
119
+ chart4.add_series(
120
+ :categories => '=Sheet1!$A$2:$A$7',
121
+ :values => '=Sheet1!$B$2:$B$7',
122
+ :data_labels => {
123
+ :value => 1,
124
+ :border => {:color => 'red'},
125
+ :fill => {:color => 'yellow'}
126
+ }
127
+ )
128
+
129
+ # Add a chart title.
130
+ chart4.set_title(:name => 'Data labels with formatting')
131
+
132
+ # Turn off the chart legend.
133
+ chart4.set_legend(:none => 1)
134
+
135
+ # Insert the chart into the worksheet (with an offset).
136
+ worksheet.insert_chart('D50', chart4, { :x_offset => 25, :y_offset => 10 })
137
+
138
+
139
+ #######################################################################
140
+ #
141
+ # Example with custom string data labels.
142
+ #
143
+
144
+ # Create a Column chart.
145
+ chart5 = workbook.add_chart( :type => 'column', :embedded => 1 )
146
+
147
+ # Some custom labels.
148
+ custom_labels = [
149
+ { :value => 'Amy' },
150
+ { :value => 'Bea' },
151
+ { :value => 'Eva' },
152
+ { :value => 'Fay' },
153
+ { :value => 'Liv' },
154
+ { :value => 'Una' }
155
+ ]
156
+
157
+ # Configure the data series and add the data labels.
158
+ chart5.add_series(
159
+ :categories => '=Sheet1!$A$2:$A$7',
160
+ :values => '=Sheet1!$B$2:$B$7',
161
+ :data_labels => { :value => 1, :custom => custom_labels }
162
+ )
163
+
164
+ # Add a chart title.
165
+ chart5.set_title(:name => 'Chart with custom string data labels')
166
+
167
+ # Turn off the chart legend.
168
+ chart5.set_legend(:none => 1)
169
+
170
+ # Insert the chart into the worksheet (with an offset).
171
+ worksheet.insert_chart('D66', chart5, { :x_offset => 25, :y_offset => 10 })
172
+
173
+
174
+ #######################################################################
175
+ #
176
+ # Example with custom data labels from cells.
177
+ #
178
+
179
+ # Create a Column chart.
180
+ chart6 = workbook.add_chart(:type => 'column', :embedded => 1)
181
+
182
+ # Some custom labels.
183
+ custom_labels = [
184
+ { :value => '=Sheet1!$C$2' },
185
+ { :value => '=Sheet1!$C$3' },
186
+ { :value => '=Sheet1!$C$4' },
187
+ { :value => '=Sheet1!$C$5' },
188
+ { :value => '=Sheet1!$C$6' },
189
+ { :value => '=Sheet1!$C$7' }
190
+ ]
191
+
192
+
193
+ # Configure the data series and add the data labels.
194
+ chart6.add_series(
195
+ :categories => '=Sheet1!$A$2:$A$7',
196
+ :values => '=Sheet1!$B$2:$B$7',
197
+ :data_labels => { :value => 1, :custom => custom_labels }
198
+ )
199
+
200
+ # Add a chart title.
201
+ chart6.set_title(:name => 'Chart with custom data labels from cells')
202
+
203
+ # Turn off the chart legend.
204
+ chart6.set_legend(:none => 1)
205
+
206
+ # Insert the chart into the worksheet (with an offset).
207
+ worksheet.insert_chart('D82', chart6, { :x_offset => 25, :y_offset => 10 })
208
+
209
+
210
+ #######################################################################
211
+ #
212
+ # Example with custom and default data labels.
213
+ #
214
+
215
+ # Create a Column chart.
216
+ chart7 = workbook.add_chart(:type => 'column', :embedded => 1)
217
+
218
+ # Some custom labels. The nil items will get the default value.
219
+ # We also set a font for the custom items as an extra example.
220
+ custom_labels = [
221
+ { :value => '=Sheet1!$C$2', :font => { :color => 'red' } },
222
+ nil,
223
+ { :value => '=Sheet1!$C$4', :font => { :color => 'red' } },
224
+ { :value => '=Sheet1!$C$5', :font => { :color => 'red' } }
225
+ ]
226
+
227
+
228
+ # Configure the data series and add the data labels.
229
+ chart7.add_series(
230
+ :categories => '=Sheet1!$A$2:$A$7',
231
+ :values => '=Sheet1!$B$2:$B$7',
232
+ :data_labels => { :value => 1, :custom => custom_labels }
233
+ )
234
+
235
+ # Add a chart title.
236
+ chart7.set_title(:name => 'Mixed custom and default data labels')
237
+
238
+ # Turn off the chart legend.
239
+ chart7.set_legend(:none => 1)
240
+
241
+ # Insert the chart into the worksheet (with an offset).
242
+ worksheet.insert_chart('D98', chart7, { :x_offset => 25, :y_offset => 10 })
243
+
244
+
245
+ #######################################################################
246
+ #
247
+ # Example with deleted custom data labels.
248
+ #
249
+
250
+ # Create a Column chart.
251
+ chart8 = workbook.add_chart(:type => 'column', :embedded => 1)
252
+
253
+ # Some deleted custom labels and defaults (nil). This allows us to
254
+ # highlight certain values such as the minimum and maximum.
255
+ custom_labels = [
256
+ { :delete => 1 },
257
+ nil,
258
+ { :delete => 1 },
259
+ { :delete => 1 },
260
+ nil,
261
+ { :delete => 1 }
262
+ ]
263
+
264
+ # Configure the data series and add the data labels.
265
+ chart8.add_series(
266
+ :categories => '=Sheet1!$A$2:$A$7',
267
+ :values => '=Sheet1!$B$2:$B$7',
268
+ :data_labels => { :value => 1, :custom => custom_labels }
269
+ )
270
+
271
+ # Add a chart title.
272
+ chart8.set_title(:name => 'Chart with deleted data labels')
273
+
274
+ # Turn off the chart legend.
275
+ chart8.set_legend(:none => 1)
276
+
277
+ # Insert the chart into the worksheet (with an offset).
278
+ worksheet.insert_chart('D114', chart8, { :x_offset => 25, :y_offset => 10 })
279
+
280
+ #######################################################################
281
+ #
282
+ # Example with custom string data labels and formatting.
283
+ #
284
+
285
+ # Create a Column chart.
286
+ chart9 = workbook.add_chart( :type => 'column', :embedded => 1 )
287
+
288
+ # Some custom labels.
289
+ custom_labels = [
290
+ { :value => 'Amy', :border => {:color => 'blue'} },
291
+ { :value => 'Bea' },
292
+ { :value => 'Eva' },
293
+ { :value => 'Fay' },
294
+ { :value => 'Liv' },
295
+ { :value => 'Una', :fill => {:color => 'green'} }
296
+ ]
297
+
298
+
299
+ # Configure the data series and add the data labels.
300
+ chart9.add_series(
301
+ :categories => '=Sheet1!$A$2:$A$7',
302
+ :values => '=Sheet1!$B$2:$B$7',
303
+ :data_labels => {
304
+ :value => 1,
305
+ :custom => custom_labels,
306
+ :border => {:color => 'red'},
307
+ :fill => {:color => 'yellow'}
308
+ }
309
+ )
310
+
311
+ # Add a chart title.
312
+ chart9.set_title( :name => 'Chart with custom labels and formatting' )
313
+
314
+ # Turn off the chart legend.
315
+ chart9.set_legend( :none => 1 )
316
+
317
+ # Insert the chart into the worksheet (with an offset).
318
+ worksheet.insert_chart( 'D130', chart9, { :x_offset => 25, :y_offset => 10 } )
319
+
320
+ workbook.close
@@ -34,7 +34,7 @@ def write_d_table(writer)
34
34
  @writer.empty_tag('c:showOutline', attributes) if ptrue?(outline)
35
35
  @writer.empty_tag('c:showKeys', attributes) if ptrue?(show_keys)
36
36
  # Write the table font.
37
- write_tx_pr(nil, font) if ptrue?(font)
37
+ write_tx_pr(font) if ptrue?(font)
38
38
  end
39
39
  end
40
40
 
@@ -783,7 +783,7 @@ def write_chart # :nodoc:
783
783
  elsif @title.formula
784
784
  write_title_formula(@title, nil, nil, @title.layout, @title.overlay)
785
785
  elsif @title.name
786
- write_title_rich(@title, nil, @title.layout, @title.overlay)
786
+ write_title_rich(@title, nil, @title.name_font, @title.layout, @title.overlay)
787
787
  end
788
788
 
789
789
  # Write the c:plotArea element.
@@ -1204,7 +1204,7 @@ def write_cat_axis(params) # :nodoc:
1204
1204
  if x_axis.formula
1205
1205
  write_title_formula(x_axis, is_y_axis, @x_axis, x_axis.layout)
1206
1206
  elsif x_axis.name
1207
- write_title_rich(x_axis, is_y_axis, x_axis.layout)
1207
+ write_title_rich(x_axis, is_y_axis, x_axis.name_font, x_axis.layout)
1208
1208
  end
1209
1209
 
1210
1210
  # Write the c:numFmt element.
@@ -1281,7 +1281,7 @@ def write_val_axis_base(x_axis, y_axis, axis_ids_0, axis_ids_1, position) # :no
1281
1281
  if y_axis.formula
1282
1282
  write_title_formula(y_axis, @horiz_val_axis, nil, y_axis.layout)
1283
1283
  elsif y_axis.name
1284
- write_title_rich(y_axis, @horiz_val_axis, y_axis.layout)
1284
+ write_title_rich(y_axis, @horiz_val_axis, y_axis.name_font, y_axis.layout)
1285
1285
  end
1286
1286
 
1287
1287
  # Write the c:numberFormat element.
@@ -1356,7 +1356,7 @@ def write_date_axis(params) # :nodoc:
1356
1356
  if x_axis.formula
1357
1357
  write_title_formula(x_axis, nil, nil, x_axis.layout)
1358
1358
  elsif x_axis.name
1359
- write_title_rich(x_axis, nil, x_axis.layout)
1359
+ write_title_rich(x_axis, nil, x_axis.name_font, x_axis.layout)
1360
1360
  end
1361
1361
  # Write the c:numFmt element.
1362
1362
  write_number_format(x_axis)
@@ -1693,7 +1693,7 @@ def write_legend # :nodoc:
1693
1693
  # Write the c:spPr element.
1694
1694
  write_sp_pr(@legend)
1695
1695
  # Write the c:txPr element.
1696
- write_tx_pr(nil, @legend.font) if ptrue?(@legend.font)
1696
+ write_tx_pr(@legend.font) if ptrue?(@legend.font)
1697
1697
  end
1698
1698
  end
1699
1699
 
@@ -1808,10 +1808,10 @@ def write_auto_title_deleted
1808
1808
  #
1809
1809
  # Write the <c:title> element for a rich string.
1810
1810
  #
1811
- def write_title_rich(title, is_y_axis = nil, layout = nil, overlay = nil) # :nodoc:
1811
+ def write_title_rich(title, is_y_axis, font, layout, overlay = nil) # :nodoc:
1812
1812
  @writer.tag_elements('c:title') do
1813
1813
  # Write the c:tx element.
1814
- write_tx_rich(title, is_y_axis)
1814
+ write_tx_rich(title, is_y_axis, font)
1815
1815
  # Write the c:layout element.
1816
1816
  write_layout(layout, 'text')
1817
1817
  # Write the c:overlay element.
@@ -1831,15 +1831,17 @@ def write_title_formula(title, is_y_axis = nil, axis = nil, layout = nil, overla
1831
1831
  # Write the c:overlay element.
1832
1832
  write_overlay if overlay
1833
1833
  # Write the c:txPr element.
1834
- write_tx_pr(is_y_axis, axis ? axis.name_font : title.name_font)
1834
+ write_tx_pr(axis ? axis.name_font : title.name_font, is_y_axis)
1835
1835
  end
1836
1836
  end
1837
1837
 
1838
1838
  #
1839
1839
  # Write the <c:tx> element.
1840
1840
  #
1841
- def write_tx_rich(title, is_y_axis) # :nodoc:
1842
- @writer.tag_elements('c:tx') { write_rich(title, is_y_axis) }
1841
+ def write_tx_rich(title, is_y_axis, font) # :nodoc:
1842
+ @writer.tag_elements('c:tx') do
1843
+ write_rich(title, font, is_y_axis)
1844
+ end
1843
1845
  end
1844
1846
 
1845
1847
  #
@@ -1861,10 +1863,11 @@ def write_tx_formula(title, data_id) # :nodoc:
1861
1863
  #
1862
1864
  # Write the <c:rich> element.
1863
1865
  #
1864
- def write_rich(title, is_y_axis) # :nodoc:
1866
+ def write_rich(title, font, is_y_axis, ignore_rich_pr = false) # :nodoc:
1865
1867
  rotation = nil
1866
- if title.name_font && title.name_font[:_rotation]
1867
- rotation = title.name_font[:_rotation]
1868
+
1869
+ if font && font[:_rotation]
1870
+ rotation = font[:_rotation]
1868
1871
  end
1869
1872
  @writer.tag_elements('c:rich') do
1870
1873
  # Write the a:bodyPr element.
@@ -1872,18 +1875,18 @@ def write_rich(title, is_y_axis) # :nodoc:
1872
1875
  # Write the a:lstStyle element.
1873
1876
  write_a_lst_style
1874
1877
  # Write the a:p element.
1875
- write_a_p_rich(title)
1878
+ write_a_p_rich(title, font, ignore_rich_pr)
1876
1879
  end
1877
1880
  end
1878
1881
  #
1879
1882
  # Write the <a:p> element for rich string titles.
1880
1883
  #
1881
- def write_a_p_rich(title) # :nodoc:
1884
+ def write_a_p_rich(title, font, ignore_rich_pr) # :nodoc:
1882
1885
  @writer.tag_elements('a:p') do
1883
1886
  # Write the a:pPr element.
1884
- write_a_p_pr_rich(title.name_font)
1887
+ write_a_p_pr_rich(font) if !ignore_rich_pr
1885
1888
  # Write the a:r element.
1886
- write_a_r(title)
1889
+ write_a_r(title, font)
1887
1890
  end
1888
1891
  end
1889
1892
 
@@ -1897,12 +1900,12 @@ def write_a_p_pr_rich(font) # :nodoc:
1897
1900
  #
1898
1901
  # Write the <a:r> element.
1899
1902
  #
1900
- def write_a_r(title) # :nodoc:
1903
+ def write_a_r(title, font) # :nodoc:
1901
1904
  @writer.tag_elements('a:r') do
1902
1905
  # Write the a:rPr element.
1903
- write_a_r_pr(title.name_font)
1906
+ write_a_r_pr(font)
1904
1907
  # Write the a:t element.
1905
- write_a_t(title.name)
1908
+ write_a_t(title.respond_to?(:name) ? title.name : title)
1906
1909
  end
1907
1910
  end
1908
1911
 
@@ -1967,17 +1970,27 @@ def write_symbol(val) # :nodoc:
1967
1970
  @writer.empty_tag('c:symbol', [ ['val', val] ])
1968
1971
  end
1969
1972
 
1973
+ def has_fill_formatting(element)
1974
+ line = series_property(element, :line)
1975
+ fill = series_property(element, :fill)
1976
+ pattern = series_property(element, :pattern)
1977
+ gradient = series_property(element, :gradient)
1978
+
1979
+ (line && ptrue?(line[:_defined])) ||
1980
+ (fill && ptrue?(fill[:_defined])) || pattern || gradient
1981
+ end
1982
+
1983
+
1970
1984
  #
1971
1985
  # Write the <c:spPr> element.
1972
1986
  #
1973
1987
  def write_sp_pr(series) # :nodoc:
1974
- line = series.line
1975
- fill = series.fill
1976
- pattern = series.pattern if series.respond_to?(:pattern)
1977
- gradient = series.gradient if series.respond_to?(:gradient)
1988
+ return if !has_fill_formatting(series)
1978
1989
 
1979
- return if (!line || !ptrue?(line[:_defined])) &&
1980
- (!fill || !ptrue?(fill[:_defined])) && !pattern && !gradient
1990
+ line = series_property(series, :line)
1991
+ fill = series_property(series, :fill)
1992
+ pattern = series_property(series, :pattern)
1993
+ gradient = series_property(series, :gradient)
1981
1994
 
1982
1995
  @writer.tag_elements('c:spPr') do
1983
1996
  # Write the fill elements for solid charts such as pie/doughnut and bar.
@@ -2002,6 +2015,14 @@ def write_sp_pr(series) # :nodoc:
2002
2015
  end
2003
2016
  end
2004
2017
 
2018
+ def series_property(object, property)
2019
+ if object.respond_to?(property)
2020
+ object.send(property)
2021
+ elsif object.respond_to?(:[])
2022
+ object[property]
2023
+ end
2024
+ end
2025
+
2005
2026
  #
2006
2027
  # Write the <a:ln> element.
2007
2028
  #
@@ -2349,8 +2370,14 @@ def write_d_lbls(labels) # :nodoc:
2349
2370
  return unless labels
2350
2371
 
2351
2372
  @writer.tag_elements('c:dLbls') do
2373
+ # Write the custom c:dLbl elements.
2374
+ if labels[:custom]
2375
+ write_custom_labels(labels, labels[:custom])
2376
+ end
2352
2377
  # Write the c:numFmt element.
2353
2378
  write_data_label_number_format(labels[:num_format]) if labels[:num_format]
2379
+ # Write the c:spPr element.
2380
+ write_sp_pr(labels)
2354
2381
  # Write the data label font elements.
2355
2382
  write_axis_font(labels[:font]) if labels[:font]
2356
2383
  # Write the c:dLblPos element.
@@ -2372,6 +2399,103 @@ def write_d_lbls(labels) # :nodoc:
2372
2399
  end
2373
2400
  end
2374
2401
 
2402
+ #
2403
+ # Write the <c:dLbl> element.
2404
+ #
2405
+ def write_custom_labels(parent, labels)
2406
+ index = 0
2407
+
2408
+ labels.each do |label|
2409
+ index += 1
2410
+ next if !ptrue?(label)
2411
+
2412
+ @writer.tag_elements('c:dLbl') do
2413
+ # Write the c:idx element.
2414
+ write_idx(index - 1)
2415
+
2416
+ if label[:delete] && label[:delete]
2417
+ write_delete(1)
2418
+ elsif label[:formula]
2419
+ write_custom_label_formula(label)
2420
+
2421
+ write_show_val if parent[:value]
2422
+ write_show_cat_name if parent[:category]
2423
+ write_show_ser_name if parent[:series_name]
2424
+ elsif label[:value]
2425
+ write_custom_label_str(label)
2426
+
2427
+ write_show_val if parent[:value]
2428
+ write_show_cat_name if parent[:category]
2429
+ write_show_ser_name if parent[:series_name]
2430
+ else
2431
+ write_custom_label_format_only(label)
2432
+ end
2433
+ end
2434
+ end
2435
+ end
2436
+
2437
+ #
2438
+ # Write parts of the <c:dLbl> element for strings.
2439
+ #
2440
+ def write_custom_label_str(label)
2441
+ value = label[:value]
2442
+ font = label[:font]
2443
+ is_y_axis = 0
2444
+ has_formatting = has_fill_formatting(label)
2445
+
2446
+ # Write the c:layout element.
2447
+ write_layout()
2448
+
2449
+ @writer.tag_elements('c:tx') do
2450
+ # Write the c:rich element.
2451
+ write_rich(value, font, is_y_axis, !has_formatting)
2452
+ end
2453
+
2454
+ # Write the c:cpPr element.
2455
+ write_sp_pr(label)
2456
+ end
2457
+
2458
+ #
2459
+ # Write parts of the <c:dLbl> element for formulas.
2460
+ #
2461
+ def write_custom_label_formula(label)
2462
+ formula = label[:formula]
2463
+ data_id = label[:data_id]
2464
+
2465
+ if data_id
2466
+ data = @formula_data[data_id]
2467
+ end
2468
+
2469
+ # Write the c:layout element.
2470
+ write_layout
2471
+
2472
+ @writer.tag_elements('c:tx') do
2473
+ # Write the c:strRef element.
2474
+ write_str_ref(formula, data, 'str')
2475
+ end
2476
+
2477
+ # Write the data label formatting, if any.
2478
+ write_custom_label_format_only(label)
2479
+ end
2480
+
2481
+ #
2482
+ # Write parts of the <c:dLbl> element for labels where only the formatting has
2483
+ # changed.
2484
+ #
2485
+ def write_custom_label_format_only(label)
2486
+ font = label[:font]
2487
+ has_formatting = has_fill_formatting(label)
2488
+
2489
+ if has_formatting
2490
+ # Write the c:spPr element.
2491
+ write_sp_pr(label)
2492
+ write_tx_pr(font)
2493
+ elsif font
2494
+ @writer.empty_tag('c:spPr')
2495
+ write_tx_pr(font)
2496
+ end
2497
+ end
2498
+
2375
2499
  #
2376
2500
  # Write the <c:showLegendKey> element.
2377
2501
  #
@@ -2700,7 +2824,7 @@ def write_a_gs_lst(gradient)
2700
2824
 
2701
2825
  # Write the a:srgbClr element.
2702
2826
  # TODO: Wait for a feature request to support transparency.
2703
- write_a_srgb_clr( color );
2827
+ write_a_srgb_clr( color )
2704
2828
  end
2705
2829
  end
2706
2830
  end