Python-pptx: copy slide

前端 未结 6 1016
谎友^
谎友^ 2020-12-16 05:59

How can I copy slide?

I created a template slide and I need to copy it and edit shapes of each copy separately.

Or how I can add my template slide to present

相关标签:
6条回答
  • 2020-12-16 06:41

    Since I also found another usecase for the code shared by @d_bergeron, I just wanted to share it here. In my case, I wanted to copy a slide from another presentation into the one I generated with python-pptx:

    As argument I pass in the Presentation() object I created using python-pptx (prs = Presenation()).

    from pptx import Presentation
    import copy
    
    def copy_slide_from_external_prs(prs):
    
        # copy from external presentation all objects into the existing presentation
        external_pres = Presentation("PATH/TO/PRES/TO/IMPORT/from.pptx")
    
        # specify the slide you want to copy the contents from
        ext_slide = external_pres.slides[0]
    
        # 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 = prs.slides.add_slide(slide_layout)
    
        # 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 ext_slide.shapes:
            el = shp.element
            newel = copy.deepcopy(el)
            curr_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')
    
        return prs
    

    I am mainly posting it here, since I was looking for a way to copy an external slide into my presentation and ended up in this thread.

    0 讨论(0)
  • 2020-12-16 06:43

    Sorry for the delay, I was moved to another project. I was able to complete my ppt project using multiple template slides and copying them. At the end of building the presentation I delete the templates. To grab the shapes you will need to iterate through the slide.shapes and find the name of the shape that you are looking for. Once you have this returned you can then edit the shape as needed. I have added a version of the add_text function that I use to populate shape.text_frame.

    def find_shape_by_name(shapes, name):
        for shape in shapes:
            if shape.name == name:
                return shape
        return None
    
    def add_text(shape, text, alignment=None):
    
        if alignment:
            shape.vertical_anchor = alignment
    
        tf = shape.text_frame
        tf.clear()
        run = tf.paragraphs[0].add_run()
        run.text = text if text else ''
    

    To find the shape "slide_title".

    slide_title = find_shape_by_name(slide.shapes,'slide_title')
    

    To add text to the shape.

    add_text(slide_title,'TEST SLIDE')
    

    Please let me know if you need any other assistance.

    0 讨论(0)
  • 2020-12-16 06:44

    I was using n00by0815's answer and it worked great until I had to copy images. Here is my adapted version that handles images. This code creates a local copy of the image then adds it to the slide. I'm sure there's a cleaner way, but this works.

    0 讨论(0)
  • 2020-12-16 06:47

    Here is another way to copy each slide onto a single PPTX slide for an entire presentation, and then you can use LibreOffice to convert each individual powerpoint into an image:

    def get_slide_count(prs):
    """ Get the number of slides in PPTX presentation """
        slidecount = 0
        for slide in prs.slides:
            slidecount += 1
        return slidecount
    
    
    def delete_slide(prs, slide):
        """ Delete a slide out of a powerpoint presentation"""
        id_dict = { slide.id: [i, slide.rId] for i,slide in enumerate(prs.slides._sldIdLst) }
        slide_id = slide.slide_id
        prs.part.drop_rel(id_dict[slide_id][1])
        del prs.slides._sldIdLst[id_dict[slide_id][0]]
    
    
    def get_single_slide_pres(prs, slidetokeep):
        for idx, slide in enumerate(prs.slides):
            if idx < slidetokeep:
                delete_slide(prs, slide)
            elif (idx > slidetokeep):
                delete_slide(prs, slide)
        prs.save(str(slidetokeep + 1) + ".pptx")
    
    
    pptxfilepath = "test.pptx"
    prs = Presentation(pptxfilepath)
    slidecount = get_slide_count(prs)
    for i in range(slidecount):
        prs_backup = Presentation(pptxfilepath)
        get_single_slide_pres(prs_backup, i)
        prs_backup = None
    
    0 讨论(0)
  • 2020-12-16 06:50

    I wanted to present my workaround to copy slides. I use a template ppt and populate it. I know before populating the slides which slides of the template need to be copied and how often. What I then do is copying the slides and saving the new ppt with the copied slides. After saving I can open the ppt with the copied slides and use pptx to populate the slides.

    import win32com.client
    ppt_instance = win32com.client.Dispatch('PowerPoint.Application')
    #open the powerpoint presentation headless in background
    read_only = True
    has_title = False
    window    = False
    prs = ppt_instance.Presentations.open('path/ppt.pptx',read_only,has_title,window)
    
    nr_slide = 1
    insert_index = 1
    prs.Slides(nr_slide).Copy()
    prs.Slides.Paste(Index=insert_index)
    
    prs.SaveAs('path/new_ppt.pptx')
    prs.Close()
    
    #kills ppt_instance
    ppt_instance.Quit()
    del ppt_instance
    

    In this case the firste slide would be copied of the presentation and inserted after the first slide of the same presentation.

    Hope this helps some of you!

    0 讨论(0)
  • 2020-12-16 06:51

    This is what I found on GitHub, and it works for me. I did change a couple of things for my project. You will need to import six and copy. I am using pptx-6.10

    def duplicate_slide(pres, index):
        template = pres.slides[index]
        try:
            blank_slide_layout = pres.slide_layouts[12]
        except:
            blank_slide_layout = pres.slide_layouts[len(pres.slide_layouts)]
    
        copied_slide = pres.slides.add_slide(blank_slide_layout)
    
        for shp in template.shapes:
            el = shp.element
            newel = copy.deepcopy(el)
            copied_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')
    
        for _, value in six.iteritems(template.part.rels):
            # Make sure we don't copy a notesSlide relation as that won't exist
            if "notesSlide" not in value.reltype:
                copied_slide.part.rels.add_relationship(
                    value.reltype,
                    value._target,
                    value.rId
                )
    
        return copied_slide
    

    Then you can create the copy with passing in your presentation and the slide index of your template:

    copied_slide = duplicate_slide(pres, 4)
    

    I am still working on editing the shapes from the copied slide, once I am further along in my project I can update

    0 讨论(0)
提交回复
热议问题