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
data/lib/ruby_pptx/oxml/chart.rb
CHANGED
|
@@ -174,9 +174,13 @@ module Pptx
|
|
|
174
174
|
# Anything carrying a `c:txPr`, which is where a chart element's font
|
|
175
175
|
# lives. The text body is created on first use.
|
|
176
176
|
module ChartTextProperties
|
|
177
|
-
def defRPr
|
|
177
|
+
def defRPr
|
|
178
|
+
get_or_add_txPr.defRPr
|
|
179
|
+
end
|
|
178
180
|
|
|
179
|
-
def new_txPr
|
|
181
|
+
def new_txPr
|
|
182
|
+
build_from_xml(CT_TextBody::TXPR_XML)
|
|
183
|
+
end
|
|
180
184
|
end
|
|
181
185
|
|
|
182
186
|
# `c:layout`, holding an optional manual layout.
|
|
@@ -186,7 +190,9 @@ module Pptx
|
|
|
186
190
|
|
|
187
191
|
# The horizontal offset as a fraction of the chart width; 0.0 when the
|
|
188
192
|
# position is automatic.
|
|
189
|
-
def horz_offset
|
|
193
|
+
def horz_offset
|
|
194
|
+
manualLayout&.horz_offset || 0.0
|
|
195
|
+
end
|
|
190
196
|
|
|
191
197
|
# Setting 0.0 hands the position back to PowerPoint.
|
|
192
198
|
def horz_offset=(offset)
|
|
@@ -238,7 +244,9 @@ module Pptx
|
|
|
238
244
|
</c:rich>
|
|
239
245
|
XML
|
|
240
246
|
|
|
241
|
-
def new_rich
|
|
247
|
+
def new_rich
|
|
248
|
+
build_from_xml(RICH_XML)
|
|
249
|
+
end
|
|
242
250
|
end
|
|
243
251
|
|
|
244
252
|
# `c:title`, the chart or axis title.
|
|
@@ -261,7 +269,9 @@ module Pptx
|
|
|
261
269
|
end
|
|
262
270
|
|
|
263
271
|
# The rich-text body, or nil when the title has none.
|
|
264
|
-
def rich
|
|
272
|
+
def rich
|
|
273
|
+
xpath("./c:tx/c:rich").first
|
|
274
|
+
end
|
|
265
275
|
|
|
266
276
|
# A title takes rich text or a cell reference, never both.
|
|
267
277
|
def get_or_add_rich
|
|
@@ -290,14 +300,18 @@ module Pptx
|
|
|
290
300
|
zero_or_one "c:min", successors: %w[c:extLst]
|
|
291
301
|
|
|
292
302
|
# nil means "auto", which is what an absent element says.
|
|
293
|
-
def maximum
|
|
303
|
+
def maximum
|
|
304
|
+
max&.val
|
|
305
|
+
end
|
|
294
306
|
|
|
295
307
|
def maximum=(value)
|
|
296
308
|
remove_max
|
|
297
309
|
get_or_add_max.val = value unless value.nil?
|
|
298
310
|
end
|
|
299
311
|
|
|
300
|
-
def minimum
|
|
312
|
+
def minimum
|
|
313
|
+
min&.val
|
|
314
|
+
end
|
|
301
315
|
|
|
302
316
|
def minimum=(value)
|
|
303
317
|
remove_min
|
|
@@ -330,7 +344,9 @@ module Pptx
|
|
|
330
344
|
end
|
|
331
345
|
end
|
|
332
346
|
|
|
333
|
-
def orientation
|
|
347
|
+
def orientation
|
|
348
|
+
scaling.orientation&.val || SimpleTypes::ST_Orientation::MIN_MAX
|
|
349
|
+
end
|
|
334
350
|
|
|
335
351
|
# Only a reversed axis is written; the normal direction is the default.
|
|
336
352
|
def orientation=(value)
|
|
@@ -340,7 +356,9 @@ module Pptx
|
|
|
340
356
|
scaling.get_or_add_orientation.val = value
|
|
341
357
|
end
|
|
342
358
|
|
|
343
|
-
def new_title
|
|
359
|
+
def new_title
|
|
360
|
+
CT_Title.new_title(self)
|
|
361
|
+
end
|
|
344
362
|
end
|
|
345
363
|
|
|
346
364
|
COMMON_AXIS_SEQ = %w[c:axId c:scaling c:delete c:axPos c:majorGridlines c:minorGridlines
|
|
@@ -391,7 +409,9 @@ module Pptx
|
|
|
391
409
|
zero_or_one "c:overlay", successors: TAG_SEQ[4..]
|
|
392
410
|
zero_or_one "c:txPr", successors: TAG_SEQ[6..]
|
|
393
411
|
|
|
394
|
-
def horz_offset
|
|
412
|
+
def horz_offset
|
|
413
|
+
layout&.horz_offset || 0.0
|
|
414
|
+
end
|
|
395
415
|
|
|
396
416
|
def horz_offset=(offset)
|
|
397
417
|
get_or_add_layout.horz_offset = offset
|
|
@@ -437,7 +457,9 @@ module Pptx
|
|
|
437
457
|
</c:dLbls>
|
|
438
458
|
XML
|
|
439
459
|
|
|
440
|
-
def self.new_data_labels(context)
|
|
460
|
+
def self.new_data_labels(context)
|
|
461
|
+
context.build_from_xml(DEFAULT_XML)
|
|
462
|
+
end
|
|
441
463
|
|
|
442
464
|
# A flag added on its own starts off, as PowerPoint writes them.
|
|
443
465
|
%w[showLegendKey showVal showCatName showSerName showPercent].each do |flag|
|
|
@@ -445,7 +467,9 @@ module Pptx
|
|
|
445
467
|
end
|
|
446
468
|
|
|
447
469
|
# The label for the point at +idx+, or nil if it has none of its own.
|
|
448
|
-
def dLbl_for_point(idx)
|
|
470
|
+
def dLbl_for_point(idx)
|
|
471
|
+
dLbl_list.find { |label| label.idx.val == idx }
|
|
472
|
+
end
|
|
449
473
|
|
|
450
474
|
# The label for the point at +idx+, created in index order if absent.
|
|
451
475
|
def get_or_add_dLbl_for_point(idx)
|
|
@@ -459,11 +483,11 @@ module Pptx
|
|
|
459
483
|
label.idx.val = idx
|
|
460
484
|
following = dLbl_list.find { |existing| existing.idx.val > idx }
|
|
461
485
|
if following
|
|
462
|
-
following.
|
|
486
|
+
following.add_previous_sibling(label)
|
|
463
487
|
elsif (last = dLbl_list.last)
|
|
464
|
-
last.
|
|
488
|
+
last.add_next_sibling(label)
|
|
465
489
|
else
|
|
466
|
-
|
|
490
|
+
prepend(label)
|
|
467
491
|
end
|
|
468
492
|
label
|
|
469
493
|
end
|
|
@@ -506,7 +530,9 @@ module Pptx
|
|
|
506
530
|
</c:dLbl>
|
|
507
531
|
XML
|
|
508
532
|
|
|
509
|
-
def self.new_dLbl(context)
|
|
533
|
+
def self.new_dLbl(context)
|
|
534
|
+
context.build_from_xml(DEFAULT_XML)
|
|
535
|
+
end
|
|
510
536
|
|
|
511
537
|
# The label's own text replaces the generated one. A `c:spPr` or
|
|
512
538
|
# `c:txPr` alongside `c:tx` makes a bubble chart unsaveable in
|
|
@@ -519,7 +545,9 @@ module Pptx
|
|
|
519
545
|
tx.get_or_add_rich
|
|
520
546
|
end
|
|
521
547
|
|
|
522
|
-
def rich
|
|
548
|
+
def rich
|
|
549
|
+
xpath("./c:tx/c:rich").first
|
|
550
|
+
end
|
|
523
551
|
|
|
524
552
|
def remove_tx_rich
|
|
525
553
|
tx = xpath("./c:tx[c:rich]").first
|
|
@@ -580,13 +608,21 @@ module Pptx
|
|
|
580
608
|
zero_or_one "c:smooth", successors: TAG_SEQ[18..]
|
|
581
609
|
zero_or_one "c:bubbleSize", successors: TAG_SEQ[19..]
|
|
582
610
|
|
|
583
|
-
def index
|
|
611
|
+
def index
|
|
612
|
+
idx&.val.to_i
|
|
613
|
+
end
|
|
584
614
|
|
|
585
|
-
def name
|
|
615
|
+
def name
|
|
616
|
+
xpath("./c:tx//c:pt/c:v").first&.text.to_s
|
|
617
|
+
end
|
|
586
618
|
|
|
587
|
-
def new_dLbls
|
|
619
|
+
def new_dLbls
|
|
620
|
+
CT_DataLabels.new_data_labels(self)
|
|
621
|
+
end
|
|
588
622
|
|
|
589
|
-
def new_dPt
|
|
623
|
+
def new_dPt
|
|
624
|
+
CT_DPt.new_dPt(self)
|
|
625
|
+
end
|
|
590
626
|
|
|
591
627
|
%w[cat xVal yVal bubbleSize].each do |source|
|
|
592
628
|
define_method(:"#{source}_ptCount_val") do
|
|
@@ -595,9 +631,13 @@ module Pptx
|
|
|
595
631
|
end
|
|
596
632
|
|
|
597
633
|
# The label of the point at +idx+, or nil.
|
|
598
|
-
def dLbl_for_point(idx)
|
|
634
|
+
def dLbl_for_point(idx)
|
|
635
|
+
dLbls&.dLbl_for_point(idx)
|
|
636
|
+
end
|
|
599
637
|
|
|
600
|
-
def get_or_add_dLbl_for_point(idx)
|
|
638
|
+
def get_or_add_dLbl_for_point(idx)
|
|
639
|
+
get_or_add_dLbls.get_or_add_dLbl_for_point(idx)
|
|
640
|
+
end
|
|
601
641
|
|
|
602
642
|
# The formatting record for the point at +idx+, created if absent.
|
|
603
643
|
def get_or_add_dPt_for_point(idx)
|
|
@@ -612,7 +652,9 @@ module Pptx
|
|
|
612
652
|
zero_or_one "c:multiLvlStrRef", successors: []
|
|
613
653
|
|
|
614
654
|
# The levels of a multi-level category source, leaf level first.
|
|
615
|
-
def lvls
|
|
655
|
+
def lvls
|
|
656
|
+
xpath(".//c:lvl")
|
|
657
|
+
end
|
|
616
658
|
end
|
|
617
659
|
|
|
618
660
|
# `c:pt`, one cached value in a series source.
|
|
@@ -620,9 +662,13 @@ module Pptx
|
|
|
620
662
|
tag "c:pt"
|
|
621
663
|
required_attr "idx", type: SimpleTypes::XsdUnsignedInt
|
|
622
664
|
|
|
623
|
-
def v
|
|
665
|
+
def v
|
|
666
|
+
xpath("./c:v").first
|
|
667
|
+
end
|
|
624
668
|
|
|
625
|
-
def value
|
|
669
|
+
def value
|
|
670
|
+
Float(v.text)
|
|
671
|
+
end
|
|
626
672
|
end
|
|
627
673
|
|
|
628
674
|
# -------------------------------------------------------------------------
|
|
@@ -651,14 +697,22 @@ module Pptx
|
|
|
651
697
|
c:extLst]
|
|
652
698
|
|
|
653
699
|
# Series in document order.
|
|
654
|
-
def ser_list
|
|
700
|
+
def ser_list
|
|
701
|
+
find_all("c:ser")
|
|
702
|
+
end
|
|
655
703
|
|
|
656
704
|
# Series in the order the chart draws them, which is `c:order`.
|
|
657
|
-
def sers
|
|
705
|
+
def sers
|
|
706
|
+
ser_list.sort_by { |ser| ser.order&.val.to_i }
|
|
707
|
+
end
|
|
658
708
|
|
|
659
|
-
def grouping_val
|
|
709
|
+
def grouping_val
|
|
710
|
+
grouping&.val || SimpleTypes::ST_Grouping::STANDARD
|
|
711
|
+
end
|
|
660
712
|
|
|
661
|
-
def new_dLbls
|
|
713
|
+
def new_dLbls
|
|
714
|
+
CT_DataLabels.new_data_labels(self)
|
|
715
|
+
end
|
|
662
716
|
|
|
663
717
|
# The data-label settings, created with PowerPoint's defaults if the
|
|
664
718
|
# plot has none yet.
|
|
@@ -671,9 +725,13 @@ module Pptx
|
|
|
671
725
|
end
|
|
672
726
|
|
|
673
727
|
# The first series' category source, which the others share.
|
|
674
|
-
def cat
|
|
728
|
+
def cat
|
|
729
|
+
xpath("./c:ser[1]/c:cat").first
|
|
730
|
+
end
|
|
675
731
|
|
|
676
|
-
def cat_pt_count
|
|
732
|
+
def cat_pt_count
|
|
733
|
+
xpath("./c:ser//c:cat//c:ptCount").first&.val.to_i
|
|
734
|
+
end
|
|
677
735
|
|
|
678
736
|
# One entry per category, nil where the workbook cell is empty -- such
|
|
679
737
|
# a category has no `c:pt` but still counts in `c:ptCount`.
|
|
@@ -693,20 +751,26 @@ module Pptx
|
|
|
693
751
|
tag "c:plotArea"
|
|
694
752
|
|
|
695
753
|
def plot_elements
|
|
696
|
-
|
|
697
|
-
.select { |child| child.name.end_with?("Chart") }
|
|
698
|
-
.map { |child| Element.wrap(child) }
|
|
754
|
+
element_children.select { |child| child.clark_name.end_with?("Chart") }
|
|
699
755
|
end
|
|
700
756
|
|
|
701
|
-
def category_axis
|
|
757
|
+
def category_axis
|
|
758
|
+
find("c:catAx") || find("c:dateAx")
|
|
759
|
+
end
|
|
702
760
|
|
|
703
|
-
def value_axes
|
|
761
|
+
def value_axes
|
|
762
|
+
find_all("c:valAx")
|
|
763
|
+
end
|
|
704
764
|
|
|
705
765
|
# Every series in the chart, in plot order then series order -- which is
|
|
706
766
|
# the order their chart-wide indices follow.
|
|
707
|
-
def series_elements
|
|
767
|
+
def series_elements
|
|
768
|
+
plot_elements.flat_map(&:ser_list)
|
|
769
|
+
end
|
|
708
770
|
|
|
709
|
-
def last_plot_element
|
|
771
|
+
def last_plot_element
|
|
772
|
+
plot_elements.last
|
|
773
|
+
end
|
|
710
774
|
end
|
|
711
775
|
|
|
712
776
|
# `c:chart`, which OOXML uses for two different things under one tag name.
|
|
@@ -739,7 +803,9 @@ module Pptx
|
|
|
739
803
|
one_and_only_one "c:plotArea"
|
|
740
804
|
zero_or_one "c:legend", successors: TAG_SEQ[9..]
|
|
741
805
|
|
|
742
|
-
def new_title
|
|
806
|
+
def new_title
|
|
807
|
+
CT_Title.new_title(self)
|
|
808
|
+
end
|
|
743
809
|
end
|
|
744
810
|
|
|
745
811
|
# `c:chartSpace`, the root of a chart part.
|
|
@@ -759,14 +825,18 @@ module Pptx
|
|
|
759
825
|
|
|
760
826
|
# The relationship id of the embedded workbook, or nil when the chart
|
|
761
827
|
# has none.
|
|
762
|
-
def xlsx_part_rId
|
|
828
|
+
def xlsx_part_rId
|
|
829
|
+
externalData&.rId
|
|
830
|
+
end
|
|
763
831
|
|
|
764
832
|
# The plot element, e.g. `c:barChart`, that this chart draws with.
|
|
765
833
|
def plot_element
|
|
766
834
|
xpath("./c:chart/c:plotArea/*").find { |e| e.nsptag.end_with?("Chart") }
|
|
767
835
|
end
|
|
768
836
|
|
|
769
|
-
def series_elements
|
|
837
|
+
def series_elements
|
|
838
|
+
xpath("./c:chart/c:plotArea/*/c:ser")
|
|
839
|
+
end
|
|
770
840
|
end
|
|
771
841
|
|
|
772
842
|
# `c:externalData`, the link from a chart to its embedded workbook.
|
|
@@ -31,11 +31,15 @@ module Pptx
|
|
|
31
31
|
module ContentModel
|
|
32
32
|
# A member of an `EG_*` element group, for {#zero_or_one_choice}.
|
|
33
33
|
Choice = Data.define(:nsptag) do
|
|
34
|
-
def prop_name
|
|
34
|
+
def prop_name
|
|
35
|
+
Ns.split_tag(nsptag).last
|
|
36
|
+
end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
# Declare one member of a choice group.
|
|
38
|
-
def choice(nsptag)
|
|
40
|
+
def choice(nsptag)
|
|
41
|
+
Choice.new(nsptag)
|
|
42
|
+
end
|
|
39
43
|
|
|
40
44
|
# An attribute that may be absent. Reading returns +default+ when it is;
|
|
41
45
|
# assigning +default+ removes it, so a document never carries an
|
|
@@ -17,9 +17,13 @@ module Pptx
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def add_lumMod(value)
|
|
20
|
+
def add_lumMod(value)
|
|
21
|
+
add_lumMod_element(value)
|
|
22
|
+
end
|
|
21
23
|
|
|
22
|
-
def add_lumOff(value)
|
|
24
|
+
def add_lumOff(value)
|
|
25
|
+
add_lumOff_element(value)
|
|
26
|
+
end
|
|
23
27
|
|
|
24
28
|
# Remove any luminance adjustment, returning self.
|
|
25
29
|
def clear_lum
|
|
@@ -74,7 +74,9 @@ module Pptx
|
|
|
74
74
|
</a:gradFill>
|
|
75
75
|
XML
|
|
76
76
|
|
|
77
|
-
def self.new_grad_fill(context)
|
|
77
|
+
def self.new_grad_fill(context)
|
|
78
|
+
context.build_from_xml(DEFAULT_XML)
|
|
79
|
+
end
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
# `a:blip`, the image reference inside a picture fill.
|
|
@@ -100,7 +102,9 @@ module Pptx
|
|
|
100
102
|
end
|
|
101
103
|
|
|
102
104
|
# The relationship id of the SVG, or nil when this is a plain raster.
|
|
103
|
-
def svg_rId
|
|
105
|
+
def svg_rId
|
|
106
|
+
xpath("./a:extLst/a:ext/asvg:svgBlip/@r:embed").first&.value
|
|
107
|
+
end
|
|
104
108
|
end
|
|
105
109
|
|
|
106
110
|
# `a:extLst` as it appears on a blip.
|