Created
August 13, 2025 04:18
-
-
Save maquedexiju/adf94d8bb02083575bf57f98639d74aa to your computer and use it in GitHub Desktop.
A snippet to copy slide using python-pptx, useful when you're creating ppt in reference of a existing file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import copy | |
| from pptx.enum.shapes import MSO_SHAPE_TYPE | |
| from pptx import Presentation | |
| namespaces = { | |
| 'p': 'http://schemas.openxmlformats.org/presentationml/2006/main', | |
| 'p14': 'http://schemas.microsoft.com/office/powerpoint/2010/main', | |
| 'a': 'http://schemas.openxmlformats.org/drawingml/2006/main', | |
| 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' | |
| } | |
| def duplicate_slide(pres_source, pres_dest, index): | |
| # Get the template slide to copy | |
| template = pres_source.slides[index] | |
| layout = template.slide_layout | |
| # Create a new slide | |
| copied_slide = pres_dest.slides.add_slide(layout) | |
| # If the background is separate | |
| if not template.follow_master_background: | |
| copied_slide.background._element = copy.deepcopy(template.background._element) | |
| # Process placeholders | |
| for placeholder in template.placeholders: | |
| o_text_frame = placeholder.text_frame._element | |
| idx = placeholder._element.ph_idx | |
| n_text_frame = copied_slide.placeholders[idx].text_frame._element | |
| copied_slide.placeholders[idx]._element.replace(n_text_frame, copy.deepcopy(o_text_frame)) | |
| # Process shapes step by step | |
| n_shps = copied_slide.shapes | |
| for shp in template.shapes: | |
| if shp.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER: | |
| continue | |
| # Copy shape | |
| el = shp.element | |
| el_n = copy.deepcopy(el) | |
| n_shps._spTree.insert_element_before(el_n) | |
| n_shp = n_shps[-1] | |
| # Process image | |
| if shp.shape_type == MSO_SHAPE_TYPE.PICTURE: | |
| # Copy image | |
| _create_image_part(n_shps, n_shp, shp) | |
| # Process images in groups | |
| elif shp.shape_type == MSO_SHAPE_TYPE.GROUP: | |
| _create_image_parts(n_shp.shapes, n_shp.shapes, shp.shapes) | |
| return copied_slide | |
| def _save_temp_img(img): | |
| name = img.filename | |
| dpi = img.dpi | |
| size = img.size | |
| blob = img.blob | |
| content_type = img.content_type | |
| # Save image to temporary file | |
| with open(name, 'wb') as f: | |
| f.write(blob) | |
| return name | |
| def _create_image_part(n_shps, n_shp, o_shp): | |
| # Copy the image from o_shp to the new shapes | |
| temp_img_file = _save_temp_img(o_shp.image) | |
| # Save the image and generate reference id | |
| img_part, rId = n_shps.part.get_or_add_image_part(temp_img_file) | |
| # The reference id is in r:embed of a:blip within p:blipFill | |
| bilp_info = n_shp._element.xpath('./p:blipFill/a:blip')[0] | |
| # Set the new value | |
| bilp_info.set(f'{{{namespaces['r']}}}embed', rId) | |
| def _create_image_parts(self, n_shps, o_shps): | |
| # Create image files | |
| for shp in n_shps: | |
| shp_id = shp.shape_id | |
| o_shp = [ s for s in o_shps if s.shape_id == shp_id][0] | |
| if shp.shape_type == MSO_SHAPE_TYPE.PICTURE: | |
| _create_image_part(n_shps, shp, o_shp) | |
| elif shp.shape_type == MSO_SHAPE_TYPE.GROUP: | |
| _create_image_parts(shp.shapes, o_shp.shapes) | |
| if __name__ == '__main__': | |
| p = Presentation('test_origin.pptx') | |
| pn = Presentation() | |
| pn.slide_width = p.slide_width | |
| pn.slide_height = p.slide_height | |
| snn = duplicate_slide(p, pn, 0) | |
| snn = duplicate_slide(p, pn, 1) | |
| snn = duplicate_slide(p, pn, 2) | |
| pn.save('test_copied.pptx') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment