Insert blank slide with python-pptx in existing presentation - python

I'm working with the python-pptx library and I'm trying to insert a blank slide at a specific place (slide with the same dimensions).
I know how to delete a slide :
def delete_slides(presentation, index):
xml_slides = presentation.slides._sldIdLst
slides = list(xml_slides)
xml_slides.remove(slides[index])
But how to insert a blank slide?

Someone will probably come along with a better solution but you could just create a blank slide and then move it to the location you want.
from pptx import Presentation
def move_slide(old_index, new_index):
xml_slides = presentation.slides._sldIdLst
slides = list(xml_slides)
xml_slides.remove(slides[old_index])
xml_slides.insert(new_index, slides[old_index])
presentation = Presentation("test1.pptx")
layout = presentation.slide_masters[0].slide_layouts[6]
slide = presentation.slides.add_slide(layout)
slide_id = presentation.slides.index(slide)
move_slide(slide_id, 5)
presentation.save("test1.pptx")

Related

Python-pptx Import Slide Layout

I'm working with pptx to create templates based on info in existing slides. I can create a slide, define its layout, enter text, etc. I can do all the basics. I want to create a slide in a new ppt based on an input ppt and use the same amount of slides as the original, all with their original layouts, and just change some text. How can I access a specific slide's layout # without knowing beforehand? All the other answers say "new_slide_layout = prs.slides.slide_layouts[i]" where i is a number they have defined in the code (usually 0). I'm trying to get that i from the input file and use it without choosing slide type as a user. How can I do this?
Latest functional code:
inputf = pptx.Presentation(input_file)
prs = pptx.Presentation()
old_slide_list = []
slides = inputf.slides
slide_count = 0
for slide in slides:
old_slide_list.append(slide)
slide_count += 1
old_text_runs = []
new_text_runs = []
for i in range(0, slide_count):
old_slide = old_slide_list[i]
old_runs_count = 0
nl = int(input("Enter your choice for this slide's layout (0-8):"))
new_layout = prs.slide_layouts[nl]
new_slide = prs.slides.add_slide(new_layout)
I can allow the user to choose their own slide layout but if I try to rip it directly from the old slide and use it for the new slide it damages the new ppt and it will ask you to repair each time you open it. Older code that damages the presentation:
import copy
for slide in slides:
print('slide number %d' % slides.index(slide))
count += 1
tempct = 0
prs2 = pptx.Presentation()
while tempct != count:
template = prs.slides[tempct]
template_layout = template.slide_layout
new_slide = prs2.slides.add_slide(template_layout)
for shp in template.shapes:
el = shp.element
newel = copy.deepcopy(el)
new_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')
tempct += 1
prs2.save(output_file)

Using win32com to combine powerpoint presentations by copying slides

I'm trying to write a python script that combines slides from different powerpoint presentations into a new standalone presentation.
The following code copies a single slide (in this case slide 11) from an existing presentation and pastes it into a new presentation at the insert_index:
import win32com.client
source_path = "source_path"
target_path = "target_path"
ppt_instance = win32com.client.Dispatch('PowerPoint.Application')
read_only = True
has_title = False
window = False
source_prs = ppt_instance.Presentations.open(source_path, read_only, has_title, window)
target_prs = ppt_instance.Presentations.Add()
nr_slide = 11
insert_index = 1
source_prs.Slides(nr_slide).Copy()
target_prs.Slides.Paste(Index=insert_index)
target_prs.SaveAs(target_path)
target_prs.Close()
source_prs.Close()
ppt_instance.Quit()
del ppt_instance
However, this unfortunately changes the colors of some objekts.
How can I get around this?
I appreciate your help.

How to remove the blank text boxes from python pptx generated slides?

from pptx import Presentation
from pptx.util import Inches
prs = Presentation("my_pptfile_begin.pptx")
left = Inches(0.6)
top = Inches(1.7)
blank_slide_1 = prs.slide_layouts[6]
add_the_slide = prs.slides.add_slide(blank_slide_1)
img_path1 = 'Three_Part_Set_Difference_excel_printout.png'
slide1=prs.slides[1]
pic = slide1.shapes.add_picture(img_path1, left, top)
blank_slide_2 = prs.slide_layouts[6]
add_the_slide = prs.slides.add_slide(blank_slide_2)
img_path2 = 'my_image.png'
slide2=prs.slides[2]
pic = slide2.shapes.add_picture(img_path2, left, top)
logoleft = Inches(4.7)
logotop = Inches(1.8)
blank_slide_3 = prs.slide_layouts[6]
add_the_slide = prs.slides.add_slide(blank_slide_3)
img_path3 = 'logo_slide.png'
slide3=prs.slides[3]
pic = slide3.shapes.add_picture(img_path3, logoleft, logotop)
prs.save('my_pptfile_Final.pptx')
How to remove the blank text boxes (or as a matter of fact all textboxes)?
I do not need any text boxes in my Powerpoint output file
If you're talking about empty placeholder shapes, just use a slide layout that has no placeholders.
In the default template used when you call Presentation() by itself (without an argument), that is the seventh layout I believe (prs.slide_layouts[6]).
But you need to adjust that for whatever starting .pptx file you're using ("my_pptfile_begin.pptx" in your case) by looking at it in slide-master view and counting down to the blank layout (or adding one if it doesn't have one).
blank_slide_3 = prs.slide_layouts[x] where x the slide number of the default template of your pptx application or your company's default template.
Therefore you need to know the default template and know the blank slide with no textboxes of that template based on the defaults of your ppt application

Color tables cells in ppt using python

So I have a excel which contains a table like this:
I want to get the same table in powerpoint using Python
Work Done till now:
Read the excel to python and store in pandas df
Add df to powerpoint
Code for the same effort:
from pd2ppt import df_to_table
import pandas as pd
from pptx import Presentation
from pptx.util import Inches
path =r"Sample PPT.pptx"
prs = Presentation(path)
title_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
title.text = "Summary Table"
top = Inches(1.5)
left =Inches(0.25)
width =Inches(9.25)
height= Inches(5.0)
df_to_table(slide, df,left, top, width, height)
All I need is how to do color formatting in this table using Python?
Each cell in a PowerPoint table has its own fill, which can do everything other FillFormat objects can do::
from pptx.dml.color import RGBColor
cell = table.cell(0, 0) # ---or whatever cell you choose---
fill = cell.fill
fill.solid()
fill.fore_color.rgb = RGBColor(0xFA, 0x00, 0x37)
The FillFormat object interface is further described in the documentation here:
https://python-pptx.readthedocs.io/en/latest/api/dml.html#fillformat-objects

Dynamic framesize in Python Reportlab

I tried to generate a shipping list with reportlab in Python.
I was trying to put all parts (like senders address, receivers address, a table) in place by using Platypus Frames.
The first problem that I ran into was that I needed a lot of Frames to position everything the right way, is there a better way using Platypus?
Because I want the senders address and my address to be on the same height and if I just add them to my story = [] they get aligned one below the other.
The next problem is that the table I'm drawing is dynamic in size and when I reach the end of the Frame ( space I want the table to go) it just does a FrameBreak and continuous in the next frame. So how can I make the Frame (space for my table ) dynamic?
Your use case is a really common one, so Reportlab has a system to help you out.
If you read the user guide about platypus it will introduce you to 4 main concepts:
DocTemplates the outermost container for the document;
PageTemplates specifications for layouts of pages of various kinds;
Frames specifications of regions in pages that can contain flowing text or graphics.
Flowables
Using PageTemplates you can combine "static" content with dynamic on a page in a sensible way like for example logo's, addresses and such.
You already discovered the Flowables and Frames but propably you did not start on fancyPageTemplates or DocTemplates yet. This makes sense because it isn't necessary for most simple documents. Saddly a shippinglist isn't a simple document, it holds address, logos and important info that has to be on every page. This is where PageTemplates come in.
So how do you use these templates? The concept is simple each page has a certain structure that might differ between pages, for example on page one you want to put the addresses and then start the table while on the second page you only want the table. This would be something like this:
Page 1:
Page 2:
A example would look like this:
(This would be perfect for the SO Documentation if there was one for Reportlab)
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, NextPageTemplate, Paragraph, PageBreak, Table, \
TableStyle
class ShippingListReport(BaseDocTemplate):
def __init__(self, filename, their_adress, objects, **kwargs):
super().__init__(filename, page_size=A4, _pageBreakQuick=0, **kwargs)
self.their_adress = their_adress
self.objects = objects
self.page_width = (self.width + self.leftMargin * 2)
self.page_height = (self.height + self.bottomMargin * 2)
styles = getSampleStyleSheet()
# Setting up the frames, frames are use for dynamic content not fixed page elements
first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height - 6 * cm, id='small_table')
later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height, id='large_table')
# Creating the page templates
first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.on_first_page)
later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.add_default_info)
self.addPageTemplates([first_page, later_pages])
# Tell Reportlab to use the other template on the later pages,
# by the default the first template that was added is used for the first page.
story = [NextPageTemplate(['*', 'LaterPages'])]
table_grid = [["Product", "Quantity"]]
# Add the objects
for shipped_object in self.objects:
table_grid.append([shipped_object, "42"])
story.append(Table(table_grid, repeatRows=1, colWidths=[0.5 * self.width, 0.5 * self.width],
style=TableStyle([('GRID',(0,1),(-1,-1),0.25,colors.gray),
('BOX', (0,0), (-1,-1), 1.0, colors.black),
('BOX', (0,0), (1,0), 1.0, colors.black),
])))
self.build(story)
def on_first_page(self, canvas, doc):
canvas.saveState()
# Add the logo and other default stuff
self.add_default_info(canvas, doc)
canvas.drawString(doc.leftMargin, doc.height, "My address")
canvas.drawString(0.5 * doc.page_width, doc.height, self.their_adress)
canvas.restoreState()
def add_default_info(self, canvas, doc):
canvas.saveState()
canvas.drawCentredString(0.5 * (doc.page_width), doc.page_height - 2.5 * cm, "Company Name")
canvas.restoreState()
if __name__ == '__main__':
ShippingListReport('example.pdf', "Their address", ["Product", "Product"] * 50)

Categories