我有一个PowerPoint,我想打开,修改,并保存为不同的文件名。但是,我得到了一个KeyError。
我用一个空白的PowerPoint演示文稿尝试了这段代码,它完美无缺。但是,当我使用代码打开现有的PowerPoint演示文稿并尝试运行相同的代码时,我得到一个KeyError。
KeyError:“存档中没有名为'ppt / slides / NULL'的项目”
#Replace Source Text
import re
#s = "string. With. Punctuation?"
#s = re.sub(r'[^\w\s]','',s)
search_str = '{{{FILTER}}}'
repl_str = re.sub(r'[^\w\s]','',(str(list(dashboard_filter2.values()))))
ppt = Presentation('HispPres1.pptx')
for slide in ppt.slides:
for shape in slide.shapes:
if shape.has_text_frame:
shape.text = shape.text.replace(search_str, repl_str)
ppt.save('HispPresSourceUpdate.pptx')
我希望通过查找{{{FILTER}}}的所有实例并将其替换为列出的值来修改现有的PowerPoint。但是,使用我现有的PowerPoint演示文稿时似乎存在问题。我没有这个问题的空白演示文稿。
所以,我想知道什么会导致现有的PowerPoint演示文稿引发错误???我计划开始制作几个“模板”,并且确实需要知道是否有任何坚固的规则要遵守。
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-42-41deffabe2f9> in <module>()
7 search_str = '{{{FILTER}}}'
8 repl_str = re.sub(r'[^\w\s]','',(str(list(dashboard_filter2.values()))))
----> 9 ppt = Presentation('HispPres1.pptx')
10
11 for slide in ppt.slides:
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\api.py in Presentation(pptx)
28 pptx = _default_pptx_path()
29
---> 30 presentation_part = Package.open(pptx).main_document_part
31
32 if not _is_pptx_package(presentation_part):
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\package.py in open(cls, pkg_file)
120 *pkg_file*.
121 """
--> 122 pkg_reader = PackageReader.from_file(pkg_file)
123 package = cls()
124 Unmarshaller.unmarshal(pkg_reader, package, PartFactory)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\pkgreader.py in from_file(pkg_file)
34 pkg_srels = PackageReader._srels_for(phys_reader, PACKAGE_URI)
35 sparts = PackageReader._load_serialized_parts(
---> 36 phys_reader, pkg_srels, content_types
37 )
38 phys_reader.close()
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\pkgreader.py in _load_serialized_parts(phys_reader, pkg_srels, content_types)
67 sparts = []
68 part_walker = PackageReader._walk_phys_parts(phys_reader, pkg_srels)
---> 69 for partname, blob, srels in part_walker:
70 content_type = content_types[partname]
71 spart = _SerializedPart(partname, content_type, blob, srels)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\pkgreader.py in _walk_phys_parts(phys_reader, srels, visited_partnames)
102 yield (partname, blob, part_srels)
103 for partname, blob, srels in PackageReader._walk_phys_parts(
--> 104 phys_reader, part_srels, visited_partnames):
105 yield (partname, blob, srels)
106
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\pkgreader.py in _walk_phys_parts(phys_reader, srels, visited_partnames)
102 yield (partname, blob, part_srels)
103 for partname, blob, srels in PackageReader._walk_phys_parts(
--> 104 phys_reader, part_srels, visited_partnames):
105 yield (partname, blob, srels)
106
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\pkgreader.py in _walk_phys_parts(phys_reader, srels, visited_partnames)
99 visited_partnames.append(partname)
100 part_srels = PackageReader._srels_for(phys_reader, partname)
--> 101 blob = phys_reader.blob_for(partname)
102 yield (partname, blob, part_srels)
103 for partname, blob, srels in PackageReader._walk_phys_parts(
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pptx\opc\phys_pkg.py in blob_for(self, pack_uri)
107 matching member is present in zip archive.
108 """
--> 109 return self._zipf.read(pack_uri.membername)
110
111 def close(self):
~\AppData\Local\Continuum\anaconda3\lib\zipfile.py in read(self, name, pwd)
1312 def read(self, name, pwd=None):
1313 """Return file bytes (as a string) for name."""
-> 1314 with self.open(name, "r", pwd) as fp:
1315 return fp.read()
1316
~\AppData\Local\Continuum\anaconda3\lib\zipfile.py in open(self, name, mode, pwd, force_zip64)
1350 else:
1351 # Get info object for name
-> 1352 zinfo = self.getinfo(name)
1353
1354 if mode == 'w':
~\AppData\Local\Continuum\anaconda3\lib\zipfile.py in getinfo(self, name)
1279 if info is None:
1280 raise KeyError(
-> 1281 'There is no item named %r in the archive' % name)
1282
1283 return info
KeyError: "There is no item named 'ppt/slides/NULL' in the archive"
是的,这是一个棘手的问题。某些规范没有提供“破坏”的关系(指的是一个不存在的包部分),但至少有一个库(如果我没记错的话,基于Java)不会在某些情况下正确清理关系在这种情况下,可能是幻灯片删除操作。
解释的要点是这样的:
slide1.xml
,它们被安排在“目录结构”中。presentation.xml
)与其每个幻灯片部分相关。这些关系存储在像presentation.xml.rels
这样的文件中。该关系用"rId3"
这样的字符串键入,并通过包中的路径标识相关部分。<p:sldId r:id="rId3"/>
)引用另一部分。目标部分在.rels文件中“查找”以查找其路径并以此方式获取。KeyError
意味着.rels文件有一个<Relationship>
元素引用部分ppt/slides/NULL
(而不是像ppt/slides/slide3.xml
)。由于包中没有这样的部分,查找失败。如果您在PowerPoint中打开“模板”文件并保存它,我认为它将自行修复。您可能需要重新排列幻灯片并将其移回以挤压该部分代码。
如果这不起作用,您需要手动修补程序包,删除任何损坏的引用和关系。 opc-diag
可以很方便。
所以,感谢Scanny的帮助。你是完全正确的。查找正在查找ppt / slides / slide#.xml并且没有找到它的关系。原因是因为关系被编码为幻灯片/幻灯片#.xml(没有ppt /)。我确实进入了opc-diag看看我能在那里做什么,但我找到了一个简单的解决方法。
我之前的代码有一行说for slide in ppt.slides:
,这是错误:KeyError: "There is no item named 'ppt/slides/NULL' in the archive"
。当使用opc-diag浏览PresentationML时,我发现关系设置如下:<Relationship Id="x" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide1.xml"/>\n
。这种关系不包括ppt
。
因此,为了摆脱该查找并使其与PowerPoint存储幻灯片关系的方式相匹配,我更改了这些行:
ppt = Presentation('HispPres1.pptx')
for slide in ppt.slides:
到此
ppt = Presentation('HispPres1.pptx')
slides = ppt.slides
for slide in slides: