write_xlsx 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/Changes +20 -0
- data/lib/write_xlsx/chart/area.rb +2 -2
- data/lib/write_xlsx/chart/axis.rb +55 -32
- data/lib/write_xlsx/chart/axis_writer.rb +528 -0
- data/lib/write_xlsx/chart/bar.rb +2 -2
- data/lib/write_xlsx/chart/caption.rb +16 -9
- data/lib/write_xlsx/chart/chart_area.rb +121 -0
- data/lib/write_xlsx/chart/column.rb +2 -2
- data/lib/write_xlsx/chart/d_pt_point_writer.rb +14 -0
- data/lib/write_xlsx/chart/doughnut.rb +0 -3
- data/lib/write_xlsx/chart/formatting_writer.rb +652 -0
- data/lib/write_xlsx/chart/initialization.rb +100 -0
- data/lib/write_xlsx/chart/line.rb +4 -3
- data/lib/write_xlsx/chart/pie.rb +6 -2
- data/lib/write_xlsx/chart/radar.rb +2 -2
- data/lib/write_xlsx/chart/scatter.rb +4 -3
- data/lib/write_xlsx/chart/series.rb +35 -15
- data/lib/write_xlsx/chart/series_data.rb +132 -0
- data/lib/write_xlsx/chart/series_writer.rb +318 -0
- data/lib/write_xlsx/chart/settings.rb +226 -0
- data/lib/write_xlsx/chart/stock.rb +2 -2
- data/lib/write_xlsx/chart/table.rb +50 -0
- data/lib/write_xlsx/chart/xml_writer.rb +305 -0
- data/lib/write_xlsx/chart.rb +286 -2477
- data/lib/write_xlsx/chartsheet.rb +31 -82
- data/lib/write_xlsx/constants.rb +11 -0
- data/lib/write_xlsx/drawing.rb +5 -3
- data/lib/write_xlsx/format/alignment_state.rb +39 -0
- data/lib/write_xlsx/format/alignment_style.rb +92 -0
- data/lib/write_xlsx/format/border_state.rb +47 -0
- data/lib/write_xlsx/format/border_style.rb +116 -0
- data/lib/write_xlsx/format/fill_state.rb +26 -0
- data/lib/write_xlsx/format/fill_style.rb +52 -0
- data/lib/write_xlsx/format/font_state.rb +74 -0
- data/lib/write_xlsx/format/font_style.rb +172 -0
- data/lib/write_xlsx/format/format_state.rb +65 -0
- data/lib/write_xlsx/format/number_format_state.rb +20 -0
- data/lib/write_xlsx/format/number_format_style.rb +28 -0
- data/lib/write_xlsx/format/protection_state.rb +20 -0
- data/lib/write_xlsx/format/protection_style.rb +28 -0
- data/lib/write_xlsx/format.rb +1093 -426
- data/lib/write_xlsx/formats.rb +0 -2
- data/lib/write_xlsx/image_property.rb +4 -1
- data/lib/write_xlsx/inserted_chart.rb +1 -1
- data/lib/write_xlsx/object_positioning.rb +15 -1
- data/lib/write_xlsx/package/app.rb +2 -2
- data/lib/write_xlsx/package/button.rb +6 -2
- data/lib/write_xlsx/package/comments.rb +11 -3
- data/lib/write_xlsx/package/conditional_format.rb +7 -3
- data/lib/write_xlsx/package/content_types.rb +2 -2
- data/lib/write_xlsx/package/core.rb +2 -2
- data/lib/write_xlsx/package/custom.rb +3 -2
- data/lib/write_xlsx/package/metadata.rb +2 -2
- data/lib/write_xlsx/package/packager.rb +0 -3
- data/lib/write_xlsx/package/relationships.rb +2 -2
- data/lib/write_xlsx/package/rich_value.rb +4 -2
- data/lib/write_xlsx/package/rich_value_rel.rb +2 -2
- data/lib/write_xlsx/package/rich_value_structure.rb +2 -2
- data/lib/write_xlsx/package/rich_value_types.rb +3 -3
- data/lib/write_xlsx/package/shared_strings.rb +2 -2
- data/lib/write_xlsx/package/styles.rb +13 -9
- data/lib/write_xlsx/package/table.rb +8 -2
- data/lib/write_xlsx/package/theme.rb +0 -3
- data/lib/write_xlsx/package/vml.rb +2 -2
- data/lib/write_xlsx/page_setup.rb +3 -1
- data/lib/write_xlsx/shape.rb +97 -100
- data/lib/write_xlsx/sheets.rb +6 -1
- data/lib/write_xlsx/sparkline.rb +2 -2
- data/lib/write_xlsx/utility/cell_reference.rb +124 -0
- data/lib/write_xlsx/utility/chart_formatting.rb +262 -0
- data/lib/write_xlsx/utility/common.rb +44 -0
- data/lib/write_xlsx/utility/date_time.rb +113 -0
- data/lib/write_xlsx/utility/dimensions.rb +40 -0
- data/lib/write_xlsx/utility/drawing.rb +136 -0
- data/lib/write_xlsx/utility/rich_text.rb +184 -0
- data/lib/write_xlsx/utility/sheetname_quoting.rb +73 -0
- data/lib/write_xlsx/utility/string_width.rb +45 -0
- data/lib/write_xlsx/utility/url.rb +27 -0
- data/lib/write_xlsx/utility/xml_primitives.rb +32 -0
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/workbook/chart_data.rb +188 -0
- data/lib/write_xlsx/workbook/format_preparation.rb +199 -0
- data/lib/write_xlsx/workbook/initialization.rb +223 -0
- data/lib/write_xlsx/workbook/package_preparation.rb +231 -0
- data/lib/write_xlsx/workbook/workbook_writer.rb +164 -0
- data/lib/write_xlsx/workbook.rb +143 -981
- data/lib/write_xlsx/worksheet/autofilter.rb +3 -1
- data/lib/write_xlsx/worksheet/cell_data.rb +5 -1
- data/lib/write_xlsx/worksheet/columns.rb +8 -3
- data/lib/write_xlsx/worksheet/data_validation.rb +9 -1
- data/lib/write_xlsx/worksheet/data_writing.rb +37 -10
- data/lib/write_xlsx/worksheet/formatting.rb +3 -1
- data/lib/write_xlsx/worksheet/hyperlink.rb +9 -1
- data/lib/write_xlsx/worksheet/row_col_sizing.rb +3 -1
- data/lib/write_xlsx/worksheet/xml_writer.rb +9 -4
- data/lib/write_xlsx/worksheet.rb +19 -2
- metadata +41 -2
- data/lib/write_xlsx/utility.rb +0 -1034
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
|
|
16
16
|
require 'write_xlsx/package/xml_writer_simple'
|
|
17
|
-
require 'write_xlsx/utility'
|
|
17
|
+
require 'write_xlsx/utility/xml_primitives'
|
|
18
18
|
|
|
19
19
|
module Writexlsx
|
|
20
20
|
class Chart
|
|
@@ -28,7 +28,7 @@ module Writexlsx
|
|
|
28
28
|
# chart = workbook.add_chart( :type => 'column', :subtype => 'stacked' )
|
|
29
29
|
#
|
|
30
30
|
class Column < self
|
|
31
|
-
include Writexlsx::Utility
|
|
31
|
+
include Writexlsx::Utility::XmlPrimitives
|
|
32
32
|
|
|
33
33
|
def initialize(subtype)
|
|
34
34
|
super
|
|
@@ -16,13 +16,10 @@
|
|
|
16
16
|
require 'write_xlsx/package/xml_writer_simple'
|
|
17
17
|
require 'write_xlsx/chart'
|
|
18
18
|
require 'write_xlsx/chart/pie'
|
|
19
|
-
require 'write_xlsx/utility'
|
|
20
19
|
|
|
21
20
|
module Writexlsx
|
|
22
21
|
class Chart
|
|
23
22
|
class Doughnut < Pie
|
|
24
|
-
include Writexlsx::Utility
|
|
25
|
-
|
|
26
23
|
def initialize(subtype)
|
|
27
24
|
super
|
|
28
25
|
@vary_data_color = 1
|
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
###############################################################################
|
|
5
|
+
#
|
|
6
|
+
# formatting_writer.rb - formatting, rich text, and label XML helpers
|
|
7
|
+
#
|
|
8
|
+
###############################################################################
|
|
9
|
+
|
|
10
|
+
module Writexlsx
|
|
11
|
+
class Chart
|
|
12
|
+
module FormattingWriter
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def write_chart_title(title, is_y_axis = nil, allow_none: false)
|
|
16
|
+
return unless title
|
|
17
|
+
|
|
18
|
+
if allow_none && title.none
|
|
19
|
+
write_auto_title_deleted
|
|
20
|
+
elsif ptrue?(title.name)
|
|
21
|
+
write_title_rich(title, is_y_axis)
|
|
22
|
+
elsif title.formula
|
|
23
|
+
write_title_formula(title, is_y_axis)
|
|
24
|
+
elsif has_formatting(title)
|
|
25
|
+
write_title_format_only(title)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Write the <c:title> element for a rich string.
|
|
31
|
+
#
|
|
32
|
+
def write_title_formula(title, is_y_axis = nil)
|
|
33
|
+
@writer.tag_elements('c:title') do
|
|
34
|
+
write_tx_formula(title.formula, title.data_id)
|
|
35
|
+
write_layout(title.layout, 'text')
|
|
36
|
+
write_overlay if title.overlay
|
|
37
|
+
write_sp_pr(title)
|
|
38
|
+
write_tx_pr(title.font, is_y_axis)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def write_title_format_only(title)
|
|
43
|
+
@writer.tag_elements('c:title') do
|
|
44
|
+
write_layout(title.layout, 'text')
|
|
45
|
+
write_overlay if title.overlay
|
|
46
|
+
write_sp_pr(title)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Write the <c:tx> element.
|
|
52
|
+
#
|
|
53
|
+
def write_tx_rich(title, is_y_axis, font) # :nodoc:
|
|
54
|
+
@writer.tag_elements('c:tx') do
|
|
55
|
+
write_rich(title, font, is_y_axis)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#
|
|
60
|
+
# Write the <c:tx> element with a simple value such as for series names.
|
|
61
|
+
#
|
|
62
|
+
def write_tx_value(title) # :nodoc:
|
|
63
|
+
@writer.tag_elements('c:tx') { write_v(title) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# Write the <c:tx> element.
|
|
68
|
+
#
|
|
69
|
+
def write_tx_formula(title, data_id) # :nodoc:
|
|
70
|
+
data = @formula_data[data_id] if data_id
|
|
71
|
+
|
|
72
|
+
@writer.tag_elements('c:tx') { write_str_ref(title, data, 'str') }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#
|
|
76
|
+
# Write the <c:rich> element.
|
|
77
|
+
#
|
|
78
|
+
def write_rich(title, font, is_y_axis, ignore_rich_pr = false) # :nodoc:
|
|
79
|
+
rotation = nil
|
|
80
|
+
|
|
81
|
+
rotation = font[:_rotation] if font && font[:_rotation]
|
|
82
|
+
@writer.tag_elements('c:rich') do
|
|
83
|
+
# Write the a:bodyPr element.
|
|
84
|
+
write_a_body_pr(rotation, is_y_axis)
|
|
85
|
+
# Write the a:lstStyle element.
|
|
86
|
+
write_a_lst_style
|
|
87
|
+
# Write the a:p element.
|
|
88
|
+
write_a_p_rich(title, font, ignore_rich_pr)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
# Write the <a:p> element for rich string titles.
|
|
94
|
+
#
|
|
95
|
+
def write_a_p_rich(title, font, ignore_rich_pr) # :nodoc:
|
|
96
|
+
@writer.tag_elements('a:p') do
|
|
97
|
+
# Write the a:pPr element.
|
|
98
|
+
write_a_p_pr_rich(font) unless ignore_rich_pr
|
|
99
|
+
# Write the a:r element.
|
|
100
|
+
write_a_r(title, font)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#
|
|
105
|
+
# Write the <a:pPr> element for rich string titles.
|
|
106
|
+
#
|
|
107
|
+
def write_a_p_pr_rich(font) # :nodoc:
|
|
108
|
+
@writer.tag_elements('a:pPr') { write_a_def_rpr(font) }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
#
|
|
112
|
+
# Write the <a:r> element.
|
|
113
|
+
#
|
|
114
|
+
def write_a_r(title, font) # :nodoc:
|
|
115
|
+
@writer.tag_elements('a:r') do
|
|
116
|
+
# Write the a:rPr element.
|
|
117
|
+
write_a_r_pr(font)
|
|
118
|
+
# Write the a:t element.
|
|
119
|
+
write_a_t(title.respond_to?(:name) ? title.name : title)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
#
|
|
124
|
+
# Write the <a:rPr> element.
|
|
125
|
+
#
|
|
126
|
+
def write_a_r_pr(font) # :nodoc:
|
|
127
|
+
attributes = [%w[lang en-US]]
|
|
128
|
+
attr_font = get_font_style_attributes(font)
|
|
129
|
+
attributes += attr_font unless attr_font.empty?
|
|
130
|
+
|
|
131
|
+
write_def_rpr_r_pr_common(font, attributes, 'a:rPr')
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
#
|
|
135
|
+
# Write the <a:t> element.
|
|
136
|
+
#
|
|
137
|
+
def write_a_t(title) # :nodoc:
|
|
138
|
+
@writer.data_element('a:t', title)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
#
|
|
142
|
+
# Write the <c:marker> element.
|
|
143
|
+
#
|
|
144
|
+
def write_marker(marker = nil) # :nodoc:
|
|
145
|
+
marker ||= @default_marker
|
|
146
|
+
|
|
147
|
+
return unless ptrue?(marker)
|
|
148
|
+
return if ptrue?(marker.automatic?)
|
|
149
|
+
|
|
150
|
+
@writer.tag_elements('c:marker') do
|
|
151
|
+
# Write the c:symbol element.
|
|
152
|
+
write_symbol(marker.type)
|
|
153
|
+
# Write the c:size element.
|
|
154
|
+
size = marker.size
|
|
155
|
+
write_marker_size(size) if ptrue?(size)
|
|
156
|
+
# Write the c:spPr element.
|
|
157
|
+
write_sp_pr(marker)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
#
|
|
162
|
+
# Write the <c:marker> element without a sub-element.
|
|
163
|
+
#
|
|
164
|
+
def write_marker_value # :nodoc:
|
|
165
|
+
return unless @default_marker
|
|
166
|
+
|
|
167
|
+
@writer.empty_tag('c:marker', [['val', 1]])
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
#
|
|
171
|
+
# Write the <c:size> element.
|
|
172
|
+
#
|
|
173
|
+
def write_marker_size(val) # :nodoc:
|
|
174
|
+
@writer.empty_tag('c:size', [['val', val]])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# Write the <c:symbol> element.
|
|
179
|
+
#
|
|
180
|
+
def write_symbol(val) # :nodoc:
|
|
181
|
+
@writer.empty_tag('c:symbol', [['val', val]])
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
#
|
|
185
|
+
# Write the <c:spPr> element.
|
|
186
|
+
#
|
|
187
|
+
def write_sp_pr(object) # :nodoc:
|
|
188
|
+
return unless has_formatting(object)
|
|
189
|
+
|
|
190
|
+
line = series_property(object, :line)
|
|
191
|
+
fill = series_property(object, :fill)
|
|
192
|
+
pattern = series_property(object, :pattern)
|
|
193
|
+
gradient = series_property(object, :gradient)
|
|
194
|
+
|
|
195
|
+
@writer.tag_elements('c:spPr') do
|
|
196
|
+
# Write the fill elements for solid charts such as pie/doughnut and bar.
|
|
197
|
+
if fill && fill[:_defined] != 0
|
|
198
|
+
if ptrue?(fill[:none])
|
|
199
|
+
# Write the a:noFill element.
|
|
200
|
+
write_a_no_fill
|
|
201
|
+
else
|
|
202
|
+
# Write the a:solidFill element.
|
|
203
|
+
write_a_solid_fill(fill)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
write_a_patt_fill(pattern) if ptrue?(pattern)
|
|
208
|
+
write_a_grad_fill(gradient) if ptrue?(gradient)
|
|
209
|
+
write_a_ln(line) if line && ptrue?(line[:_defined])
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def series_property(object, property)
|
|
214
|
+
if object.respond_to?(property)
|
|
215
|
+
object.send(property)
|
|
216
|
+
elsif object.respond_to?(:[])
|
|
217
|
+
object[property]
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
#
|
|
222
|
+
# Write the <a:ln> element.
|
|
223
|
+
#
|
|
224
|
+
def write_a_ln(line) # :nodoc:
|
|
225
|
+
attributes = []
|
|
226
|
+
|
|
227
|
+
# Add the line width as an attribute.
|
|
228
|
+
if line[:width]
|
|
229
|
+
width = line[:width]
|
|
230
|
+
# Round width to nearest 0.25, like Excel.
|
|
231
|
+
width = ((width + 0.125) * 4).to_i / 4.0
|
|
232
|
+
|
|
233
|
+
# Convert to internal units.
|
|
234
|
+
width = (0.5 + (12700 * width)).to_i
|
|
235
|
+
|
|
236
|
+
attributes << ['w', width]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
if ptrue?(line[:none]) || ptrue?(line[:color]) || line[:dash_type]
|
|
240
|
+
@writer.tag_elements('a:ln', attributes) do
|
|
241
|
+
# Write the line fill.
|
|
242
|
+
if ptrue?(line[:none])
|
|
243
|
+
# Write the a:noFill element.
|
|
244
|
+
write_a_no_fill
|
|
245
|
+
elsif ptrue?(line[:color])
|
|
246
|
+
# Write the a:solidFill element.
|
|
247
|
+
write_a_solid_fill(line)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Write the line/dash type.
|
|
251
|
+
if line[:dash_type]
|
|
252
|
+
# Write the a:prstDash element.
|
|
253
|
+
write_a_prst_dash(line[:dash_type])
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
else
|
|
257
|
+
@writer.empty_tag('a:ln', attributes)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
#
|
|
262
|
+
# Write the <a:noFill> element.
|
|
263
|
+
#
|
|
264
|
+
def write_a_no_fill # :nodoc:
|
|
265
|
+
@writer.empty_tag('a:noFill')
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
#
|
|
269
|
+
# Write the <a:alpha> element.
|
|
270
|
+
#
|
|
271
|
+
def write_a_alpha(val)
|
|
272
|
+
val = (100 - val.to_i) * 1000
|
|
273
|
+
|
|
274
|
+
@writer.empty_tag('a:alpha', [['val', val]])
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
#
|
|
278
|
+
# Write the <a:prstDash> element.
|
|
279
|
+
#
|
|
280
|
+
def write_a_prst_dash(val) # :nodoc:
|
|
281
|
+
@writer.empty_tag('a:prstDash', [['val', val]])
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
#
|
|
285
|
+
# Write the <a:gradFill> element.
|
|
286
|
+
#
|
|
287
|
+
def write_a_grad_fill(gradient)
|
|
288
|
+
attributes = [
|
|
289
|
+
%w[flip none],
|
|
290
|
+
['rotWithShape', 1]
|
|
291
|
+
]
|
|
292
|
+
attributes = [] if gradient[:type] == 'linear'
|
|
293
|
+
|
|
294
|
+
@writer.tag_elements('a:gradFill', attributes) do
|
|
295
|
+
# Write the a:gsLst element.
|
|
296
|
+
write_a_gs_lst(gradient)
|
|
297
|
+
|
|
298
|
+
if gradient[:type] == 'linear'
|
|
299
|
+
# Write the a:lin element.
|
|
300
|
+
write_a_lin(gradient[:angle])
|
|
301
|
+
else
|
|
302
|
+
# Write the a:path element.
|
|
303
|
+
write_a_path(gradient[:type])
|
|
304
|
+
|
|
305
|
+
# Write the a:tileRect element.
|
|
306
|
+
write_a_tile_rect(gradient[:type])
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
#
|
|
312
|
+
# Write the <a:gsLst> element.
|
|
313
|
+
#
|
|
314
|
+
def write_a_gs_lst(gradient)
|
|
315
|
+
positions = gradient[:positions]
|
|
316
|
+
colors = gradient[:colors]
|
|
317
|
+
|
|
318
|
+
@writer.tag_elements('a:gsLst') do
|
|
319
|
+
(0..(colors.size - 1)).each do |i|
|
|
320
|
+
pos = (positions[i] * 1000).to_i
|
|
321
|
+
|
|
322
|
+
attributes = [['pos', pos]]
|
|
323
|
+
@writer.tag_elements('a:gs', attributes) do
|
|
324
|
+
color = color(colors[i])
|
|
325
|
+
|
|
326
|
+
# Write the a:srgbClr element.
|
|
327
|
+
# TODO: Wait for a feature request to support transparency.
|
|
328
|
+
write_a_srgb_clr(color)
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
#
|
|
335
|
+
# Write the <a:lin> element.
|
|
336
|
+
#
|
|
337
|
+
def write_a_lin(angle)
|
|
338
|
+
scaled = 0
|
|
339
|
+
|
|
340
|
+
angle = (60000 * angle).to_i
|
|
341
|
+
|
|
342
|
+
attributes = [
|
|
343
|
+
['ang', angle],
|
|
344
|
+
['scaled', scaled]
|
|
345
|
+
]
|
|
346
|
+
|
|
347
|
+
@writer.empty_tag('a:lin', attributes)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
#
|
|
351
|
+
# Write the <a:path> element.
|
|
352
|
+
#
|
|
353
|
+
def write_a_path(type)
|
|
354
|
+
attributes = [['path', type]]
|
|
355
|
+
|
|
356
|
+
@writer.tag_elements('a:path', attributes) do
|
|
357
|
+
# Write the a:fillToRect element.
|
|
358
|
+
write_a_fill_to_rect(type)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
#
|
|
363
|
+
# Write the <a:fillToRect> element.
|
|
364
|
+
#
|
|
365
|
+
def write_a_fill_to_rect(type)
|
|
366
|
+
attributes = if type == 'shape'
|
|
367
|
+
[
|
|
368
|
+
['l', 50000],
|
|
369
|
+
['t', 50000],
|
|
370
|
+
['r', 50000],
|
|
371
|
+
['b', 50000]
|
|
372
|
+
]
|
|
373
|
+
else
|
|
374
|
+
[
|
|
375
|
+
['l', 100000],
|
|
376
|
+
['t', 100000]
|
|
377
|
+
]
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
@writer.empty_tag('a:fillToRect', attributes)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
#
|
|
384
|
+
# Write the <a:tileRect> element.
|
|
385
|
+
#
|
|
386
|
+
def write_a_tile_rect(type)
|
|
387
|
+
attributes = if type == 'shape'
|
|
388
|
+
[]
|
|
389
|
+
else
|
|
390
|
+
[
|
|
391
|
+
['r', -100000],
|
|
392
|
+
['b', -100000]
|
|
393
|
+
]
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
@writer.empty_tag('a:tileRect', attributes)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
#
|
|
400
|
+
# Write the <a:pattFill> element.
|
|
401
|
+
#
|
|
402
|
+
def write_a_patt_fill(pattern)
|
|
403
|
+
attributes = [['prst', pattern[:pattern]]]
|
|
404
|
+
|
|
405
|
+
@writer.tag_elements('a:pattFill', attributes) do
|
|
406
|
+
write_a_fg_clr(pattern[:fg_color])
|
|
407
|
+
write_a_bg_clr(pattern[:bg_color])
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def write_a_fg_clr(color)
|
|
412
|
+
@writer.tag_elements('a:fgClr') { write_a_srgb_clr(color(color)) }
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def write_a_bg_clr(color)
|
|
416
|
+
@writer.tag_elements('a:bgClr') { write_a_srgb_clr(color(color)) }
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
#
|
|
420
|
+
# Write the <c:numberFormat> element for data labels.
|
|
421
|
+
#
|
|
422
|
+
def write_data_label_number_format(format_code)
|
|
423
|
+
source_linked = 0
|
|
424
|
+
|
|
425
|
+
attributes = [
|
|
426
|
+
['formatCode', format_code],
|
|
427
|
+
['sourceLinked', source_linked]
|
|
428
|
+
]
|
|
429
|
+
|
|
430
|
+
@writer.empty_tag('c:numFmt', attributes)
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
#
|
|
434
|
+
# Write the <c:dLbls> element.
|
|
435
|
+
#
|
|
436
|
+
def write_d_lbls(labels) # :nodoc:
|
|
437
|
+
return unless labels
|
|
438
|
+
|
|
439
|
+
@writer.tag_elements('c:dLbls') do
|
|
440
|
+
# Write the custom c:dLbl elements.
|
|
441
|
+
write_custom_labels(labels, labels[:custom]) if labels[:custom]
|
|
442
|
+
# Write the c:numFmt element.
|
|
443
|
+
write_data_label_number_format(labels[:num_format]) if labels[:num_format]
|
|
444
|
+
# Write the c:spPr element.
|
|
445
|
+
write_sp_pr(labels)
|
|
446
|
+
# Write the data label font elements.
|
|
447
|
+
write_axis_font(labels[:font]) if labels[:font]
|
|
448
|
+
# Write the c:dLblPos element.
|
|
449
|
+
write_d_lbl_pos(labels[:position]) if ptrue?(labels[:position])
|
|
450
|
+
# Write the c:showLegendKey element.
|
|
451
|
+
write_show_legend_key if labels[:legend_key]
|
|
452
|
+
# Write the c:showVal element.
|
|
453
|
+
write_show_val if labels[:value]
|
|
454
|
+
# Write the c:showCatName element.
|
|
455
|
+
write_show_cat_name if labels[:category]
|
|
456
|
+
# Write the c:showSerName element.
|
|
457
|
+
write_show_ser_name if labels[:series_name]
|
|
458
|
+
# Write the c:showPercent element.
|
|
459
|
+
write_show_percent if labels[:percentage]
|
|
460
|
+
# Write the c:separator element.
|
|
461
|
+
write_separator(labels[:separator]) if labels[:separator]
|
|
462
|
+
# Write the c:showLeaderLines element.
|
|
463
|
+
write_show_leader_lines if labels[:leader_lines]
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
#
|
|
468
|
+
# Write the <c:dLbl> element.
|
|
469
|
+
#
|
|
470
|
+
def write_custom_labels(parent, labels)
|
|
471
|
+
index = 0
|
|
472
|
+
|
|
473
|
+
labels.each do |label|
|
|
474
|
+
index += 1
|
|
475
|
+
next unless ptrue?(label)
|
|
476
|
+
|
|
477
|
+
use_custom_formatting = true
|
|
478
|
+
|
|
479
|
+
@writer.tag_elements('c:dLbl') do
|
|
480
|
+
# Write the c:idx element.
|
|
481
|
+
write_idx(index - 1)
|
|
482
|
+
|
|
483
|
+
if label[:delete]
|
|
484
|
+
# Delete/hide label.
|
|
485
|
+
write_delete(1)
|
|
486
|
+
elsif label[:formula] || label[:value] || label[:position]
|
|
487
|
+
# Write the c:layout element.
|
|
488
|
+
write_layout
|
|
489
|
+
|
|
490
|
+
if label[:formula]
|
|
491
|
+
write_custom_label_formula(label)
|
|
492
|
+
elsif label[:value]
|
|
493
|
+
write_custom_label_str(label)
|
|
494
|
+
|
|
495
|
+
# String values use spPr formatting.
|
|
496
|
+
use_custom_formatting = false
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
write_custom_label_format(label) if use_custom_formatting
|
|
500
|
+
|
|
501
|
+
position = label[:position] || parent[:position]
|
|
502
|
+
write_d_lbl_pos(position) if position
|
|
503
|
+
|
|
504
|
+
write_show_val if parent[:value]
|
|
505
|
+
write_show_cat_name if parent[:category]
|
|
506
|
+
write_show_ser_name if parent[:series_name]
|
|
507
|
+
else
|
|
508
|
+
write_custom_label_format(label)
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
#
|
|
515
|
+
# Write parts of the <c:dLbl> element for strings.
|
|
516
|
+
#
|
|
517
|
+
def write_custom_label_str(label)
|
|
518
|
+
value = label[:value]
|
|
519
|
+
font = label[:font]
|
|
520
|
+
is_y_axis = 0
|
|
521
|
+
has_formatting = has_formatting(label)
|
|
522
|
+
|
|
523
|
+
@writer.tag_elements('c:tx') do
|
|
524
|
+
# Write the c:rich element.
|
|
525
|
+
write_rich(value, font, is_y_axis, !has_formatting)
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
# Write the c:cpPr element.
|
|
529
|
+
write_sp_pr(label)
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
#
|
|
533
|
+
# Write parts of the <c:dLbl> element for formulas.
|
|
534
|
+
#
|
|
535
|
+
def write_custom_label_formula(label)
|
|
536
|
+
formula = label[:formula]
|
|
537
|
+
data_id = label[:data_id]
|
|
538
|
+
|
|
539
|
+
data = @formula_data[data_id] if data_id
|
|
540
|
+
|
|
541
|
+
@writer.tag_elements('c:tx') do
|
|
542
|
+
# Write the c:strRef element.
|
|
543
|
+
write_str_ref(formula, data, 'str')
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
#
|
|
548
|
+
# Write the formatting and font elements for custom labels.
|
|
549
|
+
#
|
|
550
|
+
def write_custom_label_format(label)
|
|
551
|
+
font = label[:font]
|
|
552
|
+
has_formatting = has_formatting(label)
|
|
553
|
+
|
|
554
|
+
if has_formatting
|
|
555
|
+
# Write the c:spPr element.
|
|
556
|
+
write_sp_pr(label)
|
|
557
|
+
write_tx_pr(font)
|
|
558
|
+
elsif font
|
|
559
|
+
@writer.empty_tag('c:spPr')
|
|
560
|
+
write_tx_pr(font)
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
#
|
|
565
|
+
# Write the <c:showLegendKey> element.
|
|
566
|
+
#
|
|
567
|
+
def write_show_legend_key
|
|
568
|
+
@writer.empty_tag('c:showLegendKey', [['val', 1]])
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
#
|
|
572
|
+
# Write the <c:showVal> element.
|
|
573
|
+
#
|
|
574
|
+
def write_show_val # :nodoc:
|
|
575
|
+
@writer.empty_tag('c:showVal', [['val', 1]])
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
#
|
|
579
|
+
# Write the <c:showCatName> element.
|
|
580
|
+
#
|
|
581
|
+
def write_show_cat_name # :nodoc:
|
|
582
|
+
@writer.empty_tag('c:showCatName', [['val', 1]])
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
#
|
|
586
|
+
# Write the <c:showSerName> element.
|
|
587
|
+
#
|
|
588
|
+
def write_show_ser_name # :nodoc:
|
|
589
|
+
@writer.empty_tag('c:showSerName', [['val', 1]])
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
#
|
|
593
|
+
# Write the <c:showPercent> element.
|
|
594
|
+
#
|
|
595
|
+
def write_show_percent
|
|
596
|
+
@writer.empty_tag('c:showPercent', [['val', 1]])
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
#
|
|
600
|
+
# Write the <c:separator> element.
|
|
601
|
+
#
|
|
602
|
+
def write_separator(data)
|
|
603
|
+
@writer.data_element('c:separator', data)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
# Write the <c:showLeaderLines> element. This is different for Pie/Doughnut
|
|
607
|
+
# charts. Other chart types only supported leader lines after Excel 2015 via
|
|
608
|
+
# an extension element.
|
|
609
|
+
def write_show_leader_lines
|
|
610
|
+
uri = '{CE6537A1-D6FC-4f65-9D91-7224C49458BB}'
|
|
611
|
+
xmlns_c_15 = 'http://schemas.microsoft.com/office/drawing/2012/chart'
|
|
612
|
+
|
|
613
|
+
attributes1 = [
|
|
614
|
+
['uri', uri],
|
|
615
|
+
['xmlns:c15', xmlns_c_15]
|
|
616
|
+
]
|
|
617
|
+
|
|
618
|
+
attributes2 = [['val', 1]]
|
|
619
|
+
|
|
620
|
+
@writer.tag_elements('c:extLst') do
|
|
621
|
+
@writer.tag_elements('c:ext', attributes1) do
|
|
622
|
+
@writer.empty_tag('c15:showLeaderLines', attributes2)
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
#
|
|
628
|
+
# Write the <c:dLblPos> element.
|
|
629
|
+
#
|
|
630
|
+
def write_d_lbl_pos(val)
|
|
631
|
+
@writer.empty_tag('c:dLblPos', [['val', val]])
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
def has_formatting(element)
|
|
635
|
+
line = series_property(element, :line)
|
|
636
|
+
fill = series_property(element, :fill)
|
|
637
|
+
pattern = series_property(element, :pattern)
|
|
638
|
+
gradient = series_property(element, :gradient)
|
|
639
|
+
|
|
640
|
+
(line && ptrue?(line[:_defined])) ||
|
|
641
|
+
(fill && ptrue?(fill[:_defined])) || pattern || gradient
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
#
|
|
645
|
+
# Write the <a:latin> element.
|
|
646
|
+
#
|
|
647
|
+
def write_a_latin(args) # :nodoc:
|
|
648
|
+
@writer.empty_tag('a:latin', args)
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
end
|