ruby_pptx 0.1.0 → 0.2.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/CHANGELOG.md +33 -0
- data/README.md +83 -2
- data/lib/ruby_pptx/action.rb +12 -4
- data/lib/ruby_pptx/autoshape_spec.rb +6 -2
- data/lib/ruby_pptx/builder.rb +3 -1
- data/lib/ruby_pptx/chart/categories.rb +45 -15
- data/lib/ruby_pptx/chart/chart.rb +77 -27
- data/lib/ruby_pptx/chart/combo.rb +9 -3
- data/lib/ruby_pptx/chart/data.rb +45 -15
- data/lib/ruby_pptx/chart/format.rb +229 -76
- data/lib/ruby_pptx/chart/workbook_writer.rb +9 -3
- data/lib/ruby_pptx/chart/xml_writer.rb +54 -18
- data/lib/ruby_pptx/chart/xy_data.rb +68 -22
- data/lib/ruby_pptx/dml/color.rb +27 -9
- data/lib/ruby_pptx/dml/effect.rb +6 -2
- data/lib/ruby_pptx/dml/fill.rb +42 -14
- data/lib/ruby_pptx/element_proxy.rb +12 -4
- data/lib/ruby_pptx/enum/base.rb +30 -10
- data/lib/ruby_pptx/enum/prog_id.rb +3 -1
- data/lib/ruby_pptx/geometry.rb +32 -10
- data/lib/ruby_pptx/image.rb +27 -9
- data/lib/ruby_pptx/length.rb +94 -27
- data/lib/ruby_pptx/media.rb +12 -4
- data/lib/ruby_pptx/numeric_lengths.rb +34 -9
- data/lib/ruby_pptx/opc/oxml.rb +7 -5
- data/lib/ruby_pptx/opc/pack_uri.rb +15 -5
- data/lib/ruby_pptx/opc/package.rb +97 -31
- data/lib/ruby_pptx/opc/serialized.rb +15 -5
- data/lib/ruby_pptx/oxml/backend.rb +585 -0
- data/lib/ruby_pptx/oxml/chart.rb +112 -42
- data/lib/ruby_pptx/oxml/content_model.rb +6 -2
- data/lib/ruby_pptx/oxml/dml/color.rb +6 -2
- data/lib/ruby_pptx/oxml/dml/fill.rb +6 -2
- data/lib/ruby_pptx/oxml/element.rb +138 -101
- data/lib/ruby_pptx/oxml/ns.rb +7 -7
- data/lib/ruby_pptx/oxml/presentation.rb +9 -3
- data/lib/ruby_pptx/oxml/section.rb +3 -1
- data/lib/ruby_pptx/oxml/shapes/autoshape.rb +39 -13
- data/lib/ruby_pptx/oxml/shapes/groupshape.rb +15 -7
- data/lib/ruby_pptx/oxml/shapes/other.rb +47 -16
- data/lib/ruby_pptx/oxml/shapes/shared.rb +96 -30
- data/lib/ruby_pptx/oxml/simple_types.rb +169 -52
- data/lib/ruby_pptx/oxml/slide.rb +24 -8
- data/lib/ruby_pptx/oxml/table.rb +39 -13
- data/lib/ruby_pptx/oxml/text.rb +37 -15
- data/lib/ruby_pptx/oxml/theme.rb +13 -4
- data/lib/ruby_pptx/package.rb +9 -3
- data/lib/ruby_pptx/parts/chart.rb +6 -2
- data/lib/ruby_pptx/parts/image.rb +12 -4
- data/lib/ruby_pptx/parts/media.rb +3 -1
- data/lib/ruby_pptx/parts/presentation.rb +15 -5
- data/lib/ruby_pptx/parts/slide.rb +33 -11
- data/lib/ruby_pptx/parts/theme.rb +3 -1
- data/lib/ruby_pptx/pattern_matching.rb +6 -2
- data/lib/ruby_pptx/presentation.rb +24 -8
- data/lib/ruby_pptx/section.rb +30 -10
- data/lib/ruby_pptx/shapes/adjustments.rb +9 -3
- data/lib/ruby_pptx/shapes/authoring.rb +3 -1
- data/lib/ruby_pptx/shapes/base.rb +74 -24
- data/lib/ruby_pptx/shapes/freeform.rb +36 -12
- data/lib/ruby_pptx/shapes/placeholder.rb +44 -15
- data/lib/ruby_pptx/shapes/shape.rb +91 -30
- data/lib/ruby_pptx/shapes/shape_tree.rb +66 -22
- data/lib/ruby_pptx/slide.rb +123 -41
- data/lib/ruby_pptx/table.rb +105 -35
- data/lib/ruby_pptx/text/font_metrics.rb +30 -9
- data/lib/ruby_pptx/text/text.rb +108 -36
- data/lib/ruby_pptx/theme.rb +30 -10
- data/lib/ruby_pptx/version.rb +1 -1
- data/lib/ruby_pptx.rb +8 -1
- metadata +22 -1
|
@@ -12,23 +12,33 @@ module Pptx
|
|
|
12
12
|
#
|
|
13
13
|
# Reached through the `format` of whatever it belongs to.
|
|
14
14
|
class ChartFormat < ElementProxy
|
|
15
|
-
def fill
|
|
15
|
+
def fill
|
|
16
|
+
@fill ||= FillFormat.from_fill_parent(@element.get_or_add_spPr)
|
|
17
|
+
end
|
|
16
18
|
|
|
17
|
-
def line
|
|
19
|
+
def line
|
|
20
|
+
@line ||= LineFormat.new(@element.get_or_add_spPr)
|
|
21
|
+
end
|
|
18
22
|
|
|
19
|
-
def inspect
|
|
23
|
+
def inspect
|
|
24
|
+
"#<Pptx::ChartFormat #{fill.type&.name}>"
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
# A chart's legend.
|
|
23
29
|
class ChartLegend < ElementProxy
|
|
24
30
|
# The legend's font, created on first use.
|
|
25
|
-
def font
|
|
31
|
+
def font
|
|
32
|
+
@font ||= Font.new(@element.defRPr)
|
|
33
|
+
end
|
|
26
34
|
|
|
27
35
|
# Where the legend sits. Absent from the file means PowerPoint's default,
|
|
28
36
|
# which is the right-hand side.
|
|
29
37
|
#
|
|
30
38
|
# @return [Pptx::Enum::Member] a member of XL_LEGEND_POSITION
|
|
31
|
-
def position
|
|
39
|
+
def position
|
|
40
|
+
@element.legendPos&.val || Enum::XL_LEGEND_POSITION::RIGHT
|
|
41
|
+
end
|
|
32
42
|
|
|
33
43
|
def position=(value)
|
|
34
44
|
@element.get_or_add_legendPos.val = Enum::XL_LEGEND_POSITION.fetch(value)
|
|
@@ -36,7 +46,9 @@ module Pptx
|
|
|
36
46
|
|
|
37
47
|
# How far the legend is shifted sideways, as a fraction of the chart
|
|
38
48
|
# width: -1.0 to 1.0, with 0.0 meaning PowerPoint places it.
|
|
39
|
-
def horz_offset
|
|
49
|
+
def horz_offset
|
|
50
|
+
@element.horz_offset
|
|
51
|
+
end
|
|
40
52
|
|
|
41
53
|
def horz_offset=(value)
|
|
42
54
|
@element.horz_offset = value
|
|
@@ -44,7 +56,9 @@ module Pptx
|
|
|
44
56
|
|
|
45
57
|
# True when the legend sits inside the plot area, overlapping it, rather
|
|
46
58
|
# than having space made for it. An absent `c:overlay` reads as true.
|
|
47
|
-
def include_in_layout?
|
|
59
|
+
def include_in_layout?
|
|
60
|
+
@element.overlay.nil? || @element.overlay.val
|
|
61
|
+
end
|
|
48
62
|
|
|
49
63
|
# nil removes the setting and returns to the default.
|
|
50
64
|
def include_in_layout=(value)
|
|
@@ -55,7 +69,9 @@ module Pptx
|
|
|
55
69
|
end
|
|
56
70
|
end
|
|
57
71
|
|
|
58
|
-
def inspect
|
|
72
|
+
def inspect
|
|
73
|
+
"#<Pptx::ChartLegend #{position.name}>"
|
|
74
|
+
end
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
# A chart or axis title.
|
|
@@ -64,37 +80,55 @@ module Pptx
|
|
|
64
80
|
# same way.
|
|
65
81
|
class ChartTitle < ElementProxy
|
|
66
82
|
# The title box's fill and outline.
|
|
67
|
-
def format
|
|
83
|
+
def format
|
|
84
|
+
@format ||= ChartFormat.new(@element)
|
|
85
|
+
end
|
|
68
86
|
|
|
69
87
|
# True when the title has text of its own rather than being generated.
|
|
70
|
-
def text_frame?
|
|
88
|
+
def text_frame?
|
|
89
|
+
!@element.rich.nil?
|
|
90
|
+
end
|
|
71
91
|
|
|
72
92
|
# The title's text, created on first use.
|
|
73
|
-
def text_frame
|
|
93
|
+
def text_frame
|
|
94
|
+
TextFrame.new(@element.get_or_add_rich, self)
|
|
95
|
+
end
|
|
74
96
|
|
|
75
97
|
# Titles are formatting, not content; there is no part to reach for.
|
|
76
|
-
def part
|
|
98
|
+
def part
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
77
101
|
|
|
78
|
-
def text
|
|
102
|
+
def text
|
|
103
|
+
text_frame? ? text_frame.text : ""
|
|
104
|
+
end
|
|
79
105
|
|
|
80
106
|
def text=(value)
|
|
81
107
|
text_frame.text = value
|
|
82
108
|
end
|
|
83
109
|
|
|
84
|
-
def inspect
|
|
110
|
+
def inspect
|
|
111
|
+
"#<Pptx::ChartTitle #{text.inspect}>"
|
|
112
|
+
end
|
|
85
113
|
end
|
|
86
114
|
|
|
87
115
|
# The major gridlines of an axis.
|
|
88
116
|
class Gridlines < ElementProxy
|
|
89
|
-
def format
|
|
117
|
+
def format
|
|
118
|
+
@format ||= ChartFormat.new(@element.get_or_add_majorGridlines)
|
|
119
|
+
end
|
|
90
120
|
end
|
|
91
121
|
|
|
92
122
|
# The labels along an axis: their font, number format and spacing.
|
|
93
123
|
class TickLabels < ElementProxy
|
|
94
|
-
def font
|
|
124
|
+
def font
|
|
125
|
+
@font ||= Font.new(@element.defRPr)
|
|
126
|
+
end
|
|
95
127
|
|
|
96
128
|
# The Excel number format, "General" when none is set.
|
|
97
|
-
def number_format
|
|
129
|
+
def number_format
|
|
130
|
+
@element.numFmt&.formatCode || "General"
|
|
131
|
+
end
|
|
98
132
|
|
|
99
133
|
# Setting a format stops it following the source data's format.
|
|
100
134
|
def number_format=(value)
|
|
@@ -116,7 +150,9 @@ module Pptx
|
|
|
116
150
|
|
|
117
151
|
# Distance of the labels from the axis as a percentage of the default;
|
|
118
152
|
# 100 is the default. Only a category axis has one.
|
|
119
|
-
def offset
|
|
153
|
+
def offset
|
|
154
|
+
@element.respond_to?(:lblOffset) ? (@element.lblOffset&.val || 100) : 100
|
|
155
|
+
end
|
|
120
156
|
|
|
121
157
|
def offset=(value)
|
|
122
158
|
raise Error, "only a category axis has a label offset" unless @element.nsptag == "c:catAx"
|
|
@@ -132,13 +168,17 @@ module Pptx
|
|
|
132
168
|
# only they have.
|
|
133
169
|
class ChartAxis < ElementProxy
|
|
134
170
|
# The axis line and its fill.
|
|
135
|
-
def format
|
|
171
|
+
def format
|
|
172
|
+
@format ||= ChartFormat.new(@element)
|
|
173
|
+
end
|
|
136
174
|
|
|
137
175
|
# Whether the axis is drawn. A `c:delete` of true hides it.
|
|
138
176
|
#
|
|
139
177
|
# An axis with no `c:delete` at all is drawn, which is what the schema and
|
|
140
178
|
# PowerPoint say. python-pptx reports it as hidden; see PORTING.md.
|
|
141
|
-
def visible?
|
|
179
|
+
def visible?
|
|
180
|
+
@element.delete.nil? || !@element.delete.val
|
|
181
|
+
end
|
|
142
182
|
|
|
143
183
|
def visible=(value)
|
|
144
184
|
unless [true, false].include?(value)
|
|
@@ -148,50 +188,66 @@ module Pptx
|
|
|
148
188
|
@element.get_or_add_delete.val = !value
|
|
149
189
|
end
|
|
150
190
|
|
|
151
|
-
def major_gridlines?
|
|
191
|
+
def major_gridlines?
|
|
192
|
+
!@element.majorGridlines.nil?
|
|
193
|
+
end
|
|
152
194
|
|
|
153
195
|
def major_gridlines=(value)
|
|
154
196
|
value ? @element.get_or_add_majorGridlines : @element.remove_majorGridlines
|
|
155
197
|
end
|
|
156
198
|
|
|
157
199
|
# The major gridlines, for formatting. Asking for them switches them on.
|
|
158
|
-
def major_gridlines
|
|
200
|
+
def major_gridlines
|
|
201
|
+
@major_gridlines ||= Gridlines.new(@element)
|
|
202
|
+
end
|
|
159
203
|
|
|
160
|
-
def minor_gridlines?
|
|
204
|
+
def minor_gridlines?
|
|
205
|
+
!@element.minorGridlines.nil?
|
|
206
|
+
end
|
|
161
207
|
|
|
162
208
|
def minor_gridlines=(value)
|
|
163
209
|
value ? @element.get_or_add_minorGridlines : @element.remove_minorGridlines
|
|
164
210
|
end
|
|
165
211
|
|
|
166
212
|
# @return [Pptx::Enum::Member] a member of XL_TICK_MARK
|
|
167
|
-
def major_tick_mark
|
|
213
|
+
def major_tick_mark
|
|
214
|
+
@element.majorTickMark&.val || Enum::XL_TICK_MARK::CROSS
|
|
215
|
+
end
|
|
168
216
|
|
|
169
217
|
# The default, cross, is written by leaving the element out.
|
|
170
218
|
def major_tick_mark=(value)
|
|
171
219
|
set_tick_mark(:majorTickMark, value)
|
|
172
220
|
end
|
|
173
221
|
|
|
174
|
-
def minor_tick_mark
|
|
222
|
+
def minor_tick_mark
|
|
223
|
+
@element.minorTickMark&.val || Enum::XL_TICK_MARK::CROSS
|
|
224
|
+
end
|
|
175
225
|
|
|
176
226
|
def minor_tick_mark=(value)
|
|
177
227
|
set_tick_mark(:minorTickMark, value)
|
|
178
228
|
end
|
|
179
229
|
|
|
180
230
|
# The fixed end of the scale, or nil when PowerPoint scales automatically.
|
|
181
|
-
def maximum_scale
|
|
231
|
+
def maximum_scale
|
|
232
|
+
@element.scaling.maximum
|
|
233
|
+
end
|
|
182
234
|
|
|
183
235
|
def maximum_scale=(value)
|
|
184
236
|
@element.scaling.maximum = value
|
|
185
237
|
end
|
|
186
238
|
|
|
187
|
-
def minimum_scale
|
|
239
|
+
def minimum_scale
|
|
240
|
+
@element.scaling.minimum
|
|
241
|
+
end
|
|
188
242
|
|
|
189
243
|
def minimum_scale=(value)
|
|
190
244
|
@element.scaling.minimum = value
|
|
191
245
|
end
|
|
192
246
|
|
|
193
247
|
# True when the axis runs from its maximum to its minimum.
|
|
194
|
-
def reverse_order?
|
|
248
|
+
def reverse_order?
|
|
249
|
+
@element.orientation == Oxml::SimpleTypes::ST_Orientation::MAX_MIN
|
|
250
|
+
end
|
|
195
251
|
|
|
196
252
|
def reverse_order=(value)
|
|
197
253
|
@element.orientation = if value
|
|
@@ -211,17 +267,23 @@ module Pptx
|
|
|
211
267
|
end
|
|
212
268
|
|
|
213
269
|
# The labels along the axis.
|
|
214
|
-
def tick_labels
|
|
270
|
+
def tick_labels
|
|
271
|
+
@tick_labels ||= TickLabels.new(@element)
|
|
272
|
+
end
|
|
215
273
|
|
|
216
274
|
# Shortcuts for the tick-label number format, the setting most often
|
|
217
275
|
# wanted from an axis.
|
|
218
|
-
def number_format
|
|
276
|
+
def number_format
|
|
277
|
+
tick_labels.number_format
|
|
278
|
+
end
|
|
219
279
|
|
|
220
280
|
def number_format=(value)
|
|
221
281
|
tick_labels.number_format = value
|
|
222
282
|
end
|
|
223
283
|
|
|
224
|
-
def title?
|
|
284
|
+
def title?
|
|
285
|
+
!@element.title.nil?
|
|
286
|
+
end
|
|
225
287
|
|
|
226
288
|
# @return [ChartTitle, nil] nil when the axis has no title
|
|
227
289
|
def title
|
|
@@ -239,7 +301,9 @@ module Pptx
|
|
|
239
301
|
end
|
|
240
302
|
end
|
|
241
303
|
|
|
242
|
-
def inspect
|
|
304
|
+
def inspect
|
|
305
|
+
"#<#{self.class.name} visible=#{visible?}>"
|
|
306
|
+
end
|
|
243
307
|
|
|
244
308
|
private
|
|
245
309
|
|
|
@@ -254,12 +318,16 @@ module Pptx
|
|
|
254
318
|
|
|
255
319
|
# The horizontal axis of most charts: one label per category.
|
|
256
320
|
class CategoryAxis < ChartAxis
|
|
257
|
-
def category_type
|
|
321
|
+
def category_type
|
|
322
|
+
Enum::XL_CATEGORY_TYPE::CATEGORY_SCALE
|
|
323
|
+
end
|
|
258
324
|
end
|
|
259
325
|
|
|
260
326
|
# A category axis whose categories are dates.
|
|
261
327
|
class DateAxis < ChartAxis
|
|
262
|
-
def category_type
|
|
328
|
+
def category_type
|
|
329
|
+
Enum::XL_CATEGORY_TYPE::TIME_SCALE
|
|
330
|
+
end
|
|
263
331
|
end
|
|
264
332
|
|
|
265
333
|
# An axis measuring values. An XY or bubble chart has two.
|
|
@@ -270,7 +338,9 @@ module Pptx
|
|
|
270
338
|
#
|
|
271
339
|
# @return [Pptx::Enum::Member] a member of XL_AXIS_CROSSES; CUSTOM when a
|
|
272
340
|
# specific value is set through {#crosses_at}
|
|
273
|
-
def crosses
|
|
341
|
+
def crosses
|
|
342
|
+
cross_axis.crosses&.val || Enum::XL_AXIS_CROSSES::CUSTOM
|
|
343
|
+
end
|
|
274
344
|
|
|
275
345
|
def crosses=(value)
|
|
276
346
|
member = Enum::XL_AXIS_CROSSES.fetch(value)
|
|
@@ -287,7 +357,9 @@ module Pptx
|
|
|
287
357
|
end
|
|
288
358
|
|
|
289
359
|
# The value on this axis at which the other crosses, or nil.
|
|
290
|
-
def crosses_at
|
|
360
|
+
def crosses_at
|
|
361
|
+
cross_axis.crossesAt&.val
|
|
362
|
+
end
|
|
291
363
|
|
|
292
364
|
def crosses_at=(value)
|
|
293
365
|
axis = cross_axis
|
|
@@ -297,14 +369,18 @@ module Pptx
|
|
|
297
369
|
end
|
|
298
370
|
|
|
299
371
|
# The distance between major tick marks, or nil when automatic.
|
|
300
|
-
def major_unit
|
|
372
|
+
def major_unit
|
|
373
|
+
@element.majorUnit&.val
|
|
374
|
+
end
|
|
301
375
|
|
|
302
376
|
def major_unit=(value)
|
|
303
377
|
@element.remove_majorUnit
|
|
304
378
|
@element.get_or_add_majorUnit.val = value unless value.nil?
|
|
305
379
|
end
|
|
306
380
|
|
|
307
|
-
def minor_unit
|
|
381
|
+
def minor_unit
|
|
382
|
+
@element.minorUnit&.val
|
|
383
|
+
end
|
|
308
384
|
|
|
309
385
|
def minor_unit=(value)
|
|
310
386
|
@element.remove_minorUnit
|
|
@@ -316,7 +392,10 @@ module Pptx
|
|
|
316
392
|
# The axis whose `c:axId` this one names in its `c:crossAx`.
|
|
317
393
|
def cross_axis
|
|
318
394
|
id = @element.crossAx.val
|
|
319
|
-
|
|
395
|
+
# A union of whole paths rather than `(a | b)/c`: the same query, but
|
|
396
|
+
# REXML's XPath does not accept a union as a path step.
|
|
397
|
+
query = %w[c:catAx c:valAx c:dateAx].map { |axis| "../#{axis}/c:axId[@val=\"#{id}\"]" }.join(" | ")
|
|
398
|
+
@element.xpath(query).first.parent
|
|
320
399
|
end
|
|
321
400
|
end
|
|
322
401
|
|
|
@@ -344,10 +423,14 @@ module Pptx
|
|
|
344
423
|
end
|
|
345
424
|
end
|
|
346
425
|
|
|
347
|
-
def font
|
|
426
|
+
def font
|
|
427
|
+
@font ||= Font.new(@element.defRPr)
|
|
428
|
+
end
|
|
348
429
|
|
|
349
430
|
# The Excel number format, "General" when none is set.
|
|
350
|
-
def number_format
|
|
431
|
+
def number_format
|
|
432
|
+
@element.numFmt&.formatCode || "General"
|
|
433
|
+
end
|
|
351
434
|
|
|
352
435
|
def number_format=(value)
|
|
353
436
|
@element.get_or_add_numFmt.formatCode = value
|
|
@@ -366,7 +449,9 @@ module Pptx
|
|
|
366
449
|
end
|
|
367
450
|
|
|
368
451
|
# @return [Pptx::Enum::Member, nil] a member of XL_DATA_LABEL_POSITION
|
|
369
|
-
def position
|
|
452
|
+
def position
|
|
453
|
+
@element.dLblPos&.val
|
|
454
|
+
end
|
|
370
455
|
|
|
371
456
|
def position=(value)
|
|
372
457
|
if value.nil?
|
|
@@ -376,7 +461,9 @@ module Pptx
|
|
|
376
461
|
end
|
|
377
462
|
end
|
|
378
463
|
|
|
379
|
-
def inspect
|
|
464
|
+
def inspect
|
|
465
|
+
"#<Pptx::ChartDataLabels value=#{show_value?}>"
|
|
466
|
+
end
|
|
380
467
|
end
|
|
381
468
|
|
|
382
469
|
# The label of a single data point, overriding the series' labels for it.
|
|
@@ -386,19 +473,29 @@ module Pptx
|
|
|
386
473
|
@idx = idx
|
|
387
474
|
end
|
|
388
475
|
|
|
389
|
-
def font
|
|
476
|
+
def font
|
|
477
|
+
@font ||= TextFrame.new(label_element.get_or_add_txPr, self).paragraphs[0].font
|
|
478
|
+
end
|
|
390
479
|
|
|
391
480
|
# True when the label has text of its own rather than a generated value.
|
|
392
|
-
def text_frame?
|
|
481
|
+
def text_frame?
|
|
482
|
+
!@ser.dLbl_for_point(@idx)&.rich.nil?
|
|
483
|
+
end
|
|
393
484
|
|
|
394
485
|
# The label's own text, replacing the generated value. Created on use.
|
|
395
|
-
def text_frame
|
|
486
|
+
def text_frame
|
|
487
|
+
TextFrame.new(label_element.get_or_add_rich, self)
|
|
488
|
+
end
|
|
396
489
|
|
|
397
490
|
# Labels are formatting, not content; there is no part to reach for.
|
|
398
|
-
def part
|
|
491
|
+
def part
|
|
492
|
+
nil
|
|
493
|
+
end
|
|
399
494
|
|
|
400
495
|
# @return [Pptx::Enum::Member, nil] a member of XL_DATA_LABEL_POSITION
|
|
401
|
-
def position
|
|
496
|
+
def position
|
|
497
|
+
@ser.dLbl_for_point(@idx)&.dLblPos&.val
|
|
498
|
+
end
|
|
402
499
|
|
|
403
500
|
def position=(value)
|
|
404
501
|
if value.nil?
|
|
@@ -408,21 +505,29 @@ module Pptx
|
|
|
408
505
|
end
|
|
409
506
|
end
|
|
410
507
|
|
|
411
|
-
def inspect
|
|
508
|
+
def inspect
|
|
509
|
+
"#<Pptx::DataLabel point=#{@idx}>"
|
|
510
|
+
end
|
|
412
511
|
|
|
413
512
|
private
|
|
414
513
|
|
|
415
514
|
# This point's `c:dLbl`, created on first use.
|
|
416
|
-
def label_element
|
|
515
|
+
def label_element
|
|
516
|
+
@ser.get_or_add_dLbl_for_point(@idx)
|
|
517
|
+
end
|
|
417
518
|
end
|
|
418
519
|
|
|
419
520
|
# The symbol drawn at each point of a line, radar or XY series, or at one
|
|
420
521
|
# point.
|
|
421
522
|
class Marker < ElementProxy
|
|
422
|
-
def format
|
|
523
|
+
def format
|
|
524
|
+
@format ||= ChartFormat.new(@element.get_or_add_marker)
|
|
525
|
+
end
|
|
423
526
|
|
|
424
527
|
# Size in points, 2 to 72, or nil when inherited.
|
|
425
|
-
def size
|
|
528
|
+
def size
|
|
529
|
+
@element.marker&.size&.val
|
|
530
|
+
end
|
|
426
531
|
|
|
427
532
|
def size=(value)
|
|
428
533
|
marker = @element.get_or_add_marker
|
|
@@ -431,7 +536,9 @@ module Pptx
|
|
|
431
536
|
end
|
|
432
537
|
|
|
433
538
|
# @return [Pptx::Enum::Member, nil] a member of XL_MARKER_STYLE
|
|
434
|
-
def style
|
|
539
|
+
def style
|
|
540
|
+
@element.marker&.symbol&.val
|
|
541
|
+
end
|
|
435
542
|
|
|
436
543
|
def style=(value)
|
|
437
544
|
marker = @element.get_or_add_marker
|
|
@@ -447,13 +554,21 @@ module Pptx
|
|
|
447
554
|
@idx = idx
|
|
448
555
|
end
|
|
449
556
|
|
|
450
|
-
def data_label
|
|
557
|
+
def data_label
|
|
558
|
+
@data_label ||= DataLabel.new(@ser, @idx)
|
|
559
|
+
end
|
|
451
560
|
|
|
452
|
-
def format
|
|
561
|
+
def format
|
|
562
|
+
@format ||= ChartFormat.new(@ser.get_or_add_dPt_for_point(@idx))
|
|
563
|
+
end
|
|
453
564
|
|
|
454
|
-
def marker
|
|
565
|
+
def marker
|
|
566
|
+
@marker ||= Marker.new(@ser.get_or_add_dPt_for_point(@idx))
|
|
567
|
+
end
|
|
455
568
|
|
|
456
|
-
def inspect
|
|
569
|
+
def inspect
|
|
570
|
+
"#<Pptx::ChartPoint #{@idx}>"
|
|
571
|
+
end
|
|
457
572
|
end
|
|
458
573
|
|
|
459
574
|
# The points of a series, indexed from 0.
|
|
@@ -466,7 +581,9 @@ module Pptx
|
|
|
466
581
|
@count = count
|
|
467
582
|
end
|
|
468
583
|
|
|
469
|
-
def size
|
|
584
|
+
def size
|
|
585
|
+
@count
|
|
586
|
+
end
|
|
470
587
|
alias length size
|
|
471
588
|
|
|
472
589
|
def [](index, length = nil)
|
|
@@ -480,7 +597,9 @@ module Pptx
|
|
|
480
597
|
self
|
|
481
598
|
end
|
|
482
599
|
|
|
483
|
-
def inspect
|
|
600
|
+
def inspect
|
|
601
|
+
"#<Pptx::ChartPoints size=#{size}>"
|
|
602
|
+
end
|
|
484
603
|
end
|
|
485
604
|
|
|
486
605
|
# One plot -- a "chart group" in the MS API -- within a chart.
|
|
@@ -496,13 +615,19 @@ module Pptx
|
|
|
496
615
|
end
|
|
497
616
|
|
|
498
617
|
# The categories this plot's series are plotted against.
|
|
499
|
-
def categories
|
|
618
|
+
def categories
|
|
619
|
+
ChartCategories.new(@element)
|
|
620
|
+
end
|
|
500
621
|
|
|
501
622
|
# This plot's series, in the order the chart draws them.
|
|
502
|
-
def series
|
|
623
|
+
def series
|
|
624
|
+
@element.sers.map { |ser| ChartSeriesView.for(ser, @chart) }
|
|
625
|
+
end
|
|
503
626
|
|
|
504
627
|
# The space between bars, as a percentage of bar width.
|
|
505
|
-
def gap_width
|
|
628
|
+
def gap_width
|
|
629
|
+
@element.gapWidth&.val || 150
|
|
630
|
+
end
|
|
506
631
|
|
|
507
632
|
def gap_width=(value)
|
|
508
633
|
@element.get_or_add_gapWidth.val = value
|
|
@@ -510,7 +635,9 @@ module Pptx
|
|
|
510
635
|
|
|
511
636
|
# How far bars in a group overlap, -100 to 100. Zero is written by
|
|
512
637
|
# leaving the element out.
|
|
513
|
-
def overlap
|
|
638
|
+
def overlap
|
|
639
|
+
@element.overlap&.val || 0
|
|
640
|
+
end
|
|
514
641
|
|
|
515
642
|
def overlap=(value)
|
|
516
643
|
if value.zero?
|
|
@@ -521,7 +648,9 @@ module Pptx
|
|
|
521
648
|
end
|
|
522
649
|
|
|
523
650
|
# The bubble size as a percentage of the default, 0 to 300.
|
|
524
|
-
def bubble_scale
|
|
651
|
+
def bubble_scale
|
|
652
|
+
@element.bubbleScale&.val || 100
|
|
653
|
+
end
|
|
525
654
|
|
|
526
655
|
# nil returns to the default.
|
|
527
656
|
def bubble_scale=(value)
|
|
@@ -531,14 +660,18 @@ module Pptx
|
|
|
531
660
|
|
|
532
661
|
# Whether each data point gets its own colour, as a pie does. An absent
|
|
533
662
|
# `c:varyColors` reads as true, the schema default.
|
|
534
|
-
def vary_by_categories?
|
|
663
|
+
def vary_by_categories?
|
|
664
|
+
@element.varyColors.nil? || @element.varyColors.val
|
|
665
|
+
end
|
|
535
666
|
|
|
536
667
|
def vary_by_categories=(value)
|
|
537
668
|
@element.get_or_add_varyColors.val = value ? true : false
|
|
538
669
|
end
|
|
539
670
|
|
|
540
671
|
# Whether this plot shows data labels at all.
|
|
541
|
-
def data_labels?
|
|
672
|
+
def data_labels?
|
|
673
|
+
!@element.dLbls.nil?
|
|
674
|
+
end
|
|
542
675
|
|
|
543
676
|
# Switching labels on shows values, as PowerPoint's default does.
|
|
544
677
|
def data_labels=(value)
|
|
@@ -553,9 +686,13 @@ module Pptx
|
|
|
553
686
|
# The data-label settings, switched on with PowerPoint's defaults if the
|
|
554
687
|
# plot has none yet. python-pptx makes you set `has_data_labels` first;
|
|
555
688
|
# asking for them is enough here.
|
|
556
|
-
def data_labels
|
|
689
|
+
def data_labels
|
|
690
|
+
@data_labels ||= ChartDataLabels.new(@element.get_or_add_default_dLbls)
|
|
691
|
+
end
|
|
557
692
|
|
|
558
|
-
def inspect
|
|
693
|
+
def inspect
|
|
694
|
+
"#<Pptx::ChartPlot #{@element.nsptag}>"
|
|
695
|
+
end
|
|
559
696
|
end
|
|
560
697
|
|
|
561
698
|
# The categories of a plot, read back from the chart's cached values.
|
|
@@ -577,9 +714,13 @@ module Pptx
|
|
|
577
714
|
self
|
|
578
715
|
end
|
|
579
716
|
|
|
580
|
-
def [](index)
|
|
717
|
+
def [](index)
|
|
718
|
+
to_a[index]
|
|
719
|
+
end
|
|
581
720
|
|
|
582
|
-
def size
|
|
721
|
+
def size
|
|
722
|
+
@plot.cat_pt_count
|
|
723
|
+
end
|
|
583
724
|
alias length size
|
|
584
725
|
|
|
585
726
|
# How many levels of labels there are: 0 with no categories, 1 for a
|
|
@@ -610,7 +751,9 @@ module Pptx
|
|
|
610
751
|
leaf.map { |category| lineage(category, parents).reverse.map(&:label) }
|
|
611
752
|
end
|
|
612
753
|
|
|
613
|
-
def inspect
|
|
754
|
+
def inspect
|
|
755
|
+
"#<Pptx::ChartCategories #{map(&:label).inspect}>"
|
|
756
|
+
end
|
|
614
757
|
|
|
615
758
|
private
|
|
616
759
|
|
|
@@ -633,15 +776,25 @@ module Pptx
|
|
|
633
776
|
end
|
|
634
777
|
|
|
635
778
|
# The label, "" for an empty category.
|
|
636
|
-
def label
|
|
779
|
+
def label
|
|
780
|
+
@point.nil? ? "" : @point.v.text
|
|
781
|
+
end
|
|
637
782
|
|
|
638
|
-
def idx
|
|
783
|
+
def idx
|
|
784
|
+
@point.nil? ? @idx : @point.idx
|
|
785
|
+
end
|
|
639
786
|
|
|
640
|
-
def to_s
|
|
787
|
+
def to_s
|
|
788
|
+
label
|
|
789
|
+
end
|
|
641
790
|
alias to_str to_s
|
|
642
791
|
|
|
643
|
-
def ==(other)
|
|
792
|
+
def ==(other)
|
|
793
|
+
other.is_a?(ChartCategory) ? label == other.label && idx == other.idx : label == other
|
|
794
|
+
end
|
|
644
795
|
|
|
645
|
-
def inspect
|
|
796
|
+
def inspect
|
|
797
|
+
"#<Pptx::ChartCategory #{idx}:#{label.inspect}>"
|
|
798
|
+
end
|
|
646
799
|
end
|
|
647
800
|
end
|
|
@@ -64,9 +64,13 @@ module Pptx
|
|
|
64
64
|
# Only date categories need a cell style -- a number format that makes
|
|
65
65
|
# the serial numbers read as dates -- so only they get a styles part.
|
|
66
66
|
# XY and bubble data have no categories, so never dates.
|
|
67
|
-
def dates?
|
|
67
|
+
def dates?
|
|
68
|
+
@chart_data.respond_to?(:categories) && @chart_data.categories.dates?
|
|
69
|
+
end
|
|
68
70
|
|
|
69
|
-
def declaration
|
|
71
|
+
def declaration
|
|
72
|
+
%(<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n)
|
|
73
|
+
end
|
|
70
74
|
|
|
71
75
|
def content_types_xml
|
|
72
76
|
<<~XML
|
|
@@ -132,7 +136,9 @@ module Pptx
|
|
|
132
136
|
end.join
|
|
133
137
|
end
|
|
134
138
|
|
|
135
|
-
def depth
|
|
139
|
+
def depth
|
|
140
|
+
@chart_data.categories.depth
|
|
141
|
+
end
|
|
136
142
|
|
|
137
143
|
def category_cells(rows)
|
|
138
144
|
@chart_data.categories.levels.each_with_index do |level, level_index|
|