File size: 3,761 Bytes
c6643c7
3e68ccf
 
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
c6643c7
 
 
 
 
 
3e68ccf
 
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c6643c7
 
3e68ccf
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from typing import List
import json5
import pptx
import re
import yaml

from pptx.dml.color import RGBColor


PATTERN = re.compile(r"^slide[ ]+\d+:", re.IGNORECASE)


def remove_slide_number_from_heading(header: str) -> str:
    """
    Remove the slide number from a given slide header.

    :param header: The header of a slide
    """

    if PATTERN.match(header):
        idx = header.find(':')
        header = header[idx + 1:]

    return header


def generate_powerpoint_presentation(structured_data: str, as_yaml: bool, output_file_name: str) -> List:
    """
    Create and save a PowerPoint presentation file containing the contents in JSON or YAML format.

    :param structured_data: The presentation contents as "JSON" (may contain trailing commas) or YAML
    :param as_yaml: True if the input data is in YAML format; False if it is in JSON format
    :param output_file_name: The name of the PPTX file to save as
    :return A list of presentation title and slides headers
    """

    if as_yaml:
        # Avoid YAML mode: nested bullets can lead to incorrect YAML generation
        try:
            parsed_data = yaml.safe_load(structured_data)
        except yaml.parser.ParserError as ype:
            print(f'*** YAML parse error: {ype}')
            parsed_data = {'title': '', 'slides': []}
    else:
        # The structured "JSON" might contain trailing commas, so using json5
        parsed_data = json5.loads(structured_data)

    presentation = pptx.Presentation()

    # The title slide
    title_slide_layout = presentation.slide_layouts[0]
    slide = presentation.slides.add_slide(title_slide_layout)
    title = slide.shapes.title
    subtitle = slide.placeholders[1]
    title.text = parsed_data['title']
    print(f'Title is: {title.text}')
    subtitle.text = 'by Myself and SlideDeck AI :)'
    all_headers = [title.text, ]

    background = slide.background
    background.fill.solid()
    background.fill.fore_color.rgb = RGBColor.from_string('C0C0C0')  # Silver
    title.text_frame.paragraphs[0].font.color.rgb = RGBColor(0, 0, 128)  # Navy blue

    # Add contents in a loop
    for a_slide in parsed_data['slides']:
        bullet_slide_layout = presentation.slide_layouts[1]
        slide = presentation.slides.add_slide(bullet_slide_layout)
        shapes = slide.shapes

        title_shape = shapes.title
        body_shape = shapes.placeholders[1]
        title_shape.text = remove_slide_number_from_heading(a_slide['heading'])
        all_headers.append(title_shape.text)
        text_frame = body_shape.text_frame

        for an_item in a_slide['bullet_points']:
            item_type = type(an_item)
            # print('Bullet point type:', item_type)

            if item_type is str:
                paragraph = text_frame.add_paragraph()
                paragraph.text = an_item
                paragraph.level = 0
            elif item_type is list:
                for sub_item in an_item:
                    if type(sub_item) is str:
                        paragraph = text_frame.add_paragraph()
                        paragraph.text = sub_item
                        paragraph.level = 1

        background = slide.background
        background.fill.gradient()
        background.fill.gradient_angle = -225.0

    # The thank-you slide
    last_slide_layout = presentation.slide_layouts[0]
    slide = presentation.slides.add_slide(last_slide_layout)
    title = slide.shapes.title
    title.text = 'Thank you!'

    presentation.save(output_file_name)

    return all_headers


if __name__ == '__main__':
    generate_powerpoint_presentation(
        json5.loads(open('examples/example_02_structured_output.json', 'r').read()),
        as_yaml=False,
        output_file_name='test.pptx'
    )