问题
I tried to follow example as discussed in https://groups.google.com/forum/#!topic/python-pptx/nrUkiQQHyZo , however ended up with an error 'Slide' object has no attribute 'rels'
.
The minimal code I'm experimenting tries to build a hyperlink in first slide to third slide.
import pptx
import pptx.enum
from pptx import Presentation
from pptx.enum.action import PP_ACTION
from pptx.opc.constants import RELATIONSHIP_TYPE as RT
#very minimal Powerpoint template
prs = Presentation("tpl.pptx")
# create 3 slides, each with single text placeholder
s1 = prs.slides.add_slide(prs.slide_layouts[0])
s2 = prs.slides.add_slide(prs.slide_layouts[0])
s3 = prs.slides.add_slide(prs.slide_layouts[0])
# create internal hyperlink
rId = s1.part.relate_to(s3, RT.SLIDE)
r = s1.placeholders[10].text_frame.paragraphs[0].add_run()
r.text = "Link to Slide 3"
rPr = r._r.get_or_add_rPr()
hlinkClick = rPr.add_hlinkClick(rId)
hlinkClick.set('action', 'ppaction://hlinksldjump')
# ERROR WHEN SAVING - Slide' object has no attribute 'rels #
prs.save("Test.pptx")
How to resolve the error? Or perhaps, is there a simpler way to achieve this?
EDIT: Full Stack Trace
AttributeError Traceback (most recent call last)
<ipython-input-2-60361164c736> in <module>()
23
24 # ERROR WHEN SAVING - Slide' object has no attribute 'rels #
---> 25 prs.save("Test.pptx")
C:\Users\x\Anaconda3\lib\site-packages\pptx\presentation.py in save(self, file)
44 to a file (a string) or a file-like object.
45 """
---> 46 self.part.save(file)
47
48 @property
C:\Users\x\Anaconda3\lib\site-packages\pptx\parts\presentation.py in save(self, path_or_stream)
116 object.
117 """
--> 118 self.package.save(path_or_stream)
119
120 def slide_id(self, slide_part):
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in save(self, pkg_file)
162 a file (a string) or a file-like object.
163 """
--> 164 for part in self.parts:
165 part.before_marshal()
166 PackageWriter.write(pkg_file, self.rels, self.parts)
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in parts(self)
139 package.
140 """
--> 141 return [part for part in self.iter_parts()]
142
143 def relate_to(self, part, reltype):
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in <listcomp>(.0)
139 package.
140 """
--> 141 return [part for part in self.iter_parts()]
142
143 def relate_to(self, part, reltype):
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in iter_parts(self)
54 yield part
55
---> 56 for part in walk_parts(self):
57 yield part
58
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in walk_parts(source, visited)
51 yield part
52 new_source = part
---> 53 for part in walk_parts(new_source, visited):
54 yield part
55
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in walk_parts(source, visited)
51 yield part
52 new_source = part
---> 53 for part in walk_parts(new_source, visited):
54 yield part
55
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in walk_parts(source, visited)
51 yield part
52 new_source = part
---> 53 for part in walk_parts(new_source, visited):
54 yield part
55
C:\Users\x\Anaconda3\lib\site-packages\pptx\opc\package.py in walk_parts(source, visited)
42 """
43 def walk_parts(source, visited=list()):
---> 44 for rel in source.rels.values():
45 if rel.is_external:
46 continue
AttributeError: 'Slide' object has no attribute 'rels'
回答1:
As per comment by @scanny, changing s3 to s3.part works well.
# create internal hyperlink
rId = s1.part.relate_to(s3.part, RT.SLIDE)
r = s1.placeholders[10].text_frame.paragraphs[0].add_run()
r.text = "Link to Slide 3"
rPr = r._r.get_or_add_rPr()
回答2:
Putting together all the information already posted in this thread, here is a minimal example:
# Workaround for python-pptx lack of internal hyperlink support
from pptx.enum.action import PP_ACTION
from pptx.opc.constants import RELATIONSHIP_TYPE as RT
def Hyperlink( run_object, source_slide, destination_slide ):
rId = source_slide.part.relate_to(destination_slide.part, RT.SLIDE)
rPr = run_object._r.get_or_add_rPr()
hlinkClick = rPr.add_hlinkClick(rId)
hlinkClick.set('action', 'ppaction://hlinksldjump')
# Example of usage:
from pptx import Presentation
prs = Presentation()
slide = dict()
# Make Slides
title_slide_layout = prs.slide_layouts[0]
slide['title'] = prs.slides.add_slide( title_slide_layout )
title = slide['title'].shapes.title
title.text = 'Presentation with Internal Hyperlinks'
two_content_slide = prs.slide_layouts[3]
slide['table of contents'] = prs.slides.add_slide( two_content_slide )
shapes = slide['table of contents'].shapes
title = shapes.title
title.text = 'Table of contents'
two_content_slide = prs.slide_layouts[3]
slide['slide a'] = prs.slides.add_slide( two_content_slide )
shapes = slide['slide a'].shapes
title = shapes.title
title.text = 'Slide A'
two_content_slide = prs.slide_layouts[3]
slide['slide b'] = prs.slides.add_slide( two_content_slide )
shapes = slide['slide b'].shapes
title = shapes.title
title.text = 'Slide B'
# Populate contents (with hyperlinks)
shapes = slide['table of contents'].shapes
body = shapes.placeholders[1]
tf = body.text_frame
p = tf.add_paragraph()
r = p.add_run()
r.text = 'Slide A'
Hyperlink( r, slide['table of contents'], slide['slide a'] )
p = tf.add_paragraph()
r = p.add_run()
r.text = 'Slide B'
Hyperlink( r, slide['table of contents'], slide['slide b'] )
# Save as .pptx file
prs.save( 'hyperlink_slides.pptx' )
Hope this helps!
来源:https://stackoverflow.com/questions/44704555/python-pptx-internal-hyperlinks-workaround-function