File size: 4,043 Bytes
c6643c7
3e68ccf
 
 
 
 
c0b5a2b
3e68ccf
c6643c7
3e68ccf
 
 
 
c6643c7
 
 
 
 
 
3e68ccf
 
 
 
 
 
 
c0b5a2b
 
 
 
 
 
3e68ccf
 
 
 
 
c0b5a2b
3e68ccf
c6643c7
3e68ccf
 
 
 
 
 
 
 
 
 
 
 
 
c0b5a2b
 
3e68ccf
 
 
 
 
 
 
 
 
c6643c7
3e68ccf
c0b5a2b
 
 
 
3e68ccf
 
 
 
 
 
 
 
 
 
c6643c7
3e68ccf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0b5a2b
 
 
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
114
115
116
117
118
119
120
from typing import List
import json5
import pptx
import re
import yaml

from global_config import GlobalConfig


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,
        slides_template: str,
        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 slides_template: The PPTX template to use
    :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)

    print(f"*** Using PPTX template: {GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file']}")
    presentation = pptx.Presentation(GlobalConfig.PPTX_TEMPLATE_FILES[slides_template]['file'])

    # 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'
    )