如何使用Python pptx复制带有图像的幻灯片?

5
我的最终目标是更改演示文稿的主题。为了做到这一点,我创建了一个源模板和一个新模板(具有正确的主题)。我在源模板中迭代每个幻灯片,然后使用来自https://dev59.com/OlUL5IYBdhLWcg3wFEvw#56074651的代码将源内容添加到新模板中的新幻灯片中。如果有更好的方法,我很愿意听取建议。
对于文本和文本框,这种方法效果很好,但是测试图片无法在新的幻灯片中显示(如下图所示):

enter image description here

代码

def copy_slide_from_external_prs(self, src, idx, newPrs):

    # specify the slide you want to copy the contents from
    src_slide = src.slides[idx]

    # Define the layout you want to use from your generated pptx
    slide_layout = newPrs.slide_layouts[2]

    # create now slide, to copy contents to
    curr_slide = newPrs.slides.add_slide(slide_layout)


    # remove placeholders
    for p in [s.element for s in curr_slide.shapes if 'Text Placeholder' in s.name or 'Title' in s.name]:
        p.getparent().remove(p)

    # now copy contents from external slide, but do not copy slide properties
    # e.g. slide layouts, etc., because these would produce errors, as diplicate
    # entries might be generated
    for shp in src_slide.shapes:
        el = shp.element
        newel = copy.deepcopy(el)

        curr_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')
    
    return newPrs

我尝试了许多不同的解决方案,并尝试使用源图像中的image.blob属性创建一个新的图片。然而,这样做后,该图像就没有元素了。我需要将blob转换为PNG格式,保存它,然后使用保存的PNG创建一个新的图像吗?

一定有更好的方法来实现这个目标。再次强调,我只想改变主题。

2个回答

6

这是我开发的解决方法。首先,我检查形状是否为图片,如果是,我将该图片写入本地目录。然后我使用保存的图片向幻灯片添加图片。最后,我删除了本地保存的图片。

现在,此复制幻灯片功能适用于图片:

def copy_slide_from_external_prs(src, idx, newPrs):

    # specify the slide you want to copy the contents from
    src_slide = src.slides[idx]

    # Define the layout you want to use from your generated pptx
    SLD_LAYOUT = 5
    slide_layout = prs.slide_layouts[SLD_LAYOUT]

    # create now slide, to copy contents to
    curr_slide = newPrs.slides.add_slide(slide_layout)

    # create images dict
    imgDict = {}

    # now copy contents from external slide, but do not copy slide properties
    # e.g. slide layouts, etc., because these would produce errors, as diplicate
    # entries might be generated
    for shp in src_slide.shapes:
        if 'Picture' in shp.name:
            # save image
            with open(shp.name+'.jpg', 'wb') as f:
                f.write(shp.image.blob)

            # add image to dict
            imgDict[shp.name+'.jpg'] = [shp.left, shp.top, shp.width, shp.height]
        else:
            # create copy of elem
            el = shp.element
            newel = copy.deepcopy(el)

            # add elem to shape tree
            curr_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')

    # add pictures
    for k, v in imgDict.items():
        curr_slide.shapes.add_picture(k, v[0], v[1], v[2], v[3])
        os.remove(k)

3
很好的解决方案!一个小的改进是生成一个唯一的ID作为临时文件名(例如使用secrets.token_hex(10))。我发现在同一张幻灯片上的一些图像具有相同的名称(例如“Picture 8”),如果没有这个改进,只会复制其中一个相同名称的图像。 - OD1995

0

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。仅有链接的答案如果链接页面发生更改可能会变得无效。 - Tyler2P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接