ppt-template-creator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PPT Template Creator

PPT模板Skill生成器

This skill creates SKILLS, not presentations. Use this when a user wants to turn their PowerPoint template into a reusable skill that can generate presentations later. If the user just wants to create a presentation, use the
pptx
skill instead.
The generated skill includes:
  • assets/template.pptx
    - the template file
  • SKILL.md
    - complete instructions (no reference to this meta skill needed)
For general skill-building best practices, refer to the
skill-creator
skill. This skill focuses on PPT-specific patterns.
此Skill用于生成SKILL,而非演示文稿。 当用户希望将其PowerPoint模板转换为可复用的、后续可用于生成演示文稿的Skill时使用此工具。如果用户只是想创建演示文稿,请改用
pptx
skill。
生成的Skill包含:
  • assets/template.pptx
    - 模板文件
  • SKILL.md
    - 完整的使用说明(无需参考此元Skill)
关于Skill构建的通用最佳实践,请参考
skill-creator
skill。本Skill专注于PPT相关的特定模式。

Workflow

工作流程

  1. User provides template (.pptx or .potx)
  2. Analyze template - extract layouts, placeholders, dimensions
  3. Initialize skill - use the
    skill-creator
    skill to set up the skill structure
  4. Add template - copy .pptx to
    assets/template.pptx
  5. Write SKILL.md - follow template below with PPT-specific details
  6. Create example - generate sample presentation to validate
  7. Package - use the
    skill-creator
    skill to package into a .skill file
  1. 用户提供模板(.pptx或.potx格式)
  2. 分析模板 - 提取版式、占位符、尺寸
  3. 初始化Skill - 使用
    skill-creator
    skill搭建Skill结构
  4. 添加模板 - 将.pptx文件复制到
    assets/template.pptx
  5. 编写SKILL.md - 遵循下方针对PPT的特定模板填写细节
  6. 创建示例 - 生成样例演示文稿以验证功能
  7. 打包 - 使用
    skill-creator
    skill将其打包为.skill文件

Step 2: Analyze Template

步骤2:分析模板

CRITICAL: Extract precise placeholder positions - this determines content area boundaries.
python
from pptx import Presentation

prs = Presentation(template_path)
print(f"Dimensions: {prs.slide_width/914400:.2f}\" x {prs.slide_height/914400:.2f}\"")
print(f"Layouts: {len(prs.slide_layouts)}")

for idx, layout in enumerate(prs.slide_layouts):
    print(f"\n[{idx}] {layout.name}:")
    for ph in layout.placeholders:
        try:
            ph_idx = ph.placeholder_format.idx
            ph_type = ph.placeholder_format.type
            # IMPORTANT: Extract exact positions in inches
            left = ph.left / 914400
            top = ph.top / 914400
            width = ph.width / 914400
            height = ph.height / 914400
            print(f"    idx={ph_idx}, type={ph_type}")
            print(f"        x={left:.2f}\", y={top:.2f}\", w={width:.2f}\", h={height:.2f}\"")
        except:
            pass
Key measurements to document:
  • Title position: Where does the title placeholder sit?
  • Subtitle/description: Where is the subtitle line?
  • Footer placeholders: Where do footers/sources appear?
  • Content area: The space BETWEEN subtitle and footer is your content area
重要提示:提取精确的占位符位置 - 这将决定内容区域的边界。
python
from pptx import Presentation

prs = Presentation(template_path)
print(f"Dimensions: {prs.slide_width/914400:.2f}\" x {prs.slide_height/914400:.2f}\"")
print(f"Layouts: {len(prs.slide_layouts)}")

for idx, layout in enumerate(prs.slide_layouts):
    print(f"\n[{idx}] {layout.name}:")
    for ph in layout.placeholders:
        try:
            ph_idx = ph.placeholder_format.idx
            ph_type = ph.placeholder_format.type
            # IMPORTANT: Extract exact positions in inches
            left = ph.left / 914400
            top = ph.top / 914400
            width = ph.width / 914400
            height = ph.height / 914400
            print(f"    idx={ph_idx}, type={ph_type}")
            print(f"        x={left:.2f}\", y={top:.2f}\", w={width:.2f}\", h={height:.2f}\"")
        except:
            pass
需要记录的关键测量数据:
  • 标题位置:标题占位符的位置
  • 副标题/描述:副标题行的位置
  • 页脚占位符:页脚/来源信息的显示位置
  • 内容区域:副标题和页脚之间的区域即为内容区域

Finding the True Content Start Position

确定实际内容起始位置

CRITICAL: The content area does NOT always start immediately after the subtitle placeholder. Many templates have a visual border, line, or reserved space between the subtitle and content area.
Best approach: Look at Layout 2 or similar "content" layouts that have an OBJECT placeholder - this placeholder's
y
position indicates where content should actually start.
python
undefined
重要提示: 内容区域并非总是紧跟在副标题占位符之后。许多模板在副标题和内容区域之间预留了边框、线条或空白空间。
最佳方法: 查看版式2或类似的“内容”版式,其中包含OBJECT占位符 - 该占位符的
y
坐标表示内容实际应开始的位置。
python
undefined

Find the OBJECT placeholder to determine true content start

Find the OBJECT placeholder to determine true content start

for idx, layout in enumerate(prs.slide_layouts): for ph in layout.placeholders: try: if ph.placeholder_format.type == 7: # OBJECT type top = ph.top / 914400 print(f"Layout [{idx}] {layout.name}: OBJECT starts at y={top:.2f}"") # This y value is where your content should start! except: pass

**Example:** A template might have:
- Subtitle ending at y=1.38"
- But OBJECT placeholder starting at y=1.90"
- The gap (0.52") is reserved for a border/line - **do not place content there**

Use the OBJECT placeholder's `y` position as your content start, not the subtitle's end position.
for idx, layout in enumerate(prs.slide_layouts): for ph in layout.placeholders: try: if ph.placeholder_format.type == 7: # OBJECT type top = ph.top / 914400 print(f"Layout [{idx}] {layout.name}: OBJECT starts at y={top:.2f}"") # This y value is where your content should start! except: pass

**示例:** 某个模板可能有以下设置:
- 副标题结束于y=1.38"
- 但OBJECT占位符起始于y=1.90"
- 两者之间的间隙(0.52")是为边框/线条预留的 - **请勿在此处放置内容**

请使用OBJECT占位符的`y`坐标作为内容起始位置,而非副标题的结束位置。

Step 5: Write SKILL.md

步骤5:编写SKILL.md

The generated skill should have this structure:
[company]-ppt-template/
├── SKILL.md
└── assets/
    └── template.pptx
生成的Skill应具有以下结构:
[company]-ppt-template/
├── SKILL.md
└── assets/
    └── template.pptx

Generated SKILL.md Template

生成的SKILL.md模板

The generated SKILL.md must be self-contained with all instructions embedded. Use this template, filling in the bracketed values from your analysis:
markdown
---
name: [company]-ppt-template
description: [Company] PowerPoint template for creating presentations. Use when creating [Company]-branded pitch decks, board materials, or client presentations.
---
生成的SKILL.md必须是独立的,包含所有嵌入的说明。使用以下模板,将分析得到的括号内的值填充进去:
markdown
---
name: [company]-ppt-template
description: [Company] PowerPoint template for creating presentations. Use when creating [Company]-branded pitch decks, board materials, or client presentations.
---

[Company] PPT Template

[Company] PPT Template

Template:
assets/template.pptx
([WIDTH]" x [HEIGHT]", [N] layouts)
Template:
assets/template.pptx
([WIDTH]" x [HEIGHT]", [N] layouts)

Creating Presentations

创建演示文稿

python
from pptx import Presentation

prs = Presentation("path/to/skill/assets/template.pptx")
python
from pptx import Presentation

prs = Presentation("path/to/skill/assets/template.pptx")

DELETE all existing slides first

DELETE all existing slides first

while len(prs.slides) > 0: rId = prs.slides._sldIdLst[0].rId prs.part.drop_rel(rId) del prs.slides._sldIdLst[0]
while len(prs.slides) > 0: rId = prs.slides._sldIdLst[0].rId prs.part.drop_rel(rId) del prs.slides._sldIdLst[0]

Add slides from layouts

Add slides from layouts

slide = prs.slides.add_slide(prs.slide_layouts[LAYOUT_IDX])
undefined
slide = prs.slides.add_slide(prs.slide_layouts[LAYOUT_IDX])
undefined

Key Layouts

主要版式

IndexNameUse For
[0][Layout Name][Cover/title slide]
[N][Layout Name][Content with bullets]
[N][Layout Name][Two-column layout]
索引名称用途
[0][Layout Name][封面/标题幻灯片]
[N][Layout Name][带项目符号的内容幻灯片]
[N][Layout Name][双栏版式]

Placeholder Mapping

占位符映射

CRITICAL: Include exact positions (x, y coordinates) for each placeholder.
重要提示:请包含每个占位符的精确位置(x、y坐标)。

Layout [N]: [Name]

版式 [N]:[名称]

idxTypePositionUse
[idx]TITLE (1)y=[Y]"Slide title
[idx]BODY (2)y=[Y]"Subtitle/description
[idx]BODY (2)y=[Y]"Footer
[idx]BODY (2)y=[Y]"Source/notes
索引类型位置用途
[idx]TITLE (1)y=[Y]"幻灯片标题
[idx]BODY (2)y=[Y]"副标题/描述
[idx]BODY (2)y=[Y]"页脚
[idx]BODY (2)y=[Y]"来源/备注

Content Area Boundaries

内容区域边界

Document the safe content area for custom shapes/tables/charts:
Content Area (for Layout [N]):
- Left margin: [X]" (content starts here)
- Top: [Y]" (below subtitle placeholder)
- Width: [W]"
- Height: [H]" (ends before footer)

For 4-quadrant layouts:
- Left column: x=[X]", width=[W]"
- Right column: x=[X]", width=[W]"
- Top row: y=[Y]", height=[H]"
- Bottom row: y=[Y]", height=[H]"
Why this matters: Custom content (textboxes, tables, charts) must stay within these boundaries to avoid overlapping with template placeholders like titles, footers, and source lines.
记录自定义形状/表格/图表的安全内容区域:
Content Area (for Layout [N]):
- Left margin: [X]" (content starts here)
- Top: [Y]" (below subtitle placeholder)
- Width: [W]"
- Height: [H]" (ends before footer)

For 4-quadrant layouts:
- Left column: x=[X]", width=[W]"
- Right column: x=[X]", width=[W]"
- Top row: y=[Y]", height=[H]"
- Bottom row: y=[Y]", height=[H]"
为什么这很重要: 自定义内容(文本框、表格、图表)必须保持在这些边界内,以避免与模板中的占位符(如标题、页脚和来源行)重叠。

Filling Content

填充内容

Do NOT add manual bullet characters - slide master handles formatting.
python
undefined
请勿手动添加项目符号字符 - 幻灯片母版会处理格式。
python
undefined

Fill title

Fill title

for shape in slide.shapes: if hasattr(shape, 'placeholder_format'): if shape.placeholder_format.type == 1: # TITLE shape.text = "Slide Title"
for shape in slide.shapes: if hasattr(shape, 'placeholder_format'): if shape.placeholder_format.type == 1: # TITLE shape.text = "Slide Title"

Fill content with hierarchy (level 0 = header, level 1 = bullet)

Fill content with hierarchy (level 0 = header, level 1 = bullet)

for shape in slide.shapes: if hasattr(shape, 'placeholder_format'): idx = shape.placeholder_format.idx if idx == [CONTENT_IDX]: tf = shape.text_frame for para in tf.paragraphs: para.clear()
        content = [
            ("Section Header", 0),
            ("First bullet point", 1),
            ("Second bullet point", 1),
        ]

        tf.paragraphs[0].text = content[0][0]
        tf.paragraphs[0].level = content[0][1]
        for text, level in content[1:]:
            p = tf.add_paragraph()
            p.text = text
            p.level = level
undefined
for shape in slide.shapes: if hasattr(shape, 'placeholder_format'): idx = shape.placeholder_format.idx if idx == [CONTENT_IDX]: tf = shape.text_frame for para in tf.paragraphs: para.clear()
        content = [
            ("Section Header", 0),
            ("First bullet point", 1),
            ("Second bullet point", 1),
        ]

        tf.paragraphs[0].text = content[0][0]
        tf.paragraphs[0].level = content[0][1]
        for text, level in content[1:]:
            p = tf.add_paragraph()
            p.text = text
            p.level = level
undefined

Example: Cover Slide

示例:封面幻灯片

python
slide = prs.slides.add_slide(prs.slide_layouts[[COVER_IDX]])
for shape in slide.shapes:
    if hasattr(shape, 'placeholder_format'):
        idx = shape.placeholder_format.idx
        if idx == [TITLE_IDX]:
            shape.text = "Company Name"
        elif idx == [SUBTITLE_IDX]:
            shape.text = "Presentation Title | Date"
python
slide = prs.slides.add_slide(prs.slide_layouts[[COVER_IDX]])
for shape in slide.shapes:
    if hasattr(shape, 'placeholder_format'):
        idx = shape.placeholder_format.idx
        if idx == [TITLE_IDX]:
            shape.text = "Company Name"
        elif idx == [SUBTITLE_IDX]:
            shape.text = "Presentation Title | Date"

Example: Content Slide

示例:内容幻灯片

python
slide = prs.slides.add_slide(prs.slide_layouts[[CONTENT_IDX]])
for shape in slide.shapes:
    if hasattr(shape, 'placeholder_format'):
        ph_type = shape.placeholder_format.type
        idx = shape.placeholder_format.idx
        if ph_type == 1:
            shape.text = "Executive Summary"
        elif idx == [BODY_IDX]:
            tf = shape.text_frame
            for para in tf.paragraphs:
                para.clear()
            content = [
                ("Key Findings", 0),
                ("Revenue grew 40% YoY to $50M", 1),
                ("Expanded to 3 new markets", 1),
                ("Recommendation", 0),
                ("Proceed with strategic initiative", 1),
            ]
            tf.paragraphs[0].text = content[0][0]
            tf.paragraphs[0].level = content[0][1]
            for text, level in content[1:]:
                p = tf.add_paragraph()
                p.text = text
                p.level = level
undefined
python
slide = prs.slides.add_slide(prs.slide_layouts[[CONTENT_IDX]])
for shape in slide.shapes:
    if hasattr(shape, 'placeholder_format'):
        ph_type = shape.placeholder_format.type
        idx = shape.placeholder_format.idx
        if ph_type == 1:
            shape.text = "Executive Summary"
        elif idx == [BODY_IDX]:
            tf = shape.text_frame
            for para in tf.paragraphs:
                para.clear()
            content = [
                ("Key Findings", 0),
                ("Revenue grew 40% YoY to $50M", 1),
                ("Expanded to 3 new markets", 1),
                ("Recommendation", 0),
                ("Proceed with strategic initiative", 1),
            ]
            tf.paragraphs[0].text = content[0][0]
            tf.paragraphs[0].level = content[0][1]
            for text, level in content[1:]:
                p = tf.add_paragraph()
                p.text = text
                p.level = level
undefined

Step 6: Create Example Output

步骤6:创建示例输出

Generate a sample presentation to validate the skill works. Save it alongside the skill for reference.
生成样例演示文稿以验证Skill功能。将其与Skill保存在一起作为参考。

PPT-Specific Rules for Generated Skills

生成Skill的PPT特定规则

  1. Template in assets/ - always bundle the .pptx file
  2. Self-contained SKILL.md - all instructions embedded, no external references
  3. No manual bullets - use
    paragraph.level
    for hierarchy
  4. Delete slides first - always clear existing slides before adding new ones
  5. Document placeholders by idx - placeholder idx values are template-specific
  1. 模板存放于assets/目录 - 始终将.pptx文件打包在内
  2. SKILL.md独立完整 - 包含所有说明,无外部引用
  3. 请勿手动添加项目符号 - 使用
    paragraph.level
    设置层级
  4. 先删除现有幻灯片 - 添加新幻灯片前务必清除所有现有幻灯片
  5. 按索引记录占位符 - 占位符索引值是模板特有的