Print Powerpoint Slide from Python - python

I'm trying to print out a slide from Powerpoint. I've accessed the slide using the following code:
from win32com import client
powerpoint = client.Dispatch("Powerpoint.Application")
presentation = powerpoint.presentations.Open(filepath)
slide = presentation.Slides[10]
print(slide.name) # Just to check I have in fact got the slide
When printing Word docs I can just call PrintOut() on the document but it doesn't seem to work for Powerpoint.
Does anyone have any solutions?
presentation.PrintOut()
prints the entire presentation, but I just want a specific slide.

Ok I figured out I can specify a range using:
presentation.PrintOut(From=1, To=1)
And I can iterate the slides to match the name using a loop:
count = 1
for slide in presentation.Slides:
if slide.name == "Slide1":
presentation.PrintOut(From=count, To=count)
break
count += 1

Related

How do you insert an image into a specific location in an existing Word document with Python?

What I want to do is insert an image into a specific location in an existing Word document using Python. I've looked at various libraries to do this; I'm using the docx-mailmerge package to insert text and tables using Word merge fields, but unfortunately image merging is just a TODO/wishlist feature. python-docx meanwhile allows image insertion, but only at the end of a document, not in specific places.
Is there another library that does this, or a good trick to accomplish it?
Fiddling around with the underlying API (and thanks to this SO answer) I hacked my way to success:
add a placeholder in your Word document where the image should go, something like a single line that says [ChartImage1]
find the paragraph object in the document that contains that text
replace the text of that paragraph with an empty string
add a run, and inside that add your image
So something like:
document = Document("template.docx")
image_paras = [i for i, p in enumerate(document.paragraphs) if "[ChartImage1]" in p.text]
p = document.paragraphs[image_paras[0]]
p.text = ""
r = p.add_run()
r.add_picture("path/to/image.png")
document.save("my_doc.docx")

Adding Image at the very beginning of an already existing docx document [duplicate]

I use Python-docx to generate Microsoft Word document.The user want that when he write for eg: "Good Morning every body,This is my %(profile_img)s do you like it?"
in a HTML field, i create a word document and i recuper the picture of the user from the database and i replace the key word %(profile_img)s by the picture of the user NOT at the END OF THE DOCUMENT. With Python-docx we use this instruction to add a picture:
document.add_picture('profile_img.png', width=Inches(1.25))
The picture is added to the document but the problem that it is added at the end of the document.
Is it impossible to add a picture in a specific position in a microsoft word document with python? I've not found any answers to this in the net but have seen people asking the same elsewhere with no solution.
Thanks (note: I'm not a hugely experiance programmer and other than this awkward part the rest of my code will very basic)
Quoting the python-docx documentation:
The Document.add_picture() method adds a specified picture to the end of the document in a paragraph of its own. However, by digging a little deeper into the API you can place text on either side of the picture in its paragraph, or both.
When we "dig a little deeper", we discover the Run.add_picture() API.
Here is an example of its use:
from docx import Document
from docx.shared import Inches
document = Document()
p = document.add_paragraph()
r = p.add_run()
r.add_text('Good Morning every body,This is my ')
r.add_picture('/tmp/foo.jpg')
r.add_text(' do you like it?')
document.save('demo.docx')
well, I don't know if this will apply to you but here is what I've done to set an image in a specific spot to a docx document:
I created a base docx document (template document). In this file, I've inserted some tables without borders, to be used as placeholders for images. When creating the document, first I open the template, and update the file creating the images inside the tables. So the code itself is not much different from your original code, the only difference is that I'm creating the paragraph and image inside a specific table.
from docx import Document
from docx.shared import Inches
doc = Document('addImage.docx')
tables = doc.tables
p = tables[0].rows[0].cells[0].add_paragraph()
r = p.add_run()
r.add_picture('resized.png',width=Inches(4.0), height=Inches(.7))
p = tables[1].rows[0].cells[0].add_paragraph()
r = p.add_run()
r.add_picture('teste.png',width=Inches(4.0), height=Inches(.7))
doc.save('addImage.docx')
Here's my solution. It has the advantage on the first proposition that it surrounds the picture with a title (with style Header 1) and a section for additional comments. Note that you have to do the insertions in the reverse order they appear in the Word document.
This snippet is particularly useful if you want to programmatically insert pictures in an existing document.
from docx import Document
from docx.shared import Inches
# ------- initial code -------
document = Document()
p = document.add_paragraph()
r = p.add_run()
r.add_text('Good Morning every body,This is my ')
picPath = 'D:/Development/Python/aa.png'
r.add_picture(picPath)
r.add_text(' do you like it?')
document.save('demo.docx')
# ------- improved code -------
document = Document()
p = document.add_paragraph('Picture bullet section', 'List Bullet')
p = p.insert_paragraph_before('')
r = p.add_run()
r.add_picture(picPath)
p = p.insert_paragraph_before('My picture title', 'Heading 1')
document.save('demo_better.docx')
This is adopting the answer written by Robᵩ while considering more flexible input from user.
My assumption is that the HTML field mentioned by Kais Dkhili (orignal enquirer) is already loaded in docx.Document(). So...
Identify where is the related HTML text in the document.
import re
## regex module
img_tag = re.compile(r'%\(profile_img\)s') # declare pattern
for _p in enumerate(document.paragraphs):
if bool(img_tag.match(_p.text)):
img_paragraph = _p
# if and only if; suggesting img_paragraph a list and
# use append method instead for full document search
break # lose the break if want full document search
Replace desired image into placeholder identified as img_tag = '%(profile_img)s'
The following code is after considering the text contains only a single run
May be changed accordingly if condition otherwise
temp_text = img_tag.split(img_paragraph.text)
img_paragraph.runs[0].text = temp_text[0]
_r = img_paragraph.add_run()
_r.add_picture('profile_img.png', width = Inches(1.25))
img_paragraph.add_run(temp_text[1])
and done. document.save() it if finalised.
In case you are wondering what to expect from the temp_text...
[In]
img_tag.split(img_paragraph.text)
[Out]
['This is my ', ' do you like it?']
I spend few hours in it. If you need to add images to a template doc file using python, the best solution is to use python-docx-template library.
Documentation is available here
Examples available in here
This is variation on a theme. Letting I be the paragraph number in the specific document then:
p = doc.paragraphs[I].insert_paragraph_before('\n')
p.add_run().add_picture('Fig01.png', width=Cm(15))

Problem with python-docx putting pictures in a table

I am using python-docx to create a new document and then I add a table (rows=1,cols=5). Then I add a picture to each of the five cells. I have the code working but what I see from docx is not what I see when I use Word manually.
Specifically, if I set on "Show Formatting Marks" and then look at what was generated by docx, there is always a hard return in the beginning of each of the cells (put there by the add_paragraph method.) When I use Word manually, there is no hard return.
The result of the hard return is that each picture is down one line from where I want it to be. If I use Word, the pictures are where I expect them to be.
What is also strange is that on the docx document I can manually go in and single click next to the hard return, press the down cursor key once, and then press the Backspace key once and the hard return is deleted and the picture moves to the top of the cell.
So my question is, does anyone know of a way to get a picture in a table cell without having a hard return put in when the add_paragraph method is executed?
Any help would be greatly appreciated.
def paragraph_format_run(cell):
paragraph = cell.add_paragraph()
format = paragraph.paragraph_format
run = paragraph.add_run()
format.space_before = Pt(0)
format.space_after = Pt(0)
format.line_spacing = 1.0
format.alignment = WD_ALIGN_PARAGRAPH.CENTER
return paragraph, format, run
def main():
document = Document()
sections = document.sections
section = sections[0]
section.top_margin = Inches(1.0)
section.bottom_margin = Inches(1.0)
section.left_margin = Inches(0.75)
section.right_margin = Inches(0.75)
table = document.add_table(rows=1, cols=5)
table.allow_autofit = False
cells = table.rows[0].cells
for i in range(5):
pic_path = f"Table_Images\pic_{i}.jpg"
cell = cells[i]
cell.vertical_alignment = WD_ALIGN_VERTICAL.TOP
cell_p, cell_f, cell_r = paragraph_format_run(cell)
cell_r.add_picture(pic_path, width=Inches(1.25))
doc_path = "TableTest_1.docx"
document.save(doc_path)
Each blank cell in a newly created table contains a single empty paragraph. This is just one of those things about the Word format. I suppose it gives a place to put the insertion mark (flashing vertical cursor) when you're using the Word application. A completely empty cell would have no place to "click" into.
This requires that any code that adds content to a cell must treat the first paragraph differently. In short, you access the first paragraph as cell.paragraphs[0] and only create second and later paragraphs with cell.add_paragraph().
So in this particular case, the paragraph_format_run() function would change like this:
def paragraph_format_run(cell):
paragraph = cell.paragraphs[0]
...
This assumes a lot, like it only works when cell is empty, but given what you now know about cell paragraphs you may be able to adapt it to adding multiple images into a cell if later decide you need that.

Python PPTX Slide Layout Import

I apologize, I have been looking for a solution but can't find enough documentation to figure it out. I am trying to import a default slide layout required for school, it has a special background and a Title Block and a Subtitle Block. I assumed when I import this, python-pptx would just automatically create placeholders 0 and 1 for those two text blocks but when I try and edit the placeholders, I get an attribute error:
AttributeError: 'Presentation' object has no attribute 'placeholders'
My code is as follows:
from pptx import Presentation
prs = Presentation('SeniorDesignTitleSlide.pptx')
Presentation_Title = prs.placeholders[0]
Presentation_Subtitle = prs.placeholders[1]
Presentation_Title.text = 'This Is a Test'
Presentation_Subtitle.text = 'Is This Working?'
prs.save('SlideLayoutImportTest.pptx')
Edit[0]: I do realize I am just opening that particular presentation, but how do I access and edit the single slide that’s in it ?
Edit[1]: I’ve found a few posts from 2015 about python-pptx expanding on this feature, but there’s no further information that it actually occurred.
How does python-pptx assign placeholders for imported slide layouts? Or does it even do this? Does it need to be a .potx file?
Thank you in advance.
Placeholders belong to a slide object, not a presentation object. So the first thing is to get ahold of a slide.
A slide is created from a slide layout, which it essentially clones to get some starting shapes, including placeholders in many cases.
So the first step is to figure out which slide layout you want. The easiest way to do this is to open the "starting" presentation (sometimes called a "template" presentation) and inspect it's slide master and layouts using the View > Master > Slide Master... menu option.
Find the one you want, count down to it from the first layout, starting at 0, and that gives you the index of that slide layout.
Then your code looks something like this:
from pptx import Presentation
prs = Presentation('SeniorDesignTitleSlide.pptx')
slide_layout = prs.slide_layouts[0] # assuming you want the first one
slide = prs.slides.add_slide(slide_layout)
Presentation_Title = slide.placeholders[0]
Presentation_Subtitle = slide.placeholders[1]
Presentation_Title.text = 'This Is a Test'
Presentation_Subtitle.text = 'Is This Working?'
prs.save('SlideLayoutImportTest.pptx')
The placeholders collection behaves like a dict as far as indexed access goes, so the 0 and 1 used as indices above are unlikely to match exactly in your case (although the 0 will probably work; the title is always 0).
This page of the documentation explains how to discover what indices your template has available: http://python-pptx.readthedocs.io/en/latest/user/placeholders-using.html
The page before that one has more on placeholder concepts:
http://python-pptx.readthedocs.io/en/latest/user/placeholders-understanding.html

Python: Writing text to a 2003 Word Doc in a specific place on the page

I'm using Python 2.7, Windows 7, and Word 2003. Those three cannot change (well except for maybe the python version). I work in Law and the attorneys have roughly 3 boiler plate objections (just a large piece of text, maybe 5 paragraphs) that need to be inserted into a word document at a specific spot. Now instead of going through and copying and pasting the objection where its needed, my idea is for the user to go through the document adding a special word/phrase (place holder if you will) that wont be found anywhere in the document. Then run some code and have python fill in the rest. Maybe not the cleverest way to go about it, but I'm a noob. I've been practicing with a test page and inserted the below text as place holders (the extra "o" stands for objection)
oone
otwo
othree
Below is what I have so far. I have two questions
Do you have any other suggestions to go about this?
My code does insert the string in the correct order, but the formatting goes out the window and it writes in my string 6 times instead of 1. How can I resolve the formatting issue so it simply writes the text into the spot the place holder is at?
import sys
import fileinput
f = open('work.doc', 'r+')
obj1 = "oone"
obj2 = "otwo"
obj3 = "othree"
for line in fileinput.input('work.doc'):
if obj1 in line:
f.write("Objection 1")
elif obj2 in line:
f.write("Objection 2")
elif obj3 in line:
f.write("Objection 3")
else:
f.write("No Objection")
f.close
You could use python-uno to load the document into OpenOffice and manipulate it using the UNO interface. There is some example code on the site I just linked to which can get you started.

Categories

Resources