Claude
Skills
Sign in
Back

pptx-construction

Included with Lifetime
$97 forever

PowerPoint generation for construction: project updates, stakeholder presentations, progress reports, bid presentations. Automated slide creation with charts and data.

Writing & Docs

What this skill does

# PowerPoint Generation for Construction

## Overview

Create professional PowerPoint presentations for construction projects using python-pptx. Generate stakeholder updates, progress reports, and bid presentations with automated data visualization.

## Construction Use Cases

### 1. Project Progress Presentation

Generate monthly progress update slides.

```python
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.chart import XL_CHART_TYPE
from pptx.chart.data import CategoryChartData
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN

def create_progress_presentation(project_data: dict, output_path: str) -> str:
    """Create project progress presentation."""
    prs = Presentation()
    prs.slide_width = Inches(13.333)
    prs.slide_height = Inches(7.5)

    # Title slide
    title_slide = prs.slides.add_slide(prs.slide_layouts[0])
    title_slide.shapes.title.text = project_data['project_name']
    title_slide.placeholders[1].text = f"Progress Report - {project_data['report_date']}"

    # Executive Summary slide
    summary_slide = prs.slides.add_slide(prs.slide_layouts[1])
    summary_slide.shapes.title.text = "Executive Summary"

    summary_text = summary_slide.placeholders[1]
    tf = summary_text.text_frame
    tf.paragraphs[0].text = f"Overall Progress: {project_data['overall_progress']}%"

    p = tf.add_paragraph()
    p.text = f"Schedule Status: {project_data['schedule_status']}"
    p = tf.add_paragraph()
    p.text = f"Budget Status: {project_data['budget_status']}"
    p = tf.add_paragraph()
    p.text = f"Safety: {project_data['safety_status']}"

    # Schedule Progress Chart
    add_schedule_chart(prs, project_data['schedule_data'])

    # Budget Chart
    add_budget_chart(prs, project_data['budget_data'])

    # Key Milestones
    add_milestones_slide(prs, project_data['milestones'])

    # Issues & Risks
    add_issues_slide(prs, project_data.get('issues', []))

    # Photos
    if project_data.get('photos'):
        add_photos_slide(prs, project_data['photos'])

    prs.save(output_path)
    return output_path


def add_schedule_chart(prs: Presentation, schedule_data: dict):
    """Add schedule progress chart."""
    slide = prs.slides.add_slide(prs.slide_layouts[5])
    slide.shapes.title.text = "Schedule Progress"

    chart_data = CategoryChartData()
    chart_data.categories = schedule_data['phases']
    chart_data.add_series('Planned', schedule_data['planned'])
    chart_data.add_series('Actual', schedule_data['actual'])

    chart = slide.shapes.add_chart(
        XL_CHART_TYPE.COLUMN_CLUSTERED,
        Inches(1), Inches(1.5),
        Inches(11), Inches(5),
        chart_data
    ).chart

    chart.has_legend = True
    chart.legend.include_in_layout = False


def add_budget_chart(prs: Presentation, budget_data: dict):
    """Add budget status chart."""
    slide = prs.slides.add_slide(prs.slide_layouts[5])
    slide.shapes.title.text = "Budget Status"

    chart_data = CategoryChartData()
    chart_data.categories = ['Budget', 'Committed', 'Spent', 'Forecast']
    chart_data.add_series('Amount ($M)', [
        budget_data['budget'] / 1_000_000,
        budget_data['committed'] / 1_000_000,
        budget_data['spent'] / 1_000_000,
        budget_data['forecast'] / 1_000_000
    ])

    chart = slide.shapes.add_chart(
        XL_CHART_TYPE.BAR_CLUSTERED,
        Inches(1), Inches(1.5),
        Inches(11), Inches(5),
        chart_data
    ).chart


def add_milestones_slide(prs: Presentation, milestones: list):
    """Add key milestones slide."""
    slide = prs.slides.add_slide(prs.slide_layouts[5])
    slide.shapes.title.text = "Key Milestones"

    # Create table
    rows = len(milestones) + 1
    cols = 4
    table = slide.shapes.add_table(rows, cols, Inches(0.5), Inches(1.5), Inches(12), Inches(0.5 * rows)).table

    # Headers
    headers = ['Milestone', 'Planned', 'Actual/Forecast', 'Status']
    for i, header in enumerate(headers):
        table.cell(0, i).text = header

    # Data
    for i, ms in enumerate(milestones, 1):
        table.cell(i, 0).text = ms['name']
        table.cell(i, 1).text = ms['planned_date']
        table.cell(i, 2).text = ms.get('actual_date', ms.get('forecast_date', 'TBD'))
        table.cell(i, 3).text = ms['status']


def add_issues_slide(prs: Presentation, issues: list):
    """Add issues and risks slide."""
    slide = prs.slides.add_slide(prs.slide_layouts[1])
    slide.shapes.title.text = "Issues & Risks"

    if not issues:
        slide.placeholders[1].text = "No critical issues at this time."
        return

    tf = slide.placeholders[1].text_frame
    for i, issue in enumerate(issues):
        if i == 0:
            tf.paragraphs[0].text = f"• {issue['description']} ({issue['status']})"
        else:
            p = tf.add_paragraph()
            p.text = f"• {issue['description']} ({issue['status']})"


def add_photos_slide(prs: Presentation, photos: list):
    """Add site photos slide."""
    slide = prs.slides.add_slide(prs.slide_layouts[5])
    slide.shapes.title.text = "Site Progress Photos"

    # Arrange up to 4 photos in grid
    positions = [
        (Inches(0.5), Inches(1.5)),
        (Inches(6.5), Inches(1.5)),
        (Inches(0.5), Inches(4)),
        (Inches(6.5), Inches(4))
    ]

    for i, photo in enumerate(photos[:4]):
        left, top = positions[i]
        slide.shapes.add_picture(photo['path'], left, top, width=Inches(5.5))
```

### 2. Bid Presentation

Create bid/proposal presentations.

```python
def create_bid_presentation(bid_data: dict, output_path: str) -> str:
    """Create bid presentation for client."""
    prs = Presentation()

    # Title
    title_slide = prs.slides.add_slide(prs.slide_layouts[0])
    title_slide.shapes.title.text = bid_data['project_name']
    title_slide.placeholders[1].text = f"Proposal by {bid_data['company_name']}"

    # Company Overview
    overview_slide = prs.slides.add_slide(prs.slide_layouts[1])
    overview_slide.shapes.title.text = "About Us"
    tf = overview_slide.placeholders[1].text_frame
    tf.paragraphs[0].text = f"Years in Business: {bid_data['company']['years']}"
    for qual in bid_data['company']['qualifications']:
        p = tf.add_paragraph()
        p.text = f"• {qual}"

    # Project Understanding
    understanding_slide = prs.slides.add_slide(prs.slide_layouts[1])
    understanding_slide.shapes.title.text = "Project Understanding"
    tf = understanding_slide.placeholders[1].text_frame
    for i, point in enumerate(bid_data['understanding']):
        if i == 0:
            tf.paragraphs[0].text = f"• {point}"
        else:
            p = tf.add_paragraph()
            p.text = f"• {point}"

    # Approach
    approach_slide = prs.slides.add_slide(prs.slide_layouts[1])
    approach_slide.shapes.title.text = "Our Approach"
    tf = approach_slide.placeholders[1].text_frame
    for i, step in enumerate(bid_data['approach']):
        if i == 0:
            tf.paragraphs[0].text = f"{i+1}. {step}"
        else:
            p = tf.add_paragraph()
            p.text = f"{i+1}. {step}"

    # Team
    team_slide = prs.slides.add_slide(prs.slide_layouts[1])
    team_slide.shapes.title.text = "Project Team"
    tf = team_slide.placeholders[1].text_frame
    for i, member in enumerate(bid_data['team']):
        if i == 0:
            tf.paragraphs[0].text = f"{member['role']}: {member['name']}"
        else:
            p = tf.add_paragraph()
            p.text = f"{member['role']}: {member['name']}"

    # Pricing Summary
    pricing_slide = prs.slides.add_slide(prs.slide_layouts[5])
    pricing_slide.shapes.title.text = "Investment Summary"

    # Add pricing table
    rows = len(bid_data['pricing']['items']) + 2
    table = pricing_slide.shapes.add_table(rows, 2, Inches(2), Inches(2), Inches(8), Inches(0.5 * rows)).table

    table.cell(0, 0).text = "Description"
    table.cell(0, 1).text = "Amount"

    for i, item in enumerate(bid_data['pricing']['items'

Related in Writing & Docs