from pptx import Presentation from pptx.util import Inches, Pt from pptx.dml.color import RGBColor from pptx.enum.text import PP_ALIGN from pptx.oxml.ns import qn from lxml import etree OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyCountryTisOfThee.pptx" SLIDE_W = Inches(13.333) SLIDE_H = Inches(7.5) NAVY = RGBColor(0x0D, 0x27, 0x6D) GOLD = RGBColor(0xF5, 0xC5, 0x18) WHITE = RGBColor(0xFF, 0xFF, 0xFF) VERSES = [ ( "Verse 1", "My country, 'tis of thee,\n" "Sweet land of liberty,\n" "Of thee I sing;\n" "Land where my fathers died,\n" "Land of the pilgrims' pride,\n" "From ev'ry mountainside\n" "Let freedom ring!" ), ( "Verse 4", "Our fathers' God, to thee,\n" "Author of liberty,\n" "To thee we sing;\n" "Long may our land be bright\n" "With freedom's holy light.\n" "Protect us by thy might,\n" "Great God, our King!" ), ] def set_background_color(slide, color): """Fill slide background with a solid color.""" bg = slide.background fill = bg.fill fill.solid() fill.fore_color.rgb = color def add_text_paragraph(tf, text, font_size, color, bold=False, space_before=0): p = tf.add_paragraph() p.alignment = PP_ALIGN.CENTER if space_before: pPr = p._pPr if pPr is None: pPr = p._p.get_or_add_pPr() pPr.set(qn("a:spcBef"), None) spcBef = etree.SubElement(pPr, qn("a:spcBef")) spcPts = etree.SubElement(spcBef, qn("a:spcPts")) spcPts.set("val", str(space_before * 100)) run = p.add_run() run.text = text run.font.size = font_size run.font.color.rgb = color run.font.bold = bold return p def add_slide(prs, blank_layout, verse_label, verse_text): slide = prs.slides.add_slide(blank_layout) set_background_color(slide, NAVY) # Gold decorative rule above title rule_top = Inches(0.55) rule_h = Inches(0.06) rule = slide.shapes.add_shape( 1, # MSO_SHAPE_TYPE.RECTANGLE Inches(1.5), rule_top, SLIDE_W - Inches(3.0), rule_h ) rule.fill.solid() rule.fill.fore_color.rgb = GOLD rule.line.fill.background() # Song title title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.65), SLIDE_W - Inches(1.0), Inches(0.85)) tf = title_box.text_frame tf.word_wrap = False p = tf.paragraphs[0] p.alignment = PP_ALIGN.CENTER run = p.add_run() run.text = "My Country, 'Tis of Thee" run.font.size = Pt(36) run.font.color.rgb = GOLD run.font.bold = True # Verse label label_box = slide.shapes.add_textbox(Inches(0.5), Inches(1.45), SLIDE_W - Inches(1.0), Inches(0.5)) tf2 = label_box.text_frame p2 = tf2.paragraphs[0] p2.alignment = PP_ALIGN.CENTER run2 = p2.add_run() run2.text = verse_label run2.font.size = Pt(22) run2.font.color.rgb = WHITE run2.font.bold = False run2.font.italic = True # Gold rule below label rule2 = slide.shapes.add_shape( 1, Inches(1.5), Inches(1.95), SLIDE_W - Inches(3.0), rule_h ) rule2.fill.solid() rule2.fill.fore_color.rgb = GOLD rule2.line.fill.background() # Verse lyrics lyric_box = slide.shapes.add_textbox(Inches(0.5), Inches(2.1), SLIDE_W - Inches(1.0), Inches(5.0)) tf3 = lyric_box.text_frame tf3.word_wrap = True lines = verse_text.split("\n") for i, line in enumerate(lines): if i == 0: p = tf3.paragraphs[0] else: p = tf3.add_paragraph() p.alignment = PP_ALIGN.CENTER run = p.add_run() run.text = line run.font.size = Pt(40) run.font.color.rgb = WHITE run.font.bold = False print(f" Added: {verse_label}") def main(): prs = Presentation() prs.slide_width = SLIDE_W prs.slide_height = SLIDE_H blank_layout = prs.slide_layouts[6] for label, text in VERSES: add_slide(prs, blank_layout, label, text) prs.save(OUT_PATH) print(f"\nSaved: {OUT_PATH} ({len(VERSES)} slides)") if __name__ == "__main__": main()