scanny / python-pptx

Create Open XML PowerPoint documents in Python
MIT License
2.41k stars 522 forks source link

Ability to toggle bullet point formatting on run or paragraph #100

Open suidroot opened 10 years ago

suidroot commented 10 years ago

It would be nice to be able to change the bullet point formatting on a run or paragraph level. I would like to be able to have select text on a slide be bullet pointed while other text not. Also see the google group discussion for a similar request.

https://groups.google.com/d/topic/python-pptx/HhNBrUeqw_w/discussion

g2010a commented 10 years ago

This would be very, very useful! Even being to toggle bullets for an entire textbox would be welcome.

probonopd commented 8 years ago

:+1:

dansbits commented 8 years ago

+1 Is there anyway to insert a bullet-point text-frame into an existing slide? The only way I can find to create a bullet point text frame is with a new bullet slide layout

scanny commented 8 years ago

I don't believe there is.

There would be two general ways to go about it:

  1. use a placeholder that was pre-configured to use bullet points
  2. configure a new text box to use bullet points

Either one would require some work with internals. If you could manage it, like if you were generating presentations from scratch, the best way might be to create a custom slide layout in your starting template .pptx that was laid out the way you wanted.

fmaupas commented 7 years ago

+1 - it would really be awesome to be able - in easy matter - to select the type of bullet. This would complete this really nice python package.

Great work !

pysailor commented 6 years ago

My 2cts, since I have a similar problem domain: I want to have a text-box that uses bullet points - but I want to add a paragraph that does not use bullets in between; like a sub-heading. As recommended above, I use a placeholder that was pre-configured to use bullet points.

How to make a single paragraph not use bullets? I created an example in Powerpoint manually and looked at the XML source. It seems all is needed is the presence of a <a:buNone/> tag inside the paragraph (<a:pPr>). python-pptx does not provide any method to do this, but I experimentally added a single line to https://github.com/scanny/python-pptx/blob/master/pptx/oxml/text.py#L462 (updated, thanks to @julienforgeat's comment below)

    buNone = ZeroOrOne('a:buNone', successors=_tag_seq[11:])

This then allows me to do stuff like the following (target is the _textframe of my shape, the placeholder that is defined to use bullets):

    p = target.add_paragraph()
    p._pPr._add_buNone()
    p.text = "I don't do bullets"

In Powerpoint, all paragraphs I add and do p._pPr._add_buNone() on are not bulleted, the rest are (default).

I don't know the intricacies of Powerpoint and neither this package/xmlchemy so well as to understand if my "fix" is legitimate or completely brain-dead. I can only see that for the use-case described above, it seems to work (and 2355 tests are still passing).

zackmdavis commented 6 years ago

@pysailor thanks for the pointer! I've drafted a patch that allows setting a bullet property on paragraphs and seems to work (with LibreOffice Impress). (I'll pull request it later after writing tests and docs.) Example usage:

import pptx

prs = pptx.Presentation()
prs.slides.add_slide(prs.slide_layouts[1])

_, body, *_ = prs.slides[0].shapes.placeholders
p = body.text_frame.paragraphs[0]

p.text = "Hello Bullet World"  # has a bullet (because of the default style)

prs.save("test1.pptx")  # save off a "control" presentation

p.bullet = False  # no bullet
prs.save("test2.pptx")

p.bullet = "★" # bullet is star character
prs.save("test3.pptx")
swellander commented 5 years ago

Any updates on this?

zackmdavis commented 5 years ago

Um. I'm still intending to put together a proper pull request "when I have time." I fear that ascertainment of exactly how credible my mere "intent" is, must be left to the reader. :cold_sweat: :crying_cat_face: :skull_and_crossbones:

julienforgeat commented 4 years ago

I am having similar need and I used @pysailor 's quick fix to make it work. Only thing is that now the code should be inserted at https://github.com/scanny/python-pptx/blob/master/pptx/oxml/text.py#L462

@pysailor , maybe you can edit your message too as I suspect I am not the only one ending up on this page. Unless there is a better fix now of course, anyway, thanks!

zoeesilcock commented 4 years ago

For anyone that is stuck with a template that forces bullets I figured out a quick workaround that can be used until python-pptx supports shutting off bullets.

from lxml import etree

# Get or create your paragraph object

p._pPr.insert(0, etree.Element("{http://schemas.openxmlformats.org/drawingml/2006/main}buNone"))

I realize it's ugly and I wished I had the time to build the feature properly and provide a pull request, but I don't.

Force1ess commented 3 months ago

@pysailor thanks for the pointer! I've drafted a patch that allows setting a bullet property on paragraphs and seems to work (with LibreOffice Impress). (I'll pull request it later after writing tests and docs.) Example usage:感谢您的指点!我起草了一个补丁,允许在段落上设置 bullet 属性,并且似乎可以工作(使用 LibreOffice Impress)。(我稍后会在编写测试和文档后拉取请求。用法示例:

import pptx

prs = pptx.Presentation()
prs.slides.add_slide(prs.slide_layouts[1])

_, body, *_ = prs.slides[0].shapes.placeholders
p = body.text_frame.paragraphs[0]

p.text = "Hello Bullet World"  # has a bullet (because of the default style)

prs.save("test1.pptx")  # save off a "control" presentation

p.bullet = False  # no bullet
prs.save("test2.pptx")

p.bullet = "★" # bullet is star character
prs.save("test3.pptx")

zackmdavis's solution was great, but I found that sometimes it doesn't work because lacking of buFont(bullet font) element inside the a:pPr try use this to detect and insert buFont

    @bullet.setter
    def bullet(self, value):
        pPr = self._p.get_or_add_pPr()
        if (
            pPr.find(
                "a:buFont",
                namespaces={
                    "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
                },
            )
            is None
        ):
            buFont = etree.Element(
                "{http://schemas.openxmlformats.org/drawingml/2006/main}buFont",
                typeface="Wingdings",
                pitchFamily="2",
                charset="2",
                panose="05000000000000000000",
            )
            pPr.insert(0, buFont)
        pPr.bullet = value