python-pptx icon indicating copy to clipboard operation
python-pptx copied to clipboard

Ability to toggle bullet point formatting on run or paragraph

Open suidroot opened this issue 11 years ago • 13 comments

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

suidroot avatar Jun 06 '14 01:06 suidroot

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

g2010a avatar Sep 16 '14 15:09 g2010a

:+1:

probonopd avatar Mar 19 '16 22:03 probonopd

+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

dansbits avatar Mar 21 '16 21:03 dansbits

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.

scanny avatar Mar 24 '16 04:03 scanny

+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 !

fmaupas avatar Jan 05 '17 04:01 fmaupas

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 text_frame 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).

pysailor avatar May 02 '18 12:05 pysailor

@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")

zackmdavis avatar May 22 '18 23:05 zackmdavis

Any updates on this?

swellander avatar Aug 06 '19 16:08 swellander

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:

zackmdavis avatar Aug 06 '19 17:08 zackmdavis

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!

julienforgeat avatar Dec 29 '19 21:12 julienforgeat

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.

zoeesilcock avatar Mar 19 '20 15:03 zoeesilcock

@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

Force1ess avatar Jul 16 '24 04:07 Force1ess

I added a pull request that implements this functionality. It's based on @zackmdavis's implementation but the paragraph.bullet takes a new class (currently) called BulletStyle. The reason for changing the interface is that we cannot be certain what the slide's default bullet looks like. This needs to be passed explicitly. However, it's still possible to toggle the bullet in the case brought up by @zoeesilcock:

p = text_frame.add_paragraph()    # Has bullet if this is the default
p.bullet = BulletStyle.NO_BULLET  # Now the bullet is explicitly turned off
p.bullet = BulletStyle.DEFAULT    # Now the bullet is back, if this was the default

As a bonus, I have also implemented setting the paragraph to be part of a numbered list.

# Set to a numbered list
p.bullet = BulletStyle.numbered(MSO_NUMBERED_BULLET_STYLE.ARABIC_PERIOD)

# Set bullet to an "x" character
p.bullet = BulletStyle.custom("x")

Happy for any feedback! There is certainly room for improvement.

Touzen avatar Apr 30 '25 15:04 Touzen