#!/usr/bin/env python3 """ Apply brand styling to PowerPoint presentations Customizes colors, fonts, and visual elements based on brand guidelines """ import json import argparse from pathlib import Path # Note: In production, install python-pptx via pip try: from pptx import Presentation from pptx.dml.color import RGBColor from pptx.util import Pt except ImportError: print("📦 Please install python-pptx: pip install python-pptx") exit(1) class BrandStyler: """Apply brand guidelines to PowerPoint presentations""" def __init__(self, brand_config_path: str): """Load brand configuration""" with open(brand_config_path, 'r') as f: self.brand_config = json.load(f) self.colors = self.brand_config.get('colors', {}) self.fonts = self.brand_config.get('fonts', {}) self.logos = self.brand_config.get('logos', {}) def apply_to_presentation(self, pptx_path: str, output_path: str = None): """Apply brand styling to PowerPoint file""" if not output_path: output_path = pptx_path.replace('.pptx', '_branded.pptx') print(f"🎨 Applying brand styles to: {pptx_path}") # Load presentation prs = Presentation(pptx_path) # Apply styles to each slide for slide_num, slide in enumerate(prs.slides, 1): self.style_slide(slide, slide_num) # Save branded version prs.save(output_path) print(f"✅ Branded presentation saved: {output_path}") return output_path def style_slide(self, slide, slide_num: int): """Apply brand styling to individual slide""" # Style text elements for shape in slide.shapes: if shape.has_text_frame: self.style_text_frame(shape.text_frame, slide_num) # Style tables if shape.has_table: self.style_table(shape.table) def style_text_frame(self, text_frame, slide_num: int): """Apply brand fonts and colors to text""" for paragraph in text_frame.paragraphs: for run in paragraph.runs: # Apply font if slide_num == 1: # Title slide run.font.name = self.fonts.get('heading', 'Arial') if paragraph.level == 0: run.font.size = Pt(44) else: run.font.name = self.fonts.get('body', 'Arial') # Apply colors based on context if slide_num == 1: # Title slide - white text run.font.color.rgb = RGBColor(255, 255, 255) elif paragraph.level == 0: # Headings color_hex = self.colors.get('primary', '#1a73e8').lstrip('#') run.font.color.rgb = RGBColor( int(color_hex[0:2], 16), int(color_hex[2:4], 16), int(color_hex[4:6], 16) ) else: # Body text color_hex = self.colors.get('text', '#3c4043').lstrip('#') run.font.color.rgb = RGBColor( int(color_hex[0:2], 16), int(color_hex[2:4], 16), int(color_hex[4:6], 16) ) def style_table(self, table): """Apply brand styling to tables""" # Style header row if len(table.rows) > 0: for cell in table.rows[0].cells: # Apply header background color if hasattr(cell, 'fill'): color_hex = self.colors.get('secondary', '#34a853').lstrip('#') # Note: python-pptx table cell fill is complex # This is simplified for example pass # Style table text for row in table.rows: for cell in row.cells: if cell.text_frame: for paragraph in cell.text_frame.paragraphs: for run in paragraph.runs: run.font.name = self.fonts.get('body', 'Arial') run.font.size = Pt(14) def add_logo(self, slide, position='top-right'): """Add company logo to slide""" logo_path = self.logos.get('primary') if not logo_path or not Path(logo_path).exists(): return # Position mappings positions = { 'top-right': {'left': 8.5, 'top': 0.25, 'width': 1.5}, 'bottom-right': {'left': 8.5, 'top': 4.75, 'width': 1.5}, 'top-left': {'left': 0.25, 'top': 0.25, 'width': 1.5} } pos = positions.get(position, positions['top-right']) # Add logo image # Note: Requires python-pptx inches conversion # slide.shapes.add_picture(logo_path, left, top, width) def main(): parser = argparse.ArgumentParser( description="Apply brand styling to PowerPoint presentations" ) parser.add_argument( "presentation", help="Path to PowerPoint presentation" ) parser.add_argument( "--config", default="assets/brand_config.json", help="Path to brand configuration JSON" ) parser.add_argument( "--output", help="Output path for branded presentation" ) args = parser.parse_args() # Apply branding styler = BrandStyler(args.config) output_path = styler.apply_to_presentation( args.presentation, args.output ) print(f"✨ Brand styling complete: {output_path}") if __name__ == "__main__": main()