| name | mck-ppt-design |
| description | Create professional, consultant-grade PowerPoint presentations from scratch using MckEngine (python-pptx wrapper) with McKinsey-style design. Use when user asks to create slides, pitch decks, business presentations, strategy decks, quarterly reviews, board meeting slides, or any professional PPTX. AI calls eng.cover(), eng.donut(), eng.timeline() etc โ 67 high-level methods across 12 categories (structure, data, framework, comparison, narrative, timeline, team, charts, images, advanced viz, dashboards, visual storytelling), consistent typography, zero file-corruption issues, BLOCK_ARC native shapes for circular charts (donut, pie, gauge), production-hardened guard rails for spacing, overflow, legend consistency, title style uniformity, dynamic sizing for variable-count layouts, horizontal item overflow protection, chart rendering, and AI-generated cover images via Tencent Hunyuan 2.0 with professional cutout, cool grey-blue tint, and McKinsey-style Bรฉzier ribbon decoration. |
McKinsey PPT Design Framework
Copyright ยฉ 2024-2026 Kaku Li (https://github.com/likaku). Licensed under Apache 2.0. See NOTICE.
Version: 2.2.0 ยท License: Apache-2.0 ยท Author: likaku
Required tools: Read, Write, Bash ยท Requires: python3, pip
Overview
This skill encodes the complete design specification for professional business presentations โ a consultant-grade PowerPoint framework based on McKinsey design principles. It includes:
- 65 layout patterns across 12 categories (structure, data, framework, comparison, narrative, timeline, team, charts, images, advanced viz, dashboards, visual storytelling)
- Color system and strict typography hierarchy
- Python-pptx code patterns ready to copy and customize
- Three-layer defense against file corruption (zero
p:style leaks)
- Chinese + English font handling (KaiTi / Georgia / Arial)
- Image placeholder system for image-containing layouts (v1.8)
- BLOCK_ARC native shapes for charts โ donut, pie, gauge rendered with 3-4 shapes instead of hundreds of blocks, 60-80% smaller files (v2.0)
- Production Guard Rails โ 10 mandatory rules including spacing/overflow protection, legend color consistency, title style uniformity, axis label centering, dynamic sizing, BLOCK_ARC chart rendering, horizontal item overflow protection (v1.9+v2.0+v2.3)
- Code Efficiency guidelines โ variable reuse patterns, constant extraction, loop optimization for faster generation (v1.9)
- AI-generated cover images โ Tencent Hunyuan 2.0 text-to-image โ rembg professional cutout โ cool grey-blue tint + 50% lighten โ McKinsey-style Bรฉzier ribbon curves โ transparent RGBA PNG full-bleed background (v2.2)
All specifications have been refined through iterative production feedback to ensure visual consistency, professional polish, and zero-defect output.
When to Use This Skill
Use this skill when users ask to:
- Create presentations โ pitch decks, strategy presentations, quarterly reviews, board meeting slides, consulting deliverables, project proposals, business plans
- Generate slides programmatically โ using python-pptx to produce .pptx files from scratch
- Apply professional design โ McKinsey / BCG / Bain consulting style, clean flat design, no shadows or gradients
- Build specific slide types โ cover pages, data dashboards, 2x2 matrices, timelines, funnels, team introductions, executive summaries, comparison layouts
- Fix PPT issues โ file corruption ("needs repair"), shadow/3D artifacts, inconsistent fonts, Chinese text rendering problems
- Maintain design consistency โ unified color palette, font hierarchy, spacing, and line treatments across all slides
MckEngine Quick Start (v2.0)
v2.0 introduces a Python runtime engine (mck_ppt/) that encapsulates all 67 layout methods. Instead of writing raw add_shape() / add_text() coordinate code, the AI calls high-level methods like eng.cover(), eng.donut(), eng.timeline().
Why Use MckEngine
| v1.x (inline code) | v2.0 (MckEngine) |
|---|
| Code generation | AI writes add_shape() + coordinate math per slide | AI calls eng.cover(), eng.donut() etc. |
| Output tokens per 30-slide deck | 40,000โ60,000 | 9,000โ12,000 |
| Rounds per deck | 10โ15 | 3โ4 |
| Chart rendering | add_rect() stacking (100โ2,800 shapes) | BLOCK_ARC native arcs (3โ4 shapes) |
| File corruption risk | Manual cleanup needed | Automatic three-layer defense |
Setup
pip install python-pptx lxml
The mck_ppt/ package lives inside the skill directory. Before generating any presentation, the AI MUST:
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
from mck_ppt import MckEngine
Complete Generation Pattern
Every presentation script follows this exact pattern:
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
from mck_ppt import MckEngine
from mck_ppt.constants import *
from pptx.util import Inches
eng = MckEngine(total_slides=12)
eng.cover(title='Q1 2026 ๆ็ฅๅ้กพ', subtitle='่ฃไบไผๆฑๆฅ', author='ๆ็ฅ้จ', date='2026ๅนด3ๆ', cover_image='auto')
eng.toc(items=[('1', 'ๅธๅบๆฆ่ง', 'ๅฝๅ็ซไบๆ ผๅฑ'),
('2', '่ดขๅกๅๆ', '่ฅๆถไธๅฉๆถฆ่ถๅฟ'),
('3', 'ๆ็ฅๅปบ่ฎฎ', 'ไธๅคงๆ ธๅฟ่กๅจ')])
eng.section_divider(section_label='็ฌฌไธ้จๅ', title='ๅธๅบๆฆ่ง')
eng.big_number(title='ๅธๅบ่งๆจก', number='ยฅ850ไบฟ', description='2026ๅนด้ขไผฐๅธๅบๆป้',
detail_items=['ๅๆฏๅข้ฟ23%', '็บฟไธๆธ ้ๅ ๆฏ็ช็ ด60%'], source='Source: ่กไธๆฅๅ 2026')
eng.donut(title='ๅธๅบไปฝ้ขๅๅธ',
segments=[(0.35, NAVY, 'ๆไปฌ'), (0.25, ACCENT_BLUE, '็ซๅA'),
(0.20, ACCENT_GREEN, '็ซๅB'), (0.20, ACCENT_ORANGE, 'ๅ
ถไป')],
center_label='35%', center_sub='ๅธๅ ็', source='Source: ๅธๅบ่ฐ็ 2026')
eng.section_divider(section_label='็ฌฌไบ้จๅ', title='่ดขๅกๅๆ')
eng.grouped_bar(title='ๅญฃๅบฆ่ฅๆถ่ถๅฟ',
categories=['Q1', 'Q2', 'Q3', 'Q4'],
series=[('ไบงๅ', NAVY), ('ๆๅก', ACCENT_BLUE)],
data=[[120, 80], [145, 95], [160, 110], [180, 130]],
max_val=200, source='Source: ่ดขๅก้จ')
eng.section_divider(section_label='็ฌฌไธ้จๅ', title='ๆ็ฅๅปบ่ฎฎ')
eng.table_insight(title='ไธๅคงๆ็ฅๆนๅๅฏนๆฏ',
headers=['ๆ็ฅๆนๅ', 'ๆ ธๅฟไธพๆช', '้ขๆๆๆ'],
rows=[['ไบงๅๅๆฐ', 'AI่ต่ฝ + ็จๆทไฝ้ชๅ็บง', 'ๅธๅบไปฝ้ข+15%'],
['ๅธๅบๆๅฑ', '่ฟๅ
ฅ3ไธชๆฐ่กไธ + ๆตทๅคๅธๅฑ', '่ฅๆถๅข้ฟ30%'],
['่ฟ่ฅๅ่ถ', 'ๆๆฌไผๅ20% + ๆฐๅญๅ่ฆ็85%', 'ๅฉๆถฆ็+8pp']],
insights=['ไธๅคงๆนๅๅๅๅๅ๏ผๅฝขๆๅข้ฟ้ฃ่ฝฎ', 'ไบงๅๅๆฐไธบๅผๆ๏ผๅธๅบๆๅฑไธบๆ ๆ', '่ฟ่ฅๅ่ถไธบๅบๅบง๏ผ็กฎไฟๅฏๆ็ปญๆง'],
source='Source: ๆ็ฅ้จ')
eng.timeline(title='ๆง่ก่ทฏ็บฟๅพ',
milestones=[('Q1', 'ๆนๆก่ฎพ่ฎก'), ('Q2', '่ฏ็น้ช่ฏ'),
('Q3', '่งๆจกๆจๅนฟ'), ('Q4', 'ๆๆ่ฏไผฐ')],
source='Source: PMO')
eng.closing(title='่ฐข่ฐข', message='ๆๅพ
ไธๆจ่ฟไธๆญฅไบคๆต')
eng.save('output/q1_strategy_review.pptx')
print('Done! 12 slides generated.')
Key Rules
- One method = one slide.
eng.cover() creates slide 1, eng.toc() creates slide 2, etc.
eng.save() handles everything โ XML cleanup, shadow removal, p:style sanitization. No manual full_cleanup() needed.
- Page numbers are automatic โ the engine tracks
_page internally.
- All guard rails are built-in โ dynamic sizing, overflow protection, CJK font handling.
- Use constants from
mck_ppt.constants โ NAVY, ACCENT_BLUE, BG_GRAY, BODY_SIZE, etc.
Core Design Philosophy
McKinsey Design Principles
-
Extreme Minimalism - Remove all non-essential visual elements
- No color blocks unless absolutely necessary
- Lines: thin, flat, no shadows or 3D effects
- Shapes: simple, clean, no gradients
- Text: clear hierarchy, maximum readability
-
Consistency - Repeat visual language across all slides
- Unified color palette (navy + cyan + grays)
- Consistent font sizes and weights for same content types
- Aligned spacing and margins
- Matching line widths and styles
-
Hierarchy - Guide viewer through information
- Title bar (22pt) โ Sub-headers (18pt) โ Body (14pt) โ Details (9pt)
- Navy for primary elements, gray for secondary, black for divisions
- Visual weight through bold, color, size (not through effects)
-
Flat Design - No 3D, shadows, or gradients
- Pure solid colors only
- All lines are simple strokes with no effects
- Shapes have no shadow or reflection effects
- Circles are solid fills, not 3D spheres
Design Specifications
Color Palette
All colors in RGB format for python-pptx:
| Color Name | Hex | RGB | Usage | Notes |
|---|
| NAVY | #051C2C | (5, 28, 44) | Primary, titles, circles | Corporate, formal tone |
| CYAN | #00A9F4 | (0, 169, 244) | Originally used in v1 | DEPRECATED - Use NAVY for consistency |
| WHITE | #FFFFFF | (255, 255, 255) | Backgrounds, text | On navy backgrounds only |
| BLACK | #000000 | (0, 0, 0) | Lines, text separators | For clarity and contrast |
| DARK_GRAY | #333333 | (51, 51, 51) | Body text, descriptions | Main content text |
| MED_GRAY | #666666 | (102, 102, 102) | Secondary text, labels | Softer tone than DARK_GRAY |
| LINE_GRAY | #CCCCCC | (204, 204, 204) | Light separators, table rows | Table separators only |
| BG_GRAY | #F2F2F2 | (242, 242, 242) | Background panels | Takeaway/highlight areas |
Key Rule: Use navy (#051C2C) everywhere, especially for:
- All circle indicators (A, B, C, 1, 2, 3)
- All action titles
- All primary section headers
- All TOC highlight colors
Accent Colors (for multi-item differentiation)
When a slide contains 3 or more parallel items (e.g., comparison cards, pillar frameworks, multi-category overviews), use these accent colors to create visual distinction between items. Without accent colors, parallel items become visually indistinguishable.
| Accent Name | Hex | RGB | Paired Light BG | Usage |
|---|
| ACCENT_BLUE | #006BA6 | (0, 107, 166) | #E3F2FD | First item accent |
| ACCENT_GREEN | #007A53 | (0, 122, 83) | #E8F5E9 | Second item accent |
| ACCENT_ORANGE | #D46A00 | (212, 106, 0) | #FFF3E0 | Third item accent |
| ACCENT_RED | #C62828 | (198, 40, 40) | #FFEBEE | Fourth item / warning |
Accent Color Rules:
- Use accent colors for: card top accent borders (thin 0.06" rect), circle labels (
add_oval() bg param), section sub-headers (font_color)
- Use paired light BG for: card background fills only
- Body text inside cards ALWAYS remains DARK_GRAY (#333333)
- NAVY remains the primary color for single-focus elements (one card, one stat, cover title)
- Use accent colors ONLY when the slide has 3+ parallel items that need visual distinction
- The fourth item (D) can use NAVY instead of ACCENT_RED if red feels inappropriate for the content
ACCENT_BLUE = RGBColor(0x00, 0x6B, 0xA6)
ACCENT_GREEN = RGBColor(0x00, 0x7A, 0x53)
ACCENT_ORANGE = RGBColor(0xD4, 0x6A, 0x00)
ACCENT_RED = RGBColor(0xC6, 0x28, 0x28)
LIGHT_BLUE = RGBColor(0xE3, 0xF2, 0xFD)
LIGHT_GREEN = RGBColor(0xE8, 0xF5, 0xE9)
LIGHT_ORANGE = RGBColor(0xFF, 0xF3, 0xE0)
LIGHT_RED = RGBColor(0xFF, 0xEB, 0xEE)
Typography System
Font Families
English Headers: Georgia (serif, elegant)
English Body: Arial (sans-serif, clean)
Chinese (ALL): KaiTi (ๆฅทไฝ, traditional brush style)
(fallback: SimSun ๅฎไฝ)
Critical Implementation:
def set_ea_font(run, typeface='KaiTi'):
"""Set East Asian font for Chinese text"""
rPr = run._r.get_or_add_rPr()
ea = rPr.find(qn('a:ea'))
if ea is None:
ea = rPr.makeelement(qn('a:ea'), {})
rPr.append(ea)
ea.set('typeface', typeface)
Every paragraph with Chinese text MUST apply set_ea_font() to all runs.
Font Size Hierarchy
| Size | Type | Examples | Notes |
|---|
| 44pt | Cover Title | "้กน็ฎๅ็งฐ" | Cover slide only, Georgia |
| 28pt | Section Header | "็ฎๅฝ" (TOC title) | Largest body content, Georgia |
| 24pt | Subtitle | Tagline on cover | Cover slide only |
| 22pt | Action Title | Slide title bars | Main content titles, bold, Georgia |
| 18pt | Sub-Header | Column headers, section names | Supporting titles |
| 16pt | Emphasis Text | Bottom takeaway on slide 8 | Callout text, bold |
| 14pt | Body Text | Tables, lists, descriptions | PRIMARY BODY SIZE, all main content |
| 9pt | Footnote | Source attribution | Smallest, gray color only |
No other sizes should be used - stick to this hierarchy exclusively.
Line Treatment (CRITICAL)
Line Rendering Rules
- All lines are FLAT - no shadows, no effects, no 3D
- Remove theme style references - prevents automatic shadow application
- Solid color only - no gradients or patterns
- Width varies by context - see table below
Line Width Specifications
| Usage | Width | Color | Context |
|---|
| Title separator (under action titles) | 0.5pt | BLACK | Below 22pt title |
| Column/section divider (under headers) | 0.5pt | BLACK | Below 18pt headers |
| Table header line | 1.0pt | BLACK | Between header and first row |
| Table row separator | 0.5pt | LINE_GRAY (#CCCCCC) | Between table rows |
| Timeline line (roadmap) | 0.75pt | LINE_GRAY | Background for phase indicators |
| Cover accent line | 2.0pt | NAVY | Decorative bottom-left on cover |
| Column internal divider | 0.5pt | BLACK | Between "ๆฏไปไน" and "็ฌๅฐไนๅค" |
Code Implementation (v1.1 โ Rectangle-based Lines)
CRITICAL: Do NOT use slide.shapes.add_connector() for lines. Connectors carry <p:style> elements that reference theme effects and cause file corruption. Instead, draw lines as ultra-thin rectangles:
def add_hline(slide, x, y, length, color=BLACK, thickness=Pt(0.5)):
"""Draw a horizontal line using a thin rectangle (no connector, no p:style)."""
from pptx.util import Emu
h = max(int(thickness), Emu(6350))
return add_rect(slide, x, y, length, h, color)
IMPORTANT: Never use add_connector() โ it causes file corruption. Always use add_hline() (thin rectangle).
Post-Save Full Cleanup (v1.1 โ Nuclear Sanitization)
After prs.save(outpath), ALWAYS run full cleanup that sanitizes both theme XML and all slide XML:
import zipfile, os
from lxml import etree
def full_cleanup(outpath):
"""Remove ALL p:style from every slide + theme shadows/3D."""
tmppath = outpath + '.tmp'
with zipfile.ZipFile(outpath, 'r') as zin:
with zipfile.ZipFile(tmppath, 'w', zipfile.ZIP_DEFLATED) as zout:
for item in zin.infolist():
data = zin.read(item.filename)
if item.filename.endswith('.xml'):
root = etree.fromstring(data)
ns_p = 'http://schemas.openxmlformats.org/presentationml/2006/main'
ns_a = 'http://schemas.openxmlformats.org/drawingml/2006/main'
for style in root.findall(f'.//{{{ns_p}}}style'):
style.getparent().remove(style)
if 'theme' in item.filename.lower():
for tag in ['outerShdw', 'innerShdw', 'scene3d', 'sp3d']:
for el in root.findall(f'.//{{{ns_a}}}{tag}'):
el.getparent().remove(el)
data = etree.tostring(root, xml_declaration=True,
encoding='UTF-8', standalone=True)
zout.writestr(item, data)
os.replace(tmppath, outpath)
Text Box & Shape Treatment
Text Box Padding
All text boxes must have consistent internal padding to prevent text touching edges:
bodyPr = tf._txBody.find(qn('a:bodyPr'))
for attr in ['lIns','tIns','rIns','bIns']:
bodyPr.set(attr, '45720')
Vertical Anchoring
Text must be anchored correctly based on usage:
| Content Type | Anchor | Code | Notes |
|---|
| Action titles | MIDDLE | anchor='ctr' | Centered vertically in bar |
| Body text | TOP | anchor='t' | Default, aligns to top |
| Labels | CENTER | anchor='ctr' | For circle labels |
anchor_map = {
MSO_ANCHOR.MIDDLE: 'ctr',
MSO_ANCHOR.BOTTOM: 'b',
MSO_ANCHOR.TOP: 't'
}
bodyPr.set('anchor', anchor_map.get(anchor, 't'))
Shape Styling
All shapes (rectangles, circles) must have:
- Solid fill color (no gradients)
- NO border/line (
shape.line.fill.background())
- p:style removed immediately after creation (
_clean_shape())
- No shadow effects (enforced by both inline cleanup and post-save full_cleanup)
def _clean_shape(shape):
"""Remove p:style from any shape to prevent effect references."""
sp = shape._element
style = sp.find(qn('p:style'))
if style is not None:
sp.remove(style)
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
shape.fill.solid()
shape.fill.fore_color.rgb = BG_GRAY
shape.line.fill.background()
_clean_shape(shape)
Presentation Planning
This section provides mandatory guidance for planning presentation structure, selecting layouts, and ensuring adequate content density. These rules dramatically improve output quality across different LLM models.
Recommended Slide Structures
When creating a presentation, follow these templates unless the user explicitly specifies a different structure:
Standard Presentation (10-12 slides)
Slide 1: Cover Slide (Pattern #1 or #4)
Slide 2: Table of Contents (Pattern #6) โ list ALL content sections
Slide 3: Executive Summary / Core Thesis (Pattern #24 or #8+#10)
Slides 4-7: Supporting Arguments (one per slide, vary layouts)
Slides 8-10: Case Studies / Evidence (Pattern #33 or #19)
Slide 11: Synthesis / Roadmap (Pattern #29 or #16)
Slide 12: Key Takeaways + Closing (Pattern #34 or #36)
Short Presentation (6-8 slides)
Slide 1: Cover Slide
Slide 2: Executive Summary (Pattern #24)
Slides 3-5: Core Content (vary layouts: #8, #71, #19, #33)
Slide 6: Synthesis / Timeline (Pattern #29)
Slide 7: Key Takeaways (Pattern #34)
Slide 8: Closing (Pattern #36)
CRITICAL RULES:
- Minimum slide count: 8 slides for any substantive topic. If the user's content supports 10+, generate 10+.
- Never stop early: Generate ALL planned slides in a single script. Do not truncate.
- TOC must list ALL sections: The Table of Contents slide must enumerate every content slide by number and title.
Layout Diversity Requirement
Each content slide MUST use a DIFFERENT layout pattern from its neighbors. Repeating the same layout on consecutive slides makes the presentation feel monotonous and unprofessional.
Match content type to the optimal layout pattern:
| Content Type | Recommended Layouts | Avoid |
|---|
| Single key statistic | Big Number (#8) | Plain text |
| 2 options comparison | Side-by-Side (#19), Before/After (#20), Metric Comparison Row (#62) | Two-column text |
| 3-4 parallel concepts | Table+Insight (#71), Four-Column (#27), Metric Cards (#10), Icon Grid (#63) | Bullet list |
| Process / steps | Process Chevron (#16), Vertical Steps (#30), Value Chain (#67) | Numbered text |
| Timeline | Timeline/Roadmap (#29), Cycle (#31) | Bullet list |
| Data table | Data Table (#9), Scorecard (#22), Harvey Ball Table (#56) | Plain text |
| Case study | Case Study (#33), Case Study with Image (#45) | Two-column text |
| Summary / conclusion | Executive Summary (#24), Key Takeaway (#25) | Bullet list |
| Multiple KPIs | Three-Stat Dashboard (#12), Two-Stat Comparison (#11), KPI Tracker (#52), Dashboard (#57) | Plain text |
| Time series + values/percentages | Grouped Bar (#37), Stacked Bar (#38), Line Chart (#50), Stacked Area (#70) | Data Table, Scorecard |
| Category ranking / comparison | Horizontal Bar (#39), Grouped Bar (#37), Pareto (#51) | Bullet list, Plain text |
| Part-of-whole / composition | Donut (#48), Pie (#64), Stacked Bar (#38) | Bullet list |
| Content with visual / photo | Content+Right Image (#40), Left Image+Content (#41), Three Images (#42) | Text-only layouts |
| Risk / evaluation matrix | Risk Matrix (#54), SWOT (#65), Harvey Ball (#56), 2x2 Matrix (#13) | Bullet list |
| Strategic recommendations | Numbered List+Panel (#69), Decision Tree (#60), Checklist (#61) | Two-column text |
| Multi-KPI executive dashboard | Dashboard KPI+Chart (#57), Dashboard Table+Chart (#58) | Simple table |
| Stakeholder / relationship | Stakeholder Map (#59) | Bullet list |
| Meeting agenda | Agenda (#66) | Plain text |
| Opening analysis / key arguments | Table+Insight (#71), Key Takeaway (#25) | Bullet list, Plain text |
NEVER use Two-Column Text (#26) for more than 1 slide per deck. It is the least visually engaging layout.
OPENING SLIDE PRIORITY RULE: For Slides 2โ5 (the first few content slides after cover/TOC), strongly prefer high-impact editorial layouts that set the tone for the entire presentation. Prioritized layouts for opening slides (in order of preference):
- Table+Insight (
table_insight, #71) โ structured arguments with gray-bg right-panel takeaways + chevron icon
- Big Number (#8) โ single impactful statistic
- Key Takeaway (#25) โ left detail + right summary
These layouts create a strong visual opening that hooks the audience. Avoid starting presentations with plain text or simple bullet lists.
CHART PRIORITY RULE: When data contains dates/periods + numeric values or percentages (e.g., 3/4 ๆญฃ้ข 20% ไธญๆง 80% or Q1: ยฅ850ไธ), you MUST use a Chart pattern (#37-#39, #48-#56, #64, #70) instead of a text-based layout. Charts maximize data-ink ratio and are the most visually compelling way to present time-series data.
IMAGE PRIORITY RULE (v1.8): When the content involves case studies, product showcases, location overviews, or any scenario where a visual/photo would strengthen the narrative, prefer Image+Content layouts (#40-#47, #68) over text-only layouts. The add_image_placeholder() function creates gray placeholder boxes that users replace with real images after generation.
Content Density Requirements
"Minimalism" in McKinsey design means removing decorative noise (shadows, gradients, clip-art), NOT removing content. A slide with 80% whitespace is not minimalist โ it is EMPTY.
Mandatory minimums per content slide:
- At least 3 distinct visual blocks โ e.g., title bar + content area + takeaway box, or title + left panel + right panel
- Body text area utilization โฅ 50% of the available content space (between title bar at 1.4" and source line at 7.05")
- Action Title must be a FULL SENTENCE expressing the slide's key insight:
- โ
"่ฟๆฅ็ป็บฆๆ็AIๆจกๅๅฐ่ช็ฑๅๆฐๅๅฐ90%๏ผๅฎ็ฐๅ็ป่็ฒพๅบฆ้ขๆต"
- โ
"่ฟๆฅ็ป็บฆๆ็AIๆจกๅ"
- Use specific data points when the user provides them (numbers, percentages, names) โ display them prominently with Big Number or Metric Card patterns
- Source attribution (
add_source()) on every content slide with specific references, not generic labels
Production Guard Rails (v1.9 / v2.0)
These rules address recurring production defects observed across multiple presentation generations. Each rule is derived from real-world user feedback and must be followed without exception.
Rule 1: Spacing Between Content Blocks and Bottom Bars
Problem observed: Tables, charts, or content grids placed immediately above a bottom summary/action bar (e.g., "่กๅจๅ
ฌๅผ", "่ถๅฟๅค่ฏป", "้ฃ้ฉๆ็คบ") with zero vertical gap, making them visually merged.
MANDATORY: There MUST be at least 0.15" vertical gap between the last content block and any bottom bar/summary box. Calculate positions explicitly:
last_content_bottom = content_top + num_rows * row_height
bar_y = last_content_bottom
BOTTOM_BAR_GAP = Inches(0.2)
bar_y = last_content_bottom + BOTTOM_BAR_GAP
Validation formula: bottom_bar_y >= last_content_bottom + Inches(0.15)
Rule 2: Content Overflow Protection
Problem observed: Text or shapes extending beyond the right margin (left_margin + content_width) or bottom margin (source line at 7.05").
MANDATORY overflow checks:
- Right margin: Every element's
left + width โค LM + CW (i.e., Inches(0.8) + Inches(11.733) = Inches(12.533))
- Bottom margin: Every element's
top + height โค Inches(6.95) (leaving room for source line at 7.05")
- Text in bounded boxes: When placing text inside a colored
add_rect() box, the text box MUST be inset by at least 0.15" on each side:
box_left = LM
box_width = CW
add_rect(s, box_left, box_y, box_width, box_h, BG_GRAY)
add_text(s, box_left + Inches(0.3), box_y, box_width - Inches(0.6), box_h,
text, ...)
-
Multi-column layouts: When calculating column widths, account for inter-column gaps AND the right margin:
num_cols = 3
gap = Inches(0.2)
col_w = (CW - gap * (num_cols - 1)) / num_cols
-
Long text truncation: If generated text may exceed box boundaries, reduce font_size by 1-2pt or abbreviate text. Never allow visible overflow.
Rule 3: Bottom Whitespace Elimination
Problem observed: Charts or content areas end at ~Inches(5.5) while the bottom bar sits at ~Inches(6.3), leaving ~0.8" of dead whitespace.
MANDATORY: The bottom summary bar should be positioned at no higher than Inches(6.1) and no lower than Inches(6.4). Adjust chart/content heights to fill available space. Target: visible whitespace between content and bottom bar โค 0.3".
content_bottom = chart_top + chart_height
bar_y = max(content_bottom + Inches(0.15), Inches(6.1))
bar_y = min(bar_y, Inches(6.4))
Rule 4: Legend Color Consistency
Problem observed: Chart legends using plain black text "โ " symbols (โ ๅบๅๅผ โ ๅขๅ โ ๅๅฐ) while actual chart bars use NAVY, ACCENT_RED, ACCENT_GREEN โ colors don't match.
MANDATORY: Every legend indicator MUST use a colored square (add_rect()) matching the exact color used in the chart below it. Never use text-only legends with "โ " character.
add_text(s, LM, legend_y, CW, Inches(0.25),
'โ ๅบๅๅผ โ ๅขๅ โ ๅๅฐ', ...)
lgx = LM + Inches(5)
add_rect(s, lgx, legend_y, Inches(0.15), Inches(0.15), NAVY)
add_text(s, lgx + Inches(0.2), legend_y, Inches(0.9), Inches(0.25),
'ๅบๅๅผ', font_size=Pt(10), font_color=MED_GRAY)
add_rect(s, lgx + Inches(1.3), legend_y, Inches(0.15), Inches(0.15), ACCENT_RED)
add_text(s, lgx + Inches(1.5), legend_y, Inches(0.9), Inches(0.25),
'ๅขๅ ', font_size=Pt(10), font_color=MED_GRAY)
Legend placement: Inline with or immediately below the chart subtitle line (typically at Inches(1.15)-Inches(1.20)). Legend squares are 0.15" ร 0.15" with 0.05" gap to label text.
Rule 5: Title Style Consistency
Problem observed: Some slides using add_navy_title_bar() (full-width navy background + white text) while others use add_action_title() (white background + black text + underline), creating jarring visual inconsistency.
MANDATORY: Use add_action_title() (aat()) as the ONLY title style for ALL content slides. The navy title bar (antb()) is DEPRECATED for content slides and should only appear if explicitly requested by the user.
def add_navy_title_bar(slide, text):
add_rect(s, 0, 0, SW, Inches(0.75), NAVY)
add_text(s, LM, 0, CW, Inches(0.75), text, font_color=WHITE, ...)
def add_action_title(slide, text, title_size=Pt(22)):
add_text(s, Inches(0.8), Inches(0.15), Inches(11.7), Inches(0.9), text,
font_size=title_size, font_color=BLACK, bold=True, font_name='Georgia',
anchor=MSO_ANCHOR.BOTTOM)
add_hline(s, Inches(0.8), Inches(1.05), Inches(11.7), BLACK, Pt(0.5))
Note: When add_action_title() is used, content starts at Inches(1.25) (not Inches(1.0)). Account for this when positioning grids, tables, or charts below the title.
Rule 6: Axis Label Centering in Matrix/Grid Charts
Problem observed: In 2ร2 matrix layouts (#13, #59, #65), axis labels ("็จๆท่งๆจกโ", "ๆๆฏๅฃๅโ") positioned at fixed offsets rather than centered on their respective axes, causing visual misalignment.
MANDATORY: Axis labels MUST be centered on the full span of their axis:
grid_left = LM + Inches(2.0)
grid_top = Inches(1.65)
cell_w = Inches(4.5)
cell_h = Inches(2.0)
grid_w = 2 * cell_w
grid_h = 2 * cell_h
add_text(s, LM, grid_top, Inches(1.8), grid_h,
'Y่ฝดๆ ็ญพโ', alignment=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
add_text(s, grid_left, grid_top + grid_h + Inches(0.1), grid_w, Inches(0.3),
'X่ฝดๆ ็ญพ โ', alignment=PP_ALIGN.CENTER)
Rule 7: Image Placeholder Slide Requirement
Problem observed: Presentations generated with zero image-containing slides, resulting in a wall of text/charts that feels monotonous and lacks visual relief.
MANDATORY: For presentations with 8+ slides, at least 1 slide must include image placeholders (using add_image_placeholder() or custom gray boxes with "่ฏทๆๅ
ฅๅพ็" labels). Preferred positions:
- After the first 2-3 content slides (as a visual break)
- For case studies, product showcases, or ecosystem overviews
Standard placeholder style (when not using add_image_placeholder() helper):
img_l = LM; img_t = Inches(1.3); img_w = Inches(6.5); img_h = Inches(4.0)
add_rect(s, img_l, img_t, img_w, img_h, BG_GRAY)
add_rect(s, img_l + Inches(0.04), img_t + Inches(0.04),
img_w - Inches(0.08), img_h - Inches(0.08), WHITE)
add_rect(s, img_l + Inches(0.08), img_t + Inches(0.08),
img_w - Inches(0.16), img_h - Inches(0.16), RGBColor(0xF8, 0xF8, 0xF8))
add_text(s, img_l, img_t + img_h // 2 - Inches(0.3), img_w, Inches(0.5),
'[ ่ฏทๆๅ
ฅๅพ็ ]', font_size=Pt(22), font_color=LINE_GRAY,
bold=True, alignment=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
add_text(s, img_l, img_t + img_h // 2 + Inches(0.2), img_w, Inches(0.3),
'ๅพ็ๆ่ฟฐๆ ็ญพ', font_size=Pt(13), font_color=MED_GRAY,
alignment=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
This triple-border style (BG_GRAY โ WHITE โ #F8F8F8) creates a professional, clearly identifiable placeholder that prompts users to insert real images.
Rule 8: Dynamic Sizing for Variable-Count Layouts (v1.10.4)
Problem observed: Layouts with a variable number of items (checklist rows, value chain stages, cover multi-line titles) use fixed dimensions that only work for a specific count. When item count differs, content either overflows past page boundaries or leaves excessive whitespace.
MANDATORY: For any layout where the number of items is variable, compute dimensions dynamically:
n = len(items)
gap = Inches(0.35)
item_w = (CW - gap * (n - 1)) / n
bottom_limit = BOTTOM_BAR_Y if bottom_bar else SOURCE_Y - Inches(0.05)
available_h = bottom_limit - content_start_y
item_h = min(MAX_ITEM_H, available_h / max(n, 1))
n_lines = text.count('\n') + 1
title_h = Inches(0.8 + 0.65 * max(n_lines - 1, 0))
Anti-patterns (โ NEVER DO):
stage_w = Inches(2.0) for N stages โ use (CW - gap*(N-1)) / N
row_h = Inches(0.55) for N rows โ use min(0.85, available / N)
subtitle_y = Inches(3.5) on cover โ use title_y + title_h + Inches(0.3)
Rule 9: BLOCK_ARC Native Shapes for Circular Charts (v2.0)
Problem observed: Donut charts (#48), pie charts (#64), and gauge dials (#55) rendered with hundreds to thousands of small add_rect() blocks. This creates 100-2800 shapes per chart, inflates file size by 60-80%, slows generation to 2+ minutes, and produces visual artifacts (gaps between blocks, jagged edges).
MANDATORY: Use BLOCK_ARC preset shapes via python-pptx + XML adjustment for all circular/arc charts. Each segment = 1 shape (total: 3-5 shapes per chart vs. hundreds).
BLOCK_ARC angle convention (PPT coordinate system):
- Angles measured clockwise from 12 o'clock (top), in 60000ths of a degree
- Top = 0ยฐ, Right = 90ยฐ, Bottom = 180ยฐ, Left = 270ยฐ
- Example: a full-circle donut segment from 12 o'clock CW to 3 o'clock = adj1=0, adj2=5400000
Three adj parameters:
adj1: start angle (60000ths of degree, CW from top)
adj2: end angle (60000ths of degree, CW from top)
adj3: inner radius ratio (0 = solid sector / pie, 50000 = max / invisible ring)
from pptx.oxml.ns import qn
def add_block_arc(slide, left, top, width, height, start_deg, end_deg, inner_ratio, color):
"""Draw a BLOCK_ARC shape with precise angle and ring-width control.
Args:
slide: pptx slide object
left, top, width, height: bounding box (width == height for circular arc)
start_deg: start angle in degrees, CW from 12 o'clock (0=top, 90=right, 180=bottom, 270=left)
end_deg: end angle in degrees, CW from 12 o'clock
inner_ratio: 0 = solid pie sector, 50000 = max (paper-thin ring).
For ~10px ring width: int((outer_r - Pt(10)) / outer_r * 50000)
color: RGBColor fill color
"""
from pptx.enum.shapes import MSO_SHAPE
sh = slide.shapes.add_shape(MSO_SHAPE.BLOCK_ARC, left, top, width, height)
sh.fill.solid()
sh.fill.fore_color.rgb = color
sh.line.fill.background()
_clean_shape(sh)
sp = sh._element.find(qn('p:spPr'))
prstGeom = sp.find(qn('a:prstGeom'))
if prstGeom is not None:
avLst = prstGeom.find(qn('a:avLst'))
if avLst is None:
avLst = prstGeom.makeelement(qn('a:avLst'), {})
prstGeom.append(avLst)
for gd in avLst.findall(qn('a:gd')):
avLst.remove(gd)
gd1 = avLst.makeelement(qn('a:gd'), {'name': 'adj1', 'fmla': f'val {int(start_deg * 60000)}'})
gd2 = avLst.makeelement(qn('a:gd'), {'name': 'adj2', 'fmla': f'val {int(end_deg * 60000)}'})
gd3 = avLst.makeelement(qn('a:gd'), {'name': 'adj3', 'fmla': f'val {inner_ratio}'})
avLst.append(gd1)
avLst.append(gd2)
avLst.append(gd3)
return sh
Usage patterns:
outer_r = Inches(1.6)
inner_ratio = int((outer_r - Pt(10)) / outer_r * 50000)
cum_deg = 0
for pct, color, label in segments:
sweep = pct * 360
add_block_arc(s, cx - outer_r, cy - outer_r, outer_r * 2, outer_r * 2,
cum_deg, cum_deg + sweep, inner_ratio, color)
cum_deg += sweep
add_block_arc(s, cx - r, cy - r, r * 2, r * 2, 0, 151.2, 0, NAVY)
gauge_segs = [(0.40, ACCENT_RED), (0.30, ACCENT_ORANGE), (0.30, ACCENT_GREEN)]
inner_ratio = int((outer_r - Pt(10)) / outer_r * 50000)
ppt_cum = 270
for pct, color in gauge_segs:
sweep = pct * 180
add_block_arc(s, cx - outer_r, cy - outer_r, outer_r * 2, outer_r * 2,
ppt_cum % 360, (ppt_cum + sweep) % 360, inner_ratio, color)
ppt_cum += sweep
Anti-patterns (โ NEVER DO for circular charts):
- Nested
for deg in range(...): for r in range(...): add_rect(...) โ generates hundreds/thousands of tiny squares
- Drawing a white circle on top of a filled circle to "fake" a donut โ fragile, misaligns on resize
- Using
math.cos/sin + add_rect() loops for arcs โ always use BLOCK_ARC instead
Rule 10: Horizontal Item Count Overflow Protection (v2.3)
Problem observed: Layouts that place N items horizontally across the slide (Process Chevron, Metric Cards, Icon Grid, Four-Column) compute gap = (CW - item_w * N) / (N - 1). When N is large enough that item_w * N > CW, the gap becomes negative, producing shapes with negative widths. PowerPoint reports "file needs repair" and silently deletes the corrupt shapes.
Root cause example (Process Chevron with 5+ steps):
step_w = Inches(2.6)
n = 5
gap = (CW - step_w * n) / (n - 1)
MANDATORY: For any horizontal-item layout, compute item_w dynamically from the available content width, reserving a minimum gap:
MIN_GAP = Inches(0.35)
PREFERRED_W = Inches(2.6)
max_item_w = (CW - MIN_GAP * max(n - 1, 1)) / max(n, 1)
item_w = min(PREFERRED_W, max_item_w)
gap = (CW - item_w * n) / max(n - 1, 1)
Affected methods (all already fixed in engine.py v2.3):
process_chevron() โ step boxes + arrow gaps
metric_cards() โ card columns
icon_grid() โ icon columns
four_column() โ text columns
Additional safeguards:
- When items shrink significantly (
item_w < Inches(2.0)), reduce font sizes by one tier (sub-header โ body, body โ small) to prevent text overflow inside narrower boxes.
- Arrow/connector elements between items must use
max(gap - margin, Inches(0.2)) for their width โ never raw gap - margin which may be tiny or negative.
Validation formula: item_w * n + gap * (n - 1) โ CW and gap โฅ MIN_GAP and item_w > 0.
Mandatory Slide Elements
EVERY content slide (except Cover and Closing) MUST include ALL of these:
| Element | Function | Position |
|---|
| Action Title | add_action_title(slide, text) | Top (0.15" from top) |
| Title separator line | Included in add_action_title() | 1.05" from top |
| Content area | Layout-specific content blocks | 1.4" to 6.5" |
| Source attribution | add_source(slide, text) | 7.05" from top |
| Page number | add_page_number(slide, n, total) | Bottom-right corner |
Page number helper function:
def add_page_number(slide, num, total):
add_text(slide, Inches(12.2), Inches(7.1), Inches(1), Inches(0.3),
f"{num}/{total}", font_size=Pt(9), font_color=MED_GRAY,
alignment=PP_ALIGN.RIGHT)
Layout Patterns
Slide Dimensions
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
Widescreen format (16:9), standard for all presentations.
Standard Margin/Padding
| Position | Size | Usage |
|---|
| Left margin | 0.8" | Default left edge |
| Right margin | 0.8" | Default right edge |
| Top (below title) | 1.4" | Content start position |
| Bottom | 7.05" | Source text baseline |
| Title bar height | 0.9" | Action title bar |
| Title bar top | 0.15" | From slide top |
Slide Type Patterns
1. Cover Slide (Slide 1)
Layout:
- Navy bar at very top (0.05" height)
- Main title (44pt, Georgia, navy) at y=1.2" โ height computed dynamically from line count
- Subtitle (24pt, dark gray) positioned below title dynamically
- Date/info (14pt, med gray) follows subtitle
- Decorative navy line at x=1", y=6.8" (4" wide, 2pt)
Code template:
eng.cover(title='Q1 2026 ๆ็ฅๅ้กพ', subtitle='่ฃไบไผๆฑๆฅ', author='ๆ็ฅ้จ', date='2026ๅนด3ๆ')
eng.cover(title='Q1 2026 ๆ็ฅๅ้กพ', subtitle='่ฃไบไผๆฑๆฅ', author='ๆ็ฅ้จ', date='2026ๅนด3ๆ', cover_image='auto')
eng.cover(title='Q1 2026 ๆ็ฅๅ้กพ', subtitle='่ฃไบไผๆฑๆฅ', author='ๆ็ฅ้จ', date='2026ๅนด3ๆ', cover_image='assets/my_cover.png')
Cover Image Generation Pipeline (cover_image='auto'):
When cover_image='auto', the system automatically generates a McKinsey-style cover illustration:
- Keyword โ Real Product Mapping: Title keywords are matched to real-world product descriptions via
_METAPHOR_MAP in mck_ppt/cover_image.py (e.g. 'AI' โ high-end triple-fan GPU, 'ๅป่ฏ' โ stethoscope + capsules, '้่' โ metal chip bank card, 'ๅปบ็ญ' โ 3D-printed architectural model)
- Hunyuan 2.0 Generation: Tencent Hunyuan 2.0 (
SubmitHunyuanImageJob async API) generates a 1024ร1024 product photo with prompt: "็ๅฎไบงๅๆๅฝฑ็
ง็๏ผ{product}๏ผ็บฏ็ฝ่ฒ่ๆฏ๏ผ่ฝฎๅปๆธ
ๆฐ้ๅฉ๏ผๅฝฑๆฃ็ฏๅ
๏ผ่ถ
้ซๆธ
"
- Professional Cutout:
rembg removes background completely โ only the product subject remains with transparent background
- Cool Grey-Blue Tint: Desaturation (30%), channel shift (Rร0.85, Gร0.92, Bร1.18), then 50% lighten by blending with white
- Canvas Placement: Subject scaled to ~66% canvas height, placed at right-center of 1920ร1080 transparent canvas
- Bรฉzier Ribbon Curves: 24 parallel cubic Bรฉzier curves drawn from bottom-left to top-right, with a gentle twist/fold at center (lines cross over like a folded silk ribbon). Inner lines thicker+darker, outer lines thinner+lighter
- Full-bleed Embed: Image added as first shape (bottom layer), all text rendered on top
Requirements: pip install tencentcloud-sdk-python rembg pillow numpy + env vars TENCENT_SECRET_ID, TENCENT_SECRET_KEY
Standalone usage:
from mck_ppt.cover_image import generate_cover_image
path = generate_cover_image('AI็่ฝๅ่พน็', output_path='cover.png')
2. Action Title Slide (Most Content Slides)
Every main content slide has this structure:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 0.15"
โ โ Action Title (22pt, bold, black) โ โ TITLE_BAR_H = 0.9"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค 1.05"
โ โ
โ Content area (starts at 1.4") โ
โ [Tables, lists, text, etc.] โ
โ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ 7.05"
โ Source: ... โ 9pt, med gray
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 7.5"
Code pattern:
s = prs.slides.add_slide(prs.slide_layouts[6])
add_action_title(s, 'Slide Title Here')
add_source(s, 'Source attribution')
3. Table Layout (Slide 4 - Five Capabilities)
Structure:
- Header row with column names (BODY_SIZE, gray, bold)
- 1.0pt black line under header
- Data rows (1.0" height each, 14pt text)
- 0.5pt gray line between rows
- 3 columns: Module (1.6" wide), Function (5.0"), Scene (5.1")
add_text(s4, left, top, width, height, text,
font_size=BODY_SIZE, font_color=MED_GRAY, bold=True)
add_line(s4, left, top + Inches(0.5), left + full_width, top + Inches(0.5),
color=BLACK, width=Pt(1.0))
for i, (col1, col2, col3) in enumerate(rows):
y = header_y + row_height * i
add_text(s4, left, y, col1_w, row_h, col1, ...)
add_text(s4, left + col1_w, y, col2_w, row_h, col2, ...)
add_text(s4, left + col1_w + col2_w, y, col3_w, row_h, col3, ...)
add_line(s4, left, y + row_h, left + full_w, y + row_h,
color=LINE_GRAY, width=Pt(0.5))
4. Three-Column Overview (Slide 5)
Layout:
- Left column (4.1" wide): "ๆฏไปไน"
- Middle column (4.1" wide): "็ฌๅฐไนๅค"
- Right 1/4 (2.5" wide) gray panel: "Key Takeaways"
0.8" 4.9" 5.3" 9.4" 10.0" 12.5"
|-----|-----|-----|-----|------|
โๅทฆ โ โ ไธญ โ โ ๅณ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Code:
left_x = Inches(0.8)
col_w5 = Inches(4.1)
mid_x = Inches(5.3)
takeaway_left = Inches(10.0)
takeaway_width = Inches(2.5)
add_text(s5, left_x, content_top, col_w5, ...)
add_text(s5, left_x, content_top + Inches(0.6), col_w5, ...,
bullet=True, line_spacing=Pt(8))
add_rect(s5, takeaway_left, Inches(1.2), takeaway_width, Inches(5.6), BG_GRAY)
add_text(s5, takeaway_left + Inches(0.15), Inches(1.35), takeaway_width - Inches(0.3), ...,
'Key Takeaways', font_size=BODY_SIZE, color=NAVY, bold=True)
add_text(s5, takeaway_left + Inches(0.15), Inches(1.9), takeaway_width - Inches(0.3), ...,
[f'{i+1}. {t}' for i, t in enumerate(takeaways)], line_spacing=Pt(10))
็ฑปๅซ A๏ผ็ปๆๅฏผ่ช
5. Section Divider (็ซ ่ๅ้้กต)
้็จๅบๆฏ: ๅค็ซ ่ๆผ็คบๆ็จฟ็็ซ ่่ฟๆธก้กต๏ผ็จไบ่ง่งไธๅ้ไธๅไธป้ขๆจกๅใ
โโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โN โ โ
โA โ ็ฌฌไธ้จๅ โ
โV โ ็ซ ่ๆ ้ข๏ผ28pt, NAVY, bold๏ผ โ
โY โ ๅฏๆ ้ข่ฏดๆๆๅญ โ
โ โ โ
โโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.section_divider(section_label='็ฌฌไธ้จๅ', title='ๅธๅบๅๆ', subtitle='ๅฝๅๆ ผๅฑไธๆ ธๅฟๆบไผ')
6. Table of Contents / Agenda (็ฎๅฝ/่ฎฎ็จ้กต)
้็จๅบๆฏ: ๆผ็คบๆ็จฟๅผๅคด็็ฎๅฝๆไผ่ฎฎ่ฎฎ็จ๏ผๅๅบๅ็ซ ่ๅ่ฏดๆใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ ็ฎๅฝ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ (1) ็ซ ่ไธๆ ้ข ็ฎ่ฆๆ่ฟฐ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ (2) ็ซ ่ไบๆ ้ข ็ฎ่ฆๆ่ฟฐ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ (3) ็ซ ่ไธๆ ้ข ็ฎ่ฆๆ่ฟฐ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.toc(items=[('1', 'ๅธๅบๆฆ่ง', 'ๅฝๅ็ซไบๆ ผๅฑ'), ('2', 'ๆ็ฅๆนๅ', 'ไธๅคงๆ ธๅฟไธพๆช'), ('3', 'ๆง่ก่ทฏ็บฟ', 'ๆถ้ด่กจไธ่ดฃไปปไบบ')])
7. Appendix Title (้ๅฝๆ ้ข้กต)
้็จๅบๆฏ: ๆญฃๆ็ปๆๅ็้ๅฝ/ๅค็จๆๆๅ้้กตใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โ
โ ้ๅฝ โ
โ Appendix โ
โ โโโโโโโโ โ
โ ่กฅๅ
ๆฐๆฎไธๅ่่ตๆ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.appendix_title(title='้ๅฝ', subtitle='่กฅๅ
ๆฐๆฎไธๅ่่ตๆ')
็ฑปๅซ B๏ผๆฐๆฎ็ป่ฎก
8. Big Number / Factoid (ๅคงๆฐๆฎๅฑ็คบ้กต)
้็จๅบๆฏ: ็จไธไธช้็ฎ็ๅคงๆฐๅญๅผๅบๆ ธๅฟๅ็ฐๆๅ
ณ้ฎๆฐๆฎ็นใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโNAVYโโโโโโโโโโ โ
โ โ 95% โ ๅณไพงไธไธๆ่ฏดๆ โ
โ โ ๅญๆ ้ข โ ่ฏฆ็ป่งฃ้ๆฐๆฎๅซไน โ
โ โโโโโโโโโโโโโโโโ โ
โ โ
โ โโBG_GRAYโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ๅ
ณ้ฎๆด่ง๏ผ่ฏฆ็ปๅๆๆๅญ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.big_number(title='ๅ
ณ้ฎๅ็ฐๆ ้ข', number='95%', unit='', description='ๆ่ฟฐๆฐๆฎๅซไน',
detail_items=['ๆด่ง่ฆ็นไธ', 'ๆด่ง่ฆ็นไบ', 'ๆด่ง่ฆ็นไธ'], source='Source: ...')
9. Two-Stat Comparison (ๅๆฐๆฎๅฏนๆฏ้กต)
้็จๅบๆฏ: ๅนถๆๅฑ็คบไธคไธชๅ
ณ้ฎๆๆ ็ๅฏนๆฏ๏ผๅฆๅๆฏใ็ฏๆฏใA vs B๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโNAVYโโโโโโโโ โโโBG_GRAYโโโโโ โ
โ โ $2.4B โ โ $1.8B โ โ
โ โ 2026ๅนด็ฎๆ โ โ 2025ๅนดๅฎ้
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ
โ ๅๆ่ฏดๆๆๅญ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.two_stat(title='ๅฏนๆฏๆ ้ข',
stats=[('$2.4B', '2026ๅนด็ฎๆ ', True), ('$1.8B', '2025ๅนดๅฎ้
', False)],
source='Source: ...')
10. Three-Stat Dashboard (ไธๆๆ ไปช่กจ็)
้็จๅบๆฏ: ๅๆถๅฑ็คบไธไธชๅ
ณ้ฎไธๅกๆๆ ๏ผๅฆ KPIใๅญฃๅบฆๆฐๆฎ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโNAVYโโโ โโโBG_GRAYโโ โโโBG_GRAYโโโ
โ โ ๆฐๅญ1 โ โ ๆฐๅญ2 โ โ ๆฐๅญ3 โโ
โ โ ๅฐๆ ้ข โ โ ๅฐๆ ้ข โ โ ๅฐๆ ้ข โโ
โ โโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโ
โ โ
โ ่ฏฆ็ป่ฏดๆๆๅญ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.three_stat(title='ๆ ธๅฟ่ฟ่ฅๆๆ ',
stats=[('98.5%', '็ณป็ปๅฏ็จๆง', True), ('12ms', 'ๅนณๅๅๅบๆถ้ด', False), ('4.8', '็จๆทๆปกๆๅบฆ', True)],
source='Source: ...')
11. Data Table with Headers (ๆฐๆฎ่กจๆ ผ้กต)
้็จๅบๆฏ: ็ปๆๅๆฐๆฎๅฑ็คบ๏ผๅฆ่ดขๅกๆฐๆฎใๅ่ฝๅฏนๆฏ็ฉ้ตใ้กน็ฎๆธ
ๅใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๅ1 ๅ2 ๅ3 ๅ4 โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ๆฐๆฎ1-1 ๆฐๆฎ1-2 ... ... โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ๆฐๆฎ2-1 ๆฐๆฎ2-2 ... ... โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ๆฐๆฎ3-1 ๆฐๆฎ3-2 ... ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.data_table(title='ไบๅคงๆ ธๅฟ่ฝๅ',
headers=['ๆจกๅ', 'ๅ่ฝๆ่ฟฐ', 'ๅบ็จๅบๆฏ'],
rows=[['AI Agent', '่ชไธปๅณ็ญไธๆง่ก', 'ๅฎขๆ่ชๅจๅ'],
['ๆฐๆฎๅผๆ', 'ๅฎๆถๆฐๆฎๅค็', '้ฃๆงๅณ็ญ']],
source='Source: ...')
12. Metric Cards Row (ๆๆ ๅก็่ก)
้็จๅบๆฏ: 3-4ไธชๅนถๆๅก็ๅฑ็คบ็ฌ็ซๆๆ ๏ผๆฏไธชๅก็ๅซๆ ้ข+ๆ่ฟฐใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโBG_GRAYโโ โโBG_GRAYโโ โโBG_GRAYโโ โ
โ โ (A) โ โ (B) โ โ (C) โ โ
โ โ ๆ ้ข โ โ ๆ ้ข โ โ ๆ ้ข โ โ
โ โ โโโ โ โ โโโ โ โ โโโ โ โ
โ โ ๆ่ฟฐ โ โ ๆ่ฟฐ โ โ ๆ่ฟฐ โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.metric_cards(title='ๆๅบฆ่ฟ่ฅไปช่กจ็',
cards=[('98.5%', 'ๅฏ็จๆง', '่ถ
่ถSLA็ฎๆ '),
('ยฅ2.3ไบฟ', 'ๆ่ฅๆถ', 'ๅๆฏ+18%'),
('4.8/5', 'ๆปกๆๅบฆ', '่ฟ็ปญ3ๆๆๅ')],
source='Source: ...')
็ฑปๅซ C๏ผๆกๆถ็ฉ้ต
13. 2x2 Matrix (ๅ่ฑก้็ฉ้ต)
้็จๅบๆฏ: ๆ็ฅๅๆ๏ผๅฆ BCG ็ฉ้ตใไผๅ
็บงๆๅบใ้ฃ้ฉ่ฏไผฐ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ้ซ Y่ฝด โ
โ โโNAVYโโโโโโโ โโBG_GRAYโโโโ โ
โ โ ๅทฆไธ่ฑก้ โ โ ๅณไธ่ฑก้ โ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โ
โ โโBG_GRAYโโโโ โโBG_GRAYโโโโ โ
โ โ ๅทฆไธ่ฑก้ โ โ ๅณไธ่ฑก้ โ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โ
โ ไฝ ้ซ X่ฝด โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.matrix_2x2(title='ๆ็ฅไผๅ
็บง็ฉ้ต',
quadrants=[('้ซไปทๅผ / ไฝ้พๅบฆ', ['ๅฟซ้ๆจ่ฟ้กน็ฎA', '็ซๅณๅฏๅจ้กน็ฎB']),
('้ซไปทๅผ / ้ซ้พๅบฆ', ['้็นๆปๅ
ณ้กน็ฎC']),
('ไฝไปทๅผ / ไฝ้พๅบฆ', ['ๅงๆๆง่ก้กน็ฎD']),
('ไฝไปทๅผ / ้ซ้พๅบฆ', ['ๆ็ผๆๆพๅผ'])],
source='Source: ...')
14. Three-Pillar Framework โ RETIRED (v2.0.4)
ๅทฒ้ๅฝน๏ผ#14 ๅธๅฑๅทฒ่ขซ #71 Table+Insight ๅไปฃใ่ฏทไฝฟ็จ eng.table_insight() ๅฎ็ฐ็ฑปไผผ็ไธๅๅฏนๆฏ้ๆฑ๏ผๆฐๆฎ่กจ่พพๆดๆธ
ๆฐใ่ง่งๅฑ็บงๆดๅผบใ
15. Staircase Evolution (้ถๆขฏ่ฟๅๅพ) โญ v2.0.5
้็จๅบๆฏ: ๅฑ็คบ้ถๆฎตๆงๆผ่ฟ่ทฏๅพ๏ผๅฆๅ็่ฟๅใ่ฝๅๆ้ฟใๆ็ฅๅ็บง๏ผ๏ผไปๅทฆไธๅฐๅณไธ้ถๆขฏๅผไธๅใๅ
ทๆๆๆพ็้ถๆขฏๅฐ้ถ่ฝฎๅป็บฟใๅฏ้ๅบ้จ็ปๆๅ่ฏฆๆ
่กจๆ ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ3โ ่ฟๆๆ ้ข โ
โ โโโโโโโโโโโ โ
โ โ2โ ไธญๆๆ ้ขโ ่ฟๆๆ่ฟฐ... โ
โ โโโโโโ โ โ
โ โ1โ ่ฟๆๆ ้ข โ ไธญๆๆ่ฟฐ... โ
โ โโโโโโโโโโโ โ โ
โ ่ฟๆๆ่ฟฐ... โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ่กๆ ้ข1 โ โข bullet1 โ โข bullet1 โ โข bullet1 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ่กๆ ้ข2 โ โข bullet1 โ โข bullet1 โ โข bullet1 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Engine method: eng.pyramid()
eng.pyramid(
title='ๅ็ๅฟๆบไธๅฑ่ฟๅ่ทฏๅพ',
levels=[
('ๅฑๆฌกไธ๏ผ2-3ๅนด', '"ๅฐๆทๆทๅ็ฑป็ๆไฝ็ณป็ป"\nB็ซฏ้่ดญๅณ็ญ่
', '1'),
('ๅฑๆฌกไบ๏ผ3-5ๅนด', '"ๅฐๆทๆท็็Dolby"\nๅ่ดจ่ฎค็ฅๆถ่ดน่
', '2'),
('ๅฑๆฌกไธ๏ผ5-10ๅนด', '"็พๅฅฝ็่ๆถๅป็ๅฎๆค่
"\nๆๆๆถ่ดน่
', '3'),
],
detail_rows=[
('ๆ ธๅฟ็ญ็ฅ', [
['AIๆฐๆฎ+ๅ็ฑป็ฝ็ฎไนฆ', 'ๅปบ็ซB็ซฏๆไฝ็ณป็ปๅฃๅ'],
['"ๆฅไธๅ่ดจ"่ฎค่ฏๆ ่ฏ', 'ๅ่ดจ่ฎค็ฅๆธ้ๆถ่ดน็ซฏ'],
['ๅ็ๆ
ๆๅๅ็บง', 'ๅ
จๆธ ้ๆถ่ดน่
ๅฟๆบๅ ้ข'],
]),
('ๅฏนๆ ๆกไพ', [
['Intel Inside', 'B็ซฏๆๆฏๆ ๅโๆถ่ดน่ฎค็ฅ'],
['ๅฉไน / ๆๆฏ', 'ๅ่ดจ่ฎค่ฏโ่กไธๆ ้
'],
['Gore-Tex', 'ไธไธๅ็โๅคงไผไฟก่ต'],
]),
],
source='ๅฏนๆ : Intel Inside / ๅฉไน / ๆๆฏ / Gore-Tex',
)
Parameters: title, levels (label, description, icon_text), detail_rows (row_label, [[col_texts]...]), source, bottom_bar (optional)
่ฎพ่ฎก็น็น:
- ้ถๆขฏๅฐ้ถ่ฝฎๅป็บฟ๏ผNAVY ้ข่ฒ็ๆฐดๅนณๅฐ้ข็บฟ+ๅ็ด้ถๆขฏ็บฟ๏ผๅฝขๆๆธ
ๆฐ็ๅฐ้ถๅคๅฝข
- Icon + ๆ ้ขๅ่ก๏ผNAVY ๅๅฝข icon ๅจๅทฆ๏ผ็ฒไฝๆ ้ขๅจๅณ๏ผไฝไบๅฐ้ข็บฟไธๆน
- ๆ่ฟฐๅจๅฐ้ข็บฟไธๆน๏ผๆฏ้ถๆฎต็่ฏฆ็ปๆ่ฟฐๆๅญๅจๆฐดๅนณๅฐ้ข็บฟไธ้ข
- ๅฏ้ๅบ้จ็ปๆๅ่กจๆ ผ๏ผ่กๆ ้ข+ๅ้ถๆฎต bullet ่ฏฆๆ
๏ผๅฑ
ไธญๅฏน้ฝ
- ๅ
ผๅฎนๆ/ๆ detail_rows ไธค็งๆจกๅผ
16. Process Chevron (ๆต็จ็ฎญๅคด้กต)
้็จๅบๆฏ: ็บฟๆงๆต็จๅฑ็คบ๏ผ2-7ๆญฅ๏ผ๏ผๅฆๅฎๆฝ่ทฏๅพใไธๅกๆต็จใๆนๆณ่ฎบๆญฅ้ชคใๆจ่3-5ๆญฅๆๆๆไฝณ๏ผ6-7ๆญฅๆถๆนๆกๅๅญไฝไผ่ชๅจ็ผฉๅฐ๏ผGuard Rail Rule 10๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โNAVYโ -> โGRAYโ -> โGRAYโ -> โGRAYโ โ
โ โ S1 โ โ S2 โ โ S3 โ โ S4 โ โ
โ โโโโโโ โโโโโโ โโโโโโ โโโโโโ โ
โ ๆ่ฟฐ ๆ่ฟฐ ๆ่ฟฐ ๆ่ฟฐ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.process_chevron(title='ๅฎขๆทๆ
็จไบๆญฅๆณ',
steps=['้ๆฑ่ฏๅซ', 'ๆนๆก่ฎพ่ฎก', 'ๅฎๆฝไบคไป', '่ฟ่ฅไผๅ', 'ๆ็ปญๅๆฐ'],
bottom_bar=('ๅ
ณ้ฎๆด่ง', '็ซฏๅฐ็ซฏๆฐๅญๅ่ฆ็็ไป30%ๆๅ่ณ85%'),
source='Source: ...')
17. Venn Diagram Concept (็ปดๆฉๅพๆฆๅฟต้กต)
้็จๅบๆฏ: ๅฑ็คบไธคไธไธชๆฆๅฟต็ไบค้ๅ
ณ็ณป๏ผๅฆ่ฝๅไบคๅใๅธๅบๅฎไฝ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโBGโโโ โ
โ โฑๆฆๅฟตA โฒ โ
โ โฑ โโโโ โฒ ๅณไพง่ฏดๆ โ
โ โ โไบคโ โ โ
โ โฒ โโโโ โฑ โ
โ โฒๆฆๅฟตB โฑ โ
โ โโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.venn(title='่ฝๅไบคๅๆจกๅ',
circles=[('ๆๆฏ', ['ไบ่ฎก็ฎ', 'AI/ML'], 0.8, 1.5, 4.5, 3.5),
('ไธๅก', ['่กไธKnow-how', 'ๆต็จไผๅ'], 3.5, 1.5, 4.5, 3.5)],
overlap_label='ๆฐๅญๅๅๆฐ',
source='Source: ...')
18. Temple / House Framework (ๆฎฟๅ ๆกๆถ)
้็จๅบๆฏ: ๅฑ็คบ"ๅฑ้กถ-ๆฏๆฑ-ๅบๅบง"็็ปๆ๏ผๅฆไผไธๆถๆใ่ฝๅไฝ็ณป๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโโโโโโโโโNAVY๏ผๆฟๆฏ/ๅฑ้กถ๏ผโโโโโโโโโโโโ
โ โโโโโโค โโโโโโค โโโโโโค โโโโโโค โโ
โ โๆฏๆฑโ โๆฏๆฑโ โๆฏๆฑโ โๆฏๆฑโ โโ
โ โ 1 โ โ 2 โ โ 3 โ โ 4 โ โโ
โ โโโโโโงโโโงโโโโโงโโโงโโโโโงโโโงโโโโโงโโโโโโโโโคโ
โ โ ๅบๅบง๏ผๅบ็ก่ฝๅ/ๆๅ๏ผ โโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.temple(title='ไผไธๆถๆๆกๆถ',
roof_text='ไผไธๆฟๆฏ๏ผๆไธบๅ
จ็้ขๅ
็็งๆๅ
ฌๅธ',
pillar_names=['ไบงๅๅๆฐ', 'ๅฎขๆทไฝ้ช', '่ฟ่ฅๅ่ถ', 'ไบบๆๅๅฑ'],
foundation_text='ๆฐๆฎ้ฉฑๅจ ยท ๆๆท็ป็ป ยท ๅผๆพ็ๆ',
source='Source: ...')
็ฑปๅซ D๏ผๅฏนๆฏ่ฏไผฐ
19. Side-by-Side Comparison (ๅทฆๅณๅฏนๆฏ้กต)
้็จๅบๆฏ: ไธคไธชๆนๆก/้้กน/ไบงๅ็ๅนถๆๅฏนๆฏๅๆใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโๆนๆก Aโโโโโโโ โโโๆนๆก Bโโโโโโโ โ
โ โ ๆ ้ข๏ผNAVY๏ผ โ โ ๆ ้ข๏ผNAVY๏ผ โ โ
โ โโโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโค โ
โ โ ไผๅฟ โ โ ไผๅฟ โ โ
โ โ ๅฃๅฟ โ โ ๅฃๅฟ โ โ
โ โ ๆๆฌ โ โ ๆๆฌ โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.side_by_side(title='ๆนๆกA vs ๆนๆกB',
options=[('ๆนๆกA๏ผ่ชๅปบ', ['ๅฎๅ
จ่ชไธปๅฏๆง', 'ๅๆๆๅ
ฅยฅ500ไธ', 'ไธ็บฟๅจๆ6ไธชๆ']),
('ๆนๆกB๏ผSaaS', ['ๅฟซ้ไธ็บฟ2ๅจ', 'ๅนด่ดนยฅ80ไธ', 'ไพ่ตไพๅบๅ'])],
source='Source: ...')
20. Before / After (ๅๅๅฏนๆฏ้กต) (v2.0.1 rewrite)
้็จๅบๆฏ: ๅฑ็คบๅ้ฉๅๅ็ๅฏนๆฏ๏ผๅฆ่กไธ้ๆฝฎ vs ็ๅญๅ
ฌๅผใๆต็จไผๅใ็ป็ปๅ้ฉ๏ผใ
่ฎพ่ฎก็นๅพ:
- ็ฝๅบๆธ
ๆดๅธๅฑ โ ๆ ่ๆฏ่ฒๅ๏ผ็บฏ็ฝๅบ
- ้ป่ฒ็ซ็บฟ + ๅๅ็ฎญๅคด โ ไธญ้ด็ป็ซ็บฟๅ้๏ผ็ซ็บฟๆญฃไธญๆพ้ป่ฒๅฎๅฟๅๅๅ
ๅซ
> ็ฎญๅคด๏ผArial ๅญไฝ๏ผๅ
่พน่ท0๏ผ
- ็ปๆๅๆฐๆฎ่ก๏ผๅทฆไพง๏ผโ ๆฏ่กๆ label/brand/value/extra๏ผๆฐๅผ็บข่ฒๅคงๅญ
- ๅ
ฌๅผๅก็๏ผๅณไพง๏ผโ ๆฏๆกๆ title/desc/cases๏ผๆกไพๆฐๅญ้ป่ฒ+ไธๅ็บฟ
- ๆฏๆ็ฎๅๆๅญๅ่กจๅๅค โ ๅฆไผ ๅ
ฅ
list[str] ่ชๅจ้ๅไธบ็ฎๅ bullet ๆจกๅผ
- ๅฏ้่็บฟ่งๆ โ ๅณไธ่ง่็บฟๆก๏ผๅฆ
Part II > ้ๆฝฎ๏ผ
- ๅฏ้ๅบ้จๆป็ปๆก โ bottom_bar
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โPart II >โ โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ ๅทฆไพงๆ ้ข โ โ ๅณไพงๆ ้ข โ
โ โ โ โ โ
โ ๆ ็ญพ ๅ็ ๆฐๅผ โ > โ 1. ๅ
ฌๅผๆ ้ข โ
โ โโโโโโโโโโโโโโ โ โ โ ๆ่ฟฐ + ๆกไพไธๅ็บฟ โ
โ ๆ ็ญพ ๅ็ ๆฐๅผ โ โ โโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโ โ โ 2. ๅ
ฌๅผๆ ้ข โ
โ ๆป็ป(็ฐ็ฒไฝ) โ โ ๆป็ป(็บข่ฒ็ฒไฝ) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ [ๅ
ณ้ฎๆดๅฏ] ๅบ้จๆป็ปๆก โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Engine method: eng.before_after()
eng.before_after(title='ๆต็จไผๅๆๆ',
before_title='ไผๅๅ', before_points=['ไบบๅทฅๅฎกๆน 3-5ๅคฉ', '้่ฏฏ็ 8%', 'ๆปกๆๅบฆ 65ๅ'],
after_title='ไผๅๅ', after_points=['่ชๅจๅฎกๆน 2ๅฐๆถ', '้่ฏฏ็ 0.5%', 'ๆปกๆๅบฆ 92ๅ'],
source='Source: ...')
Parameters:
| ๅๆฐ | ็ฑปๅ | ่ฏดๆ |
|---|
title | str | ้กต้ขๆ ้ข |
before_title | str | ๅทฆไพงๆ ้ข |
before_points | list[dict] ๆ list[str] | ๅทฆไพงๆฐๆฎ่ก๏ผdict: label/brand1/val1/brand2/val2/extra๏ผๆ็ฎๅๆๅญๅ่กจ |
after_title | str | ๅณไพงๆ ้ข |
after_points | list[dict] ๆ list[str] | ๅณไพงๅ
ฌๅผๅก็๏ผdict: title/desc/cases๏ผๆ็ฎๅๆๅญๅ่กจ |
corner_label | str | ๅณไธ่ง่็บฟ่งๆ ๆๅญ๏ผๅฏ้๏ผ |
bottom_bar | tuple(str,str) | ๅบ้จๆก (ๆ ็ญพ, ๆๅญ)๏ผๅฏ้๏ผ |
left_summary | str | ๅทฆไพงๅบ้จๆป็ปๆๅญ๏ผๅฏ้๏ผ็ฐ่ฒ็ฒไฝ๏ผ |
right_summary | str | ๅณไพงๅบ้จๆป็ปๆๅญ๏ผๅฏ้๏ผ้ป่ฎค็บข่ฒ็ฒไฝ๏ผ |
right_summary_color | RGBColor | ๅณไพงๆป็ปๆๅญ้ข่ฒ๏ผ้ป่ฎค ACCENT_RED๏ผ |
source | str | ๆฐๆฎๆฅๆบ |
21. Pros and Cons (ไผๅฃๅๆ้กต)
้็จๅบๆฏ: ่ฏไผฐๆไธชๅณ็ญ/ๆนๆก็ไผๅฟไธ้ฃ้ฉใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ V ไผๅฟ X ้ฃ้ฉ โ
โ โโโโโโโโโโโ โโโโโโโโโโ โ
โ โข ่ฆ็น1 โข ่ฆ็น1 โ
โ โข ่ฆ็น2 โข ่ฆ็น2 โ
โ โข ่ฆ็น3 โข ่ฆ็น3 โ
โ โ
โ โโโBG_GRAY ็ป่ฎบ/ๅปบ่ฎฎโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.pros_cons(title='ๅนถ่ดญๆนๆก่ฏไผฐ',
pros_title='ไผๅฟ', pros=['ๅฟซ้่ทๅๅธๅบไปฝ้ข', 'ๆๆฏๅข้ๆดๅ', 'ๅ็ๅๅๆๅบ'],
cons_title='้ฃ้ฉ', cons=['ๆดๅๆๆฌ้ซ', 'ๆๅๅฒ็ช', '็็ฎกๅฎกๆนไธ็กฎๅฎ'],
source='Source: ...')
22. Traffic Light / RAG Status (็บข็ปฟ็ฏ็ถๆ้กต)
้็จๅบๆฏ: ๅค้กน็ฎ/ๅคๆจกๅ็็ถๆๆป่ง๏ผ็ปฟ=ๆญฃๅธธใ้ป=ๅ
ณๆณจใ็บข=้ฃ้ฉ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ้กน็ฎ ็ถๆ ่ฟๅบฆ ๅคๆณจ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ้กน็ฎA (G) 85% ๆ่ฎกๅๆจ่ฟ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ้กน็ฎB (Y) 60% ้ๅ
ณๆณจ่ตๆบ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ้กน็ฎC (R) 30% ๅญๅจ้ปๅก โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.rag_status(title='้กน็ฎๅฅๅบทๅบฆไปช่กจ็',
headers=['้กน็ฎ', '่ฟๅบฆ', '้ข็ฎ', '่ดจ้', '่ด่ดฃไบบ'],
rows=[('CRMๅ็บง', '๐ข', '๐ก', '๐ข', 'ๅผ ไธ'),
('ERP่ฟ็งป', '๐ก', '๐ด', '๐ข', 'ๆๅ')],
source='Source: ...')
23. Scorecard (่ฎกๅๅก้กต)
้็จๅบๆฏ: ๅฑ็คบๅค้กน่ฏไผฐ็ปดๅบฆ็ๅพๅ/่ฏ็บง๏ผๅฆไพๅบๅ่ฏไผฐใๅข้็ปฉๆใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ่ฏไผฐ็ปดๅบฆ ๅพๅ ่ฏ็บง โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ๅฎขๆทๆปกๆๅบฆ 92 โโโโโโโโโโ โ
โ ไบงๅ่ดจ้ 85 โโโโโโโโโโ โ
โ ไบคไป้ๅบฆ 78 โโโโโโโโโโ โ
โ ๅๆฐ่ฝๅ 65 โโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.scorecard(title='ๆฐๅญๅๆ็ๅบฆ่ฏไผฐ',
items=[('ๆฐๆฎๆฒป็', 85, 'ๅทฒๅปบ็ซๅฎๆดๆฐๆฎๆ ๅ'),
('ๆต็จ่ชๅจๅ', 62, 'RPA่ฆ็40%ๆ ธๅฟๆต็จ'),
('AIๅบ็จ', 45, '่ฏ็น้ถๆฎต๏ผ3ไธชๅบๆฏ่ฝๅฐ')],
source='Source: ...')
็ฑปๅซ E๏ผๅ
ๅฎนๅไบ
24. Executive Summary (ๆง่กๆ่ฆ้กต)
้็จๅบๆฏ: ๆผ็คบๆ็จฟ็ๆ ธๅฟ็ป่ฎบๆฑๆป๏ผ้ๅธธๆพๅจๅผๅคดๆ็ปๅฐพใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโNAVY๏ผๆ ธๅฟ็ป่ฎบ๏ผโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ไธๅฅ่ฏๆ ธๅฟ็ป่ฎบ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ (1) ๆฏๆ่ฎบ็นไธ ่ฏฆ็ป่ฏดๆ โ
โ (2) ๆฏๆ่ฎบ็นไบ ่ฏฆ็ป่ฏดๆ โ
โ (3) ๆฏๆ่ฎบ็นไธ ่ฏฆ็ป่ฏดๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.executive_summary(title='ๆง่กๆ่ฆ',
headline='ๆฌๅญฃๅบฆๅฎ็ฐ่ฅๆถยฅ8.5ไบฟ๏ผๅๆฏๅข้ฟ23%๏ผ่ถ
้ขๅฎๆๅนดๅบฆ็ฎๆ ็52%',
items=[('ๅธๅบๆๅฑ', 'ๆฐๅขๅฎขๆท127ๅฎถ๏ผ่ฆ็3ไธชๆฐ่กไธ'),
('ไบงๅ่ฟญไปฃ', 'ๅๅธV3.0็ๆฌ๏ผNPSๆๅ15ไธช็พๅ็น'),
('่ฟ่ฅๆ็', 'ไบบๆๆฏๆๅ18%๏ผไบคไปๅจๆ็ผฉ็ญ40%')],
source='Source: ...')
25. Key Takeaway with Detail (ๆ ธๅฟๆด่ง้กต)
้็จๅบๆฏ: ๅทฆไพง่ฏฆ็ป่ฎบ่ฟฐ + ๅณไพง็ฐๅบ่ฆ็นๆ็ผ๏ผ็จไบๆ ธๅฟๅ็ฐ้กตใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโBG_GRAYโโโโโโโโโโ
โ ๅทฆไพงๆญฃๆๅ
ๅฎน โ Key Takeaways โโ
โ ่ฏฆ็ปๅๆ่ฎบ่ฟฐ โ 1. ่ฆ็นไธ โโ
โ ๆฐๆฎไธๆฏๆ โ 2. ่ฆ็นไบ โโ
โ โ 3. ่ฆ็นไธ โโ
โ โโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.key_takeaway(title='ๆ ธๅฟๆด่ง',
takeaway='ๆฐๅญๅ่ฝฌๅ็ๅ
ณ้ฎไธๅจๆๆฏ๏ผ่ๅจ็ป็ป่ฝๅ็้ๅก',
details=['ๆๆฏๆฏenabler๏ผ็ป็ปๆฏdriver', '่ชไธ่ไธ็ๆ็ฅๅ
ฑ่ฏๆฏๅๆ', 'ๅฐๆญฅๅฟซ่ทไผไบๅคง่งๆจก้ๆ'],
source='Source: ...')
26. Quote / Insight Page (ๅผ่จ/ๆด่ง้กต)
้็จๅบๆฏ: ็ชๅบไธๆฎต้่ฆๅผ่จใไธๅฎถ่ง็นๆๆ ธๅฟๆดๅฏใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โโโโโโโโโโ โ
โ โ
โ "ๅผ่จๅ
ๅฎน๏ผๅฑ
ไธญๆพ็คบ๏ผ โ
โ ๅคงๅญๅทๅผบ่ฐๆ ธๅฟ่ง็น" โ
โ โ
โ โโโโโโโโโโ โ
โ โ ๆฅๆบ/ไฝ่
โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.quote(title='ๅฎขๆทๅ้ฆ',
quote_text='่ฟๆฏๆไปฌ่ง่ฟ็ๆไธไธใๆ้ซๆ็ๆฐๅญๅ่ฝฌๅๆนๆกใ',
attribution='ๅผ ๆป, XX้ๅขCEO',
source='Source: ...')
27. Two-Column Text (ๅๆ ๆๆฌ้กต)
้็จๅบๆฏ: ๅนณ่กกๅฑ็คบไธคไธชไธป้ข/ๆน้ข๏ผๆฏๅ็ฌ็ซๆ ้ข+ๆญฃๆใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ (A) ๅทฆๆ ๆ ้ข (B) ๅณๆ ๆ ้ข โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โ
โ ๅทฆๆ ๆญฃๆๅ
ๅฎน ๅณๆ ๆญฃๆๅ
ๅฎน โ
โ ่ฏฆ็ปๅๆ ่ฏฆ็ปๅๆ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.two_column_text(title='่ฝๅๅฏนๆฏๅๆ',
columns=[('A', 'ๆ ธๅฟ่ฝๅ', ['ไบๅ็ๆถๆ่ฎพ่ฎก', 'ๅคง่งๆจกๅๅธๅผ็ณป็ป', 'AI/MLๅทฅ็จๅ']),
('B', 'ๅพ
ๆๅ้ขๅ', ['ๅ็ซฏไฝ้ช่ฎพ่ฎก', 'ๅฝ้
ๅ่ฟ่ฅ', '็ๆๅไฝไผไผด'])],
source='Source: ...')
28. Four-Column Overview (ๅๆ ๆฆ่ง้กต)
้็จๅบๆฏ: ๅไธชๅนถๅ็ปดๅบฆ็ๆฆ่ง๏ผๅฆๅๅคงไธๅก็บฟใๅไธช่ฝๅๅ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ (1) (2) (3) (4) โ
โ ๆ ้ข1 ๆ ้ข2 ๆ ้ข3 ๆ ้ข4 โ
โ โโโโ โโโโ โโโโ โโโโ โ
โ ๆ่ฟฐ ๆ่ฟฐ ๆ่ฟฐ ๆ่ฟฐ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.four_column(title='ๅๅคงๆ็ฅๆนๅ',
items=[('ไบงๅๅๆฐ', 'ๆ็ปญ่ฟญไปฃๆ ธๅฟไบงๅ็บฟ'),
('ๅธๅบๆๅฑ', '่ฟๅ
ฅ3ไธชๆฐๅ็ด่กไธ'),
('่ฟ่ฅๅ่ถ', 'ๅ
จๆต็จๆฐๅญๅ่ฆ็'),
('ไบบๆๆ็ฅ', 'ๅ
ณ้ฎๅฒไฝ100%ๅฐไฝ')],
source='Source: ...')
็ฑปๅซ F๏ผๆถ้ดๆต็จ
29. Timeline / Roadmap (ๆถ้ด่ฝด/่ทฏ็บฟๅพ)
้็จๅบๆฏ: ๅฑ็คบๆถ้ด็ปดๅบฆ็้็จ็ข่ฎกๅ๏ผๅญฃๅบฆ/ๆๅบฆ/ๅนดๅบฆ่ทฏ็บฟๅพ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ (1)โโโโโโ(2)โโโโโโ(3)โโโโโโ(4) โ
โ Q1 Q2 Q3 Q4 โ
โ ้็จ็ข1 ้็จ็ข2 ้็จ็ข3 ้็จ็ข4 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.timeline(title='้กน็ฎ่ทฏ็บฟๅพ 2026',
milestones=[('Q1', '้ๆฑ่ฐ็ ไธๆนๆก่ฎพ่ฎก'),
('Q2', 'ๆ ธๅฟๅ่ฝๅผๅไธๆต่ฏ'),
('Q3', '็ฐๅบฆๅๅธไธ็จๆทๅ้ฆ'),
('Q4', 'ๅ
จ้ไธ็บฟไธๆๆ่ฏไผฐ')],
source='Source: ...')
30. Vertical Steps (ๅ็ดๆญฅ้ชค้กต)
้็จๅบๆฏ: ไปไธๅฐไธ็ๆไฝๆญฅ้ชคๆๅฎๆฝ้ถๆฎตใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ (1) ๆญฅ้ชคไธๆ ้ข ่ฏฆ็ป่ฏดๆ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ (2) ๆญฅ้ชคไบๆ ้ข ่ฏฆ็ป่ฏดๆ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ (3) ๆญฅ้ชคไธๆ ้ข ่ฏฆ็ป่ฏดๆ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ (4) ๆญฅ้ชคๅๆ ้ข ่ฏฆ็ป่ฏดๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.vertical_steps(title='ๅฎๆฝไบๆญฅๆณ',
steps=[('1', '่ฏๆญ่ฏไผฐ', 'ๅ
จ้ขไบ่งฃ็ฐ็ถไธ็็น'),
('2', 'ๆนๆก่ฎพ่ฎก', 'ๅถๅฎๅ้ถๆฎตๅฎๆฝๆนๆก'),
('3', '่ฏ็น้ช่ฏ', '้ๅ2-3ไธชๅบๆฏๅฟซ้้ช่ฏ'),
('4', '่งๆจกๆจๅนฟ', 'ๅคๅถๆๅ็ป้ช่ณๅ
จไธๅก็บฟ'),
('5', 'ๆ็ปญไผๅ', 'ๅปบ็ซๆฐๆฎ้ฉฑๅจ็่ฟญไปฃๆบๅถ')],
source='Source: ...')
31. Cycle / Loop (ๅพช็ฏๅพ้กต)
้็จๅบๆฏ: ้ญ็ฏๆต็จๆ่ฟญไปฃๅพช็ฏ๏ผๅฆ PDCAใๆๆท่ฟญไปฃใๅ้ฆๅพช็ฏ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโ้ถๆฎต1โโโ โ
โ โ โ โ
โ โ้ถๆฎต4โโ โโ้ถๆฎต2โ ๅณไพง่ฏดๆ โ
โ โ โโโโโโโโโโโโ โ โ
โ โโโโโโโ โโโโโโโ โ
โ โโโ้ถๆฎต3โโโ โ
โ โโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.cycle(title='ๆๆทๅผๅๅพช็ฏ',
phases=[('่งๅ', 1.0, 2.0), ('ๅผๅ', 5.0, 1.0),
('ๆต่ฏ', 9.0, 2.0), ('ๅๅธ', 5.0, 4.0)],
source='Source: ...')
32. Funnel (ๆผๆๅพ้กต)
้็จๅบๆฏ: ่ฝฌๅๆผๆ๏ผๅฆ้ๅฎๆผๆใ็จๆท่ฝฌๅ่ทฏๅพ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 100% โ
โ โ ่ฎค็ฅ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโค 60% โ
โ โ ๅ
ด่ถฃ โ โ
โ โโโโโโโโโโโโโโโโโโค 35% โ
โ โ ่ดญไนฐ โ โ
โ โโโโโโโโโโโโค 15% โ
โ โ ็ๅญ โ โ
โ โโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.funnel(title='้ๅฎๆผๆๅๆ',
stages=[('็บฟ็ดข่ทๅ', '10,000', '100%'),
('้ๆฑ็กฎ่ฎค', '3,500', '35%'),
('ๆนๆกๆฅไปท', '1,200', '12%'),
('ๅๅ็ญพ็ฝฒ', '480', '4.8%')],
source='Source: ...')
็ฑปๅซ G๏ผๅข้ไธ้ข
33. Meet the Team (ๅข้ไป็ป้กต)
้็จๅบๆฏ: ๅข้ๆๅ/ๆ ธๅฟ้ซ็ฎก/้กน็ฎ็ป็ฎไปใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโBGโโโ โโBGโโโ โโBGโโโ โ
โ โ(ๅคดๅ)โ โ(ๅคดๅ)โ โ(ๅคดๅ)โ โ
โ โ ๅงๅ โ โ ๅงๅ โ โ ๅงๅ โ โ
โ โ ่ไฝ โ โ ่ไฝ โ โ ่ไฝ โ โ
โ โ ็ฎไป โ โ ็ฎไป โ โ ็ฎไป โ โ
โ โโโโโโโโ โโโโโโโโ โโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.meet_the_team(title='ๆ ธๅฟๅข้',
members=[('ๅผ ไธ', 'CEO', '15ๅนด่กไธ็ป้ช'),
('ๆๅ', 'CTO', 'ๅGoogle้ซ็บงๅทฅ็จๅธ'),
('็ไบ', 'VP Sales', 'ๅนด้ๅฎ้ขยฅ5ไบฟ+')],
source='Source: ...')
34. Case Study (ๆกไพ็ ็ฉถ้กต)
้็จๅบๆฏ: ๅฑ็คบๆๅๆกไพ๏ผๆ"ๆ
ๅข-่กๅจ-็ปๆ"็ปๆ็ป็ปใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโSituationโโโ โโApproachโโโ โResultโโ โ
โ โ ่ๆฏ/ๆๆ โ โ ้ๅ่กๅจ โ โ ๆๆ โ โ
โ โ โ โ โ โ โ โ
โ โโโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโ โ
โ โ
โ โโโBG_GRAY ๅฎขๆท่ฏไปท/ๅ
ณ้ฎๆๆ โโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.case_study(title='XX้ถ่กๆฐๅญๅ่ฝฌๅๆกไพ',
sections=[('S', '่ๆฏ', 'ไผ ็ปๆ ธๅฟ็ณป็ป่ๅ๏ผๆ ๆณๆฏๆไธๅกๅข้ฟ'),
('A', '่กๅจ', 'ๅ้ถๆฎตๅพฎๆๅกๆน้ + ๆฐๆฎไธญๅฐๅปบ่ฎพ'),
('R', 'ๆๆ', 'ไบคๆๅค็่ฝๅๆๅ10ๅ๏ผๆ
้็ไธ้90%')],
result_box=('ๅ
ณ้ฎๆๆ ', 'ROI 380% | 12ไธชๆๅๆฌ'),
source='Source: ...')
35. Action Items / Next Steps (่กๅจ่ฎกๅ้กต)
้็จๅบๆฏ: ๆผ็คบๆ็จฟ็ปๅฐพ็ไธไธๆญฅ่กๅจๆธ
ๅใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโNAVYโโโ โโโNAVYโโโ โโโNAVYโโโ โ
โ โ่กๅจไธ โ โ่กๅจไบ โ โ่กๅจไธ โ โ
โ โโBGโโโโโโค โโBGโโโโโโค โโBGโโโโโโค โ
โ โ ๆถ้ด โ โ ๆถ้ด โ โ ๆถ้ด โ โ
โ โ ๆ่ฟฐ โ โ ๆ่ฟฐ โ โ ๆ่ฟฐ โ โ
โ โ ่ด่ดฃไบบ โ โ ่ด่ดฃไบบ โ โ ่ด่ดฃไบบ โ โ
โ โโโโโโโโโโ โโโโโโโโโโ โโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.action_items(title='ไธไธๆญฅ่กๅจ่ฎกๅ',
actions=[('ๅฏๅจๆฐๆฎๆฒป็้กน็ฎ', 'Q2 2026', 'ๅปบ็ซ็ปไธๆฐๆฎๆ ๅไธ่ดจ้ไฝ็ณป', 'ๅผ ไธ'),
('ๆ่AIๅทฅ็จๅธๅข้', 'Q1-Q2 2026', '็ปๅปบ10ไบบMLๅทฅ็จๅข้', 'ๆๅ'),
('ๅฎๆERPไบ่ฟ็งป', 'Q3 2026', 'ๆ ธๅฟERP็ณป็ป่ฟ็งป่ณไบๅ็ๆถๆ', '็ไบ')],
source='Source: ...')
36. Closing / Thank You (็ปๆ้กต)
้็จๅบๆฏ: ๆผ็คบๆ็จฟ็ปๅฐพ็่ด่ฐขๆๆป็ปๆถๅฐพ้กตใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โโโ โ
โ โ
โ ๆ ธๅฟๆป็ป่ฏญๅฅ โ
โ โโโโโโโโโโ โ
โ ็ปๆๅฏ่ฏญ โ
โ โ
โ โโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.closing(title='่ฐข่ฐข', message='ๆๅพ
ไธๆจ่ฟไธๆญฅไบคๆต')
็ฑปๅซ H๏ผๆฐๆฎๅพ่กจ
่งฆๅ่งๅ๏ผๅฝ็จๆทๆไพ็ๅ
ๅฎนๅ
ๅซ ๆฅๆ/ๆถ้ด + ๆฐๅผ/็พๅๆฏ ็็ปๆๅๆฐๆฎ๏ผๅฆ่ๆ
ๅๅใ้ๅฎ่ถๅฟใKPI ๅจๆฅใ่ฝฌๅ็ๅๅ็ญ๏ผ๏ผๅฟ
้กปไผๅ
ไฝฟ็จๆฌ็ฑปๅซ็ๅพ่กจๆจกๅผ๏ผ่ไธๆฏ Data Table (#11) ๆ Scorecard (#23)ใ
่ฏๅซไฟกๅท๏ผๆปก่ถณไปปไธๅณ่งฆๅ๏ผ๏ผ
- ๆฐๆฎไธญๅบ็ฐ
ๆฅๆ + ็พๅๆฏ ๆ ๆฅๆ + ๆฐๅผ ็็ปๅ
- ๆ็คบ่ฏๅซ
โโโโ ่ฟๅบฆๆกๅญ็ฌฆ + ็พๅๆฏ
- ๅ
ๅฎนๆถๅ"่ถๅฟ"ใ"ๆผๅ"ใ"ๅๅ"ใ"่ตฐๅฟ"ใ"ๅจๆฅ"ใ"ๆฅๆฅ"็ญๆถๅบๅ
ณ้ฎ่ฏ
- ๆฐๆฎ่กๆฐ โฅ 3 ไธๆฏ่กๅ
ๅซ่ณๅฐไธไธช็ฑปๅซๅไธไธชๆฐๅผ
37. Grouped Bar Chart๏ผๅ็ปๆฑ็ถๅพ / ๆ
็ปช็ญๅๅพ๏ผ
้็จๅบๆฏ: ๅคไธช็ฑปๅซๅจไธๅๆถ้ด็น็ๆฐๅผๅฏนๆฏ๏ผๅฆ่ๆ
ๆ
็ปชๅๅธใๅคไบงๅ้ๅฎๅฏนๆฏใๅคๆๆ ๅจๅๅ๏ผใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 100% โ โ
โ 80% โ โโ โ
โ 60% โ โโ โโ โ
โ 40% โ โโ โโ โโ โโ โ
โ 20% โ โโ โโ โโ โโ โโ โโ โโ โ
โ 0% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ 3/4 3/6 3/8 3/10 โ
โ โ
โ โ ๆญฃ้ข โ ไธญๆง โ ่ด้ข โ
โ โ
โ โโBG_GRAY ่ถๅฟๆป็ปโโโโโโโโโโโโโโโโโโโ โ
โ โ ๆป็ปๆๅญ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
่ฎพ่ฎก่ง่:
- ๆฑ็ถๅพไฝฟ็จ
add_rect() ๆๅทฅ็ปๅถ๏ผไธไพ่ต matplotlib
- Y ่ฝดๆ ็ญพ๏ผ็พๅๆฏ๏ผ็จ
add_text() ๅทฆๅฏน้ฝ
- X ่ฝดๆ ็ญพ๏ผๆฅๆ๏ผ็จ
add_text() ๅฑ
ไธญ
- ๆฏ็ปๆฑๅญ้ด็ 0.3" ้ด่ท๏ผ็ปๅ
ๆฑๅญ้ด็ 0.05" ้ด่ท
- ๅพไพ็จๅฐ็ฉๅฝข่ฒๅ + ๆๅญๆ ็ญพ๏ผๆพๅจๅพ่กจไธๆน
- ๅบ้จๅฏ้่ถๅฟๆป็ปๅบ๏ผBG_GRAY๏ผ
้ข่ฒๅ้
:
- ็ฌฌไธ็ฑปๅซ๏ผNAVY (#051C2C) โ ไธป่ฆ/ๆญฃ้ข
- ็ฌฌไบ็ฑปๅซ๏ผLINE_GRAY (#CCCCCC) โ ไธญๆง/ๅบๅ
- ็ฌฌไธ็ฑปๅซ๏ผMED_GRAY (#666666) โ ๆฌก่ฆ/่ด้ข
- ็ฌฌๅ็ฑปๅซ๏ผACCENT_BLUE (#006BA6) โ ๆฉๅฑ
- ่ฅ็ฑปๅซๆ่ฏญไน่ฒ๏ผๅฆๆญฃ้ข=NAVY, ่ด้ข=MED_GRAY๏ผ๏ผไผๅ
ไฝฟ็จ่ฏญไน่ฒ
eng.grouped_bar(title='ๅญฃๅบฆ่ฅๆถ่ถๅฟ๏ผๆไบงๅ็บฟ๏ผ',
categories=['Q1', 'Q2', 'Q3', 'Q4'],
series=[('ไบงๅA', NAVY), ('ไบงๅB', ACCENT_BLUE)],
data=[[120, 80], [145, 95], [160, 110], [180, 130]],
y_max=200, y_step=50, y_unit='ไธ',
source='Source: ...')
38. Stacked Bar Chart๏ผๅ ๅ ๆฑ็ถๅพ / ็พๅๆฏๅ ๆฏๅพ๏ผ
้็จๅบๆฏ: ๅฑ็คบๅ็ฑปๅซๅจๆปไฝไธญ็ๅ ๆฏ้ๆถ้ดๅๅ๏ผๅฆๅธๅบไปฝ้ขๆผๅใ้ข็ฎๅ้
ๅๅใๆธ ้่ดก็ฎๅ ๆฏ๏ผใ้ๅๅผบ่ฐ"ๆๆๆฏไพ"่้"็ปๅฏนๅผ"ใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 100% โ โโโโ โโโโ โโโโ โโโโ โ
โ โC โ โ โ โ โ โ โ โ
โ 50% โ โB โ โB โ โ โ โ โ โ
โ โ โ โ โ โB โ โB โ โ
โ โA โ โA โ โA โ โA โ โ
โ 0% โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ Q1 Q2 Q3 Q4 โ
โ โ
โ โ A็ฑป โ B็ฑป โ C็ฑป โ
โ โ
โ โโBG_GRAY ๅ
ณ้ฎๅ็ฐโโโโโโโโโโโโโโโโโโโ โ
โ โ ๅๆๆๅญ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
่ฎพ่ฎก่ง่:
- ๆฏๆ นๆฑๅญๅ
้จไปๅบ้จๅฐ้กถ้จไพๆฌกๅ ๅ ๅ็ฑปๅซ
- ๆฑๅญๅฎฝๅบฆ็ปไธไธบ 0.8"~1.2"๏ผๆฏๅ็ปๆฑ็ถๅพๆดๅฎฝ๏ผ
- ๅๆฎตไน้ดๆ ้ด่ท๏ผ็ดๆฅๅ ๅ
- ็พๅๆฏๆ ็ญพๅๅจๅฏนๅบ่ฒๅๅ
้จ๏ผๅฝ่ฒๅ้ซๅบฆ่ถณๅคๆถ๏ผ๏ผๆ็็ฅ
- ๅณไพงๅฏ้ๆพ็ฝฎ"็ดๆฅๆ ็ญพ"ๆๅๆๅไธๆ นๆฑๅญ็ๅๆฎต
้ข่ฒๅ้
๏ผไปๅบๅฐ้กถ๏ผ:
- ็ฌฌไธๅฑ๏ผๆๅคง/ๆ้่ฆ๏ผ๏ผNAVY (#051C2C)
- ็ฌฌไบๅฑ๏ผACCENT_BLUE (#006BA6)
- ็ฌฌไธๅฑ๏ผLINE_GRAY (#CCCCCC)
- ็ฌฌๅๅฑ๏ผBG_GRAY (#F2F2F2) + ็ป่พนๆก
- ๆดๅคๅฑ็บง๏ผไฝฟ็จ ACCENT_GREEN, ACCENT_ORANGE
eng.stacked_bar(title='่ฅๆถๆๆๅๅ่ถๅฟ',
periods=['2023', '2024', '2025', '2026E'],
series=[('ไบงๅ', NAVY), ('ๆๅก', ACCENT_BLUE), ('่ฎข้
', ACCENT_GREEN)],
data=[[40, 35, 25], [35, 35, 30], [30, 35, 35], [25, 35, 40]],
source='Source: ...')
39. Horizontal Bar Chart๏ผๆฐดๅนณๆฑ็ถๅพ / ๆๅๅพ๏ผ
้็จๅบๆฏ: ็ฑปๅซๅ็งฐ่พ้ฟ็ๆๅๅฏนๆฏ๏ผๅฆ้จ้จ็ปฉๆๆๅใๅ็่ฎค็ฅๅบฆใๅ่ฝไฝฟ็จ็ๆ่ก๏ผใๆจชๅๆฑ็ถๅพๅจ็ฑปๅซ่พๅคๆถๅฏ่ฏปๆงๆดๅฅฝใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Action Title โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ็ฑปๅซ A โโโโโโโโโโโโโโโโโโโโ 92% โ
โ ็ฑปๅซ B โโโโโโโโโโโโโโโโ 85% โ
โ ็ฑปๅซ C โโโโโโโโโโโโโโ 78% โ
โ ็ฑปๅซ D โโโโโโโโโโโโ 65% โ
โ ็ฑปๅซ E โโโโโโโโ 52% โ
โ โ
โ โโBG_GRAY ่ฏดๆโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ๅๆๆๅญ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
่ฎพ่ฎก่ง่:
- ็ฑปๅซๆ ็ญพๅทฆๅฏน้ฝ๏ผๆฑๅญ่ตทๅงไฝ็ฝฎ็ปไธ
- ๆ้ฟๆฑๅญ = 100% ๅ่ๅฎฝๅบฆ
- ๆฏๆ นๆฑๅญๅณไพงๆ ๆณจๆฐๅผ
- ็ฌฌไธๅ็จ NAVY๏ผๅ
ถไฝ็จ BG_GRAY๏ผๆๆธๅ็ฐ่ฒ๏ผ
- ่ก้ด่ทๅๅ
eng.horizontal_bar(title='ๅ้จ้จๆฐๅญๅๆ็ๅบฆๆๅ',
items=[('็ ๅ้จ', 92, NAVY), ('ๅธๅบ้จ', 78, ACCENT_BLUE), ('่ฟ่ฅ้จ', 65, ACCENT_GREEN),
('่ดขๅก้จ', 58, ACCENT_ORANGE), ('HR', 45, MED_GRAY)],
source='Source: ...')
Category I: Image + Content Layouts
Image Placeholder Convention: Since python-pptx cannot embed web images at generation time, all image positions use a gray placeholder rectangle with crosshair lines and a label. The user replaces these with real images after generation.
Helper: add_image_placeholder()
The add_image_placeholder() helper is available via from mck_ppt.core import add_image_placeholder. Image layouts in MckEngine call it automatically โ you do not need to invoke it directly.
#40 โ Content + Right Image
Use case: Text explanation on the left, supporting visual on the right โ product screenshot, photo, diagram.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ Heading โ โ
โ โข Bullet point 1 โ โโโโโโโโโโโโโโโโ โ
โ โข Bullet point 2 โ โ IMAGE โ โ
โ โข Bullet point 3 โ โ PLACEHOLDER โ โ
โ โ โโโโโโโโโโโโโโโโ โ
โ Takeaway box (gray) โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.content_right_image(title='ไบงๅๆ ธๅฟๅ่ฝ',
subtitle='AIๆบ่ฝๅๆๅผๆ',
bullets=['ๅฎๆถๆฐๆฎๅค็', '่ชๅจๅผๅธธๆฃๆต', 'ๆบ่ฝๅณ็ญๆจ่'],
takeaway='ๅ็กฎ็่พพๅฐ98.5%๏ผ้ขๅ
่กไธๅนณๅๆฐดๅนณ20ไธช็พๅ็น',
image_label='ไบงๅๆชๅพ',
source='Source: ...')
#41 โ Left Image + Content
Use case: Visual-first layout โ image on left draws attention, text on right provides context.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ Heading โ
โ โโโโโโโโโโโโโโโโ โ โข Bullet point 1 โ
โ โ IMAGE โ โ โข Bullet point 2 โ
โ โ PLACEHOLDER โ โ โข Bullet point 3 โ
โ โโโโโโโโโโโโโโโโ โ โ
โ โ Takeaway box (gray) โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
s = prs.slides.add_slide(prs.slide_layouts[6])
add_rect(s, Inches(0), Inches(0), Inches(13.333), Inches(0.75), NAVY)
add_text(s, LM, Inches(0), CONTENT_W, Inches(0.75),
'ๅฎขๆทๆ
็จไผๅ็ๅ
ณ้ฎ่งฆ็นๅๆ',
font_size=TITLE_SIZE, font_color=WHITE, bold=True,
anchor=MSO_ANCHOR.MIDDLE)
add_hline(s, LM, Inches(0.75), CONTENT_W, BLACK, Pt(0.5))
img_w = Inches(5.4)
add_image_placeholder(s, LM, Inches(1.1), img_w, Inches(4.2), 'ๅฎขๆทๆ
็จๅฐๅพ')
rx = LM + img_w + Inches(0.3)
rw = CONTENT_W - img_w - Inches(0.3)
ty = Inches(1.1)
add_text(s, rx, ty, rw, Inches(0.4),
'ไบไธชๅ
ณ้ฎ่งฆ็นๅณๅฎ80%็ๅฎขๆทๆปกๆๅบฆ',
font_size=Pt(18), font_color=NAVY, bold=True)
bullets = [
'โข ้ฆๆฌกๆฅ่งฆ๏ผๅ็่ฎค็ฅไธ็ฌฌไธๅฐ่ฑกๅปบ็ซ',
'โข ไบงๅไฝ้ช๏ผๆ ธๅฟๅ่ฝ็ๆ็จๆงไธ็จณๅฎๆง',
'โข ๅฎๅๆๅก๏ผๅๅบ้ๅบฆไธ้ฎ้ข่งฃๅณ็',
'โข ็ปญ็บฆๅณ็ญ๏ผไปทๅผๆ็ฅไธ็ซๅๆฏ่พ',
]
add_text(s, rx, ty + Inches(0.5), rw, Inches(2.4),
bullets, font_size=BODY_SIZE, font_color=DARK_GRAY, line_spacing=Pt(8))
add_rect(s, rx, Inches(4.5), rw, Inches(0.8), BG_GRAY)
add_text(s, rx + Inches(0.2), Inches(4.5), rw - Inches(0.4), Inches(0.8),
'ๅปบ่ฎฎไผๅ
ๆ่ต"้ฆๆฌกๆฅ่งฆ"ๅ"ไบงๅไฝ้ช"ไธคไธช้ซๆ ๆ่งฆ็น',
font_size=BODY_SIZE, font_color=NAVY, bold=True, anchor=MSO_ANCHOR.MIDDLE)
add_source(s, 'Source: ๅฎขๆทๆปกๆๅบฆ่ฐ็ ๆฐๆฎ๏ผ2026 Q1')
add_page_number(s, 4, 12)
#42 โ Three Images + Descriptions
Use case: Visual comparison of three products, locations, or concepts side by side.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโค
โ โโโโโโโโโโโโ โ โโโโโโโโโโโโ โ โโโโโโโโโโโโ โ
โ โ IMAGE 1 โ โ โ IMAGE 2 โ โ โ IMAGE 3 โ โ
โ โโโโโโโโโโโโ โ โโโโโโโโโโโโ โ โโโโโโโโโโโโ โ
โ Title 1 โ Title 2 โ Title 3 โ
โ Description โ Description โ Description โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.three_images(title='ๅๅ
ฌ็ฏๅข',
items=[('ๆป้จๅคงๆฅผ', 'ไฝไบ็งๆๅญๅบๆ ธๅฟไฝ็ฝฎ', 'ๆป้จๅคๆฏ'),
('ๅผๆพๅๅ
ฌ', 'ๆๆทๅไฝ็ฉบ้ด่ฎพ่ฎก', 'ๅๅ
ฌๅบๅ'),
('ๅๆฐๅฎ้ชๅฎค', 'ๅๆฒฟๆๆฏ็ ๅๅบๅฐ', 'ๅฎ้ชๅฎค')],
source='Source: ...')
#43 โ Image + Four Key Points
Use case: Central image/diagram with four callout points arranged around or beside it.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโโโโฌโโโโโโโโโโโ โโโโโโโฌโโโโโโโโโโโ โ
โ โ 01 โ Point A โ โ 02 โ Point B โ โ
โ โโโโโโโดโโโโโโโโโโโ โโโโโโโดโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ IMAGE PLACEHOLDER โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโฌโโโโโโโโโโโ โโโโโโโฌโโโโโโโโโโโ โ
โ โ 03 โ Point C โ โ 04 โ Point D โ โ
โ โโโโโโโดโโโโโโโโโโโ โโโโโโโดโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.image_four_points(title='ๆ ธๅฟไผๅฟ',
image_label='ไบงๅ็คบๆๅพ',
points=[('้ซๆง่ฝ', 'ๆฏซ็ง็บงๅๅบ'),
('้ซๅฏ็จ', '99.99% SLA'),
('ๅฎๅ
จ', 'ๅคๅฑ้ฒๆคไฝ็ณป'),
('ๅผนๆง', '่ชๅจๆฉ็ผฉๅฎน')],
source='Source: ...')
#44 โ Full-Width Image with Overlay Text
Use case: Hero image covering the slide with semi-transparent overlay text โ for visual storytelling, case study intros.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ FULL-WIDTH IMAGE โ
โ PLACEHOLDER โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Semi-transparent dark overlay โ โ
โ โ "Quote or headline text" โ โ
โ โ โ Attribution โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.full_width_image(title='ๅ
จ็ๅธๅฑ',
image_label='ไธ็ๅฐๅพ',
overlay_text='่ฆ็ๅ
จ็32ไธชๅฝๅฎถๅๅฐๅบ',
source='Source: ...')
#45 โ Case Study with Image
Use case: Extended case study with a visual โ Situation, Approach, Result + supporting image.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ SITUATION โ โ
โ Background text... โ โโโโโโโโโโโโโโโโ โ
โ โ โ IMAGE โ โ
โ APPROACH โ โ PLACEHOLDER โ โ
โ Method text... โ โโโโโโโโโโโโโโโโ โ
โ โ โ
โ RESULT โ โโโโโโโฌโโโโโโ โ
โ Outcome metrics... โ โ KPI1โ KPI2โ โ
โ โ โโโโโโโดโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.case_study_image(title='XX้ถ่กๆกไพ',
sections=[('่ๆฏ', 'ไผ ็ป็ณป็ป่ๅ', ACCENT_BLUE),
('ๆนๆก', 'ๅพฎๆๅกๆน้ ', ACCENT_GREEN),
('ๆๆ', 'ๆ็ๆๅ10ๅ', ACCENT_ORANGE)],
image_label='็ณป็ปๆถๆๅพ',
kpis=[('10x', 'ๅค็่ฝๅ'), ('90%', 'ๆ
้ๅๅฐ')],
source='Source: ...')
#46 โ Quote with Background Image
Use case: Inspirational quote or key insight with a subtle background visual โ for keynote-style emphasis slides.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ IMAGE PLACEHOLDER โ โ
โ โ (subtle / blurred) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ "Quote text in large font" โ
โ โ Speaker Name, Title โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.quote_bg_image(title='',
quote_text='ๅๆฐไธๆฏ้ๆฉ๏ผ่ๆฏ็ๅญ็ๅฟ
้ใ',
attribution='CEO, 2026ๅนดๅ
จๅๅคงไผ',
image_label='่ๆฏๅพ',
source='')
#47 โ Goals / Targets with Illustration
Use case: Strategic goals or OKRs with a supporting illustration โ for goal-setting and planning slides.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ โ Goal 1 โ desc โ โโโโโโโโโโโโโโโโ โ
โ โ Goal 2 โ desc โ โ IMAGE โ โ
โ โ Goal 3 โ desc โ โ PLACEHOLDER โ โ
โ โ Goal 4 โ desc โ โโโโโโโโโโโโโโโโ โ
โ โ โ
โ Summary metric โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.goals_illustration(title='2026ๅนดๅบฆ็ฎๆ ',
goals=[('่ฅๆถ็ฟปๅ', '่พพๅฐยฅ20ไบฟๅนด่ฅๆถ'),
('ๅ
จ็ๅ', '่ฟๅ
ฅ5ไธชๆตทๅคๅธๅบ'),
('IPOๅๅค', 'ๅฎๆๅ่งไธๆฒป็ๅ็บง')],
image_label='็ฎๆ ๆฟๆฏๅพ',
source='Source: ...')
Category J: Advanced Data Visualization
Drawing Convention: All charts are drawn with add_rect() and add_oval() โ no matplotlib, no chart objects, no connectors. This ensures zero file corruption and full style control.
#48 โ Donut Chart
Use case: Part-of-whole composition โ market share, budget allocation, sentiment distribution. Up to 5 segments.
v2.0: Uses BLOCK_ARC native shapes โ only 4 shapes per chart (was hundreds of rect blocks). See Guard Rails Rule 9.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ โโโโโโโโโโโโโ โ โ Segment A 45% โ
โ โ DONUT โ โ โ Segment B 28% โ
โ โ (BLOCK_ โ โ โ Segment C 15% โ
โ โ ARC ร4) โ โ โ Segment D 12% โ
โ โ CENTER% โ โ โ
โ โโโโโโโโโโโโโ โ Insight text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.donut(title='2026ๅนดไธๅๅนด่ฅๆถๆธ ้ๆๆ',
segments=[(0.45, NAVY, '็บฟไธ็ด่ฅ'), (0.28, ACCENT_BLUE, '็ป้ๅ'),
(0.15, ACCENT_GREEN, 'ไผไธๅฎขๆท'), (0.12, ACCENT_ORANGE, 'ๅ
ถไป')],
center_label='ยฅ8.5ไบฟ', center_sub='ๆป่ฅๆถ',
summary='็บฟไธ็ด่ฅๆธ ้ๅ ๆฏๅๆฏๆๅ12ไธช็พๅ็น',
source='Source: ...')
#49 โ Waterfall Chart
Use case: Bridge from starting value to ending value showing incremental changes โ revenue bridge, profit walk, budget variance.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโ โ
โ Start โ โ +A -B +C -D +E โโโโ End โ
โ โ โ โโ โโ โโ โโ โโ โ โ โ
โ โ โ โโ โโ โโ โโ โโ โ โ โ
โ โ โ โโโโโโโโโโโโโโโโโโ โ โ โ
โ โโโโ โโโโ โ
โ Takeaway text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.waterfall(title='ๅฉๆถฆๅๅจ็ๅธๅพ',
items=[('2025ๅนดๅฉๆถฆ', 100, 'base'), ('่ฅๆถๅข้ฟ', 35, 'up'),
('ๆๆฌ่็', 15, 'up'), ('ๆฐๆ่ต', -20, 'down'),
('2026ๅนดๅฉๆถฆ', 130, 'base')],
source='Source: ...')
#50 โ Line / Trend Chart
Use case: Time-series trends โ revenue growth, user count, market share over time. Supports 1-4 series.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Y โ โ
โ โโโโโโ Series A (black, bold) โโโ LabelA โ
โ โโโโโโ Series B (blue) โโโโโโโโโโ LabelB โ
โ โโโโโโ Series C (green) โโโโโโโโโ LabelC โ
โ 0 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ Q1'24 Q2'24 Q3'24 Q4'24 Q1'25 โ
โ Takeaway text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.line_chart(title='ๆๆดป็จๆท่ถๅฟ',
x_labels=['1ๆ','2ๆ','3ๆ','4ๆ','5ๆ','6ๆ'],
y_labels=['0','100ไธ','200ไธ','300ไธ'],
values=[0.4, 0.45, 0.5, 0.6, 0.7, 0.82],
legend_label='ๆๆดป็จๆท',
source='Source: ...')
#51 โ Pareto Chart (Bar + Cumulative Line)
Use case: 80/20 analysis โ identifying the vital few causes/items that account for most of the impact.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Yโ โ โ Yโ โ
โ โโโโ ----100% โ
โ โ โโโโโ ------ โ
โ โ โโ โโโโโ ------ โ
โ โ โโ โโ โโโโโ- โ
โ โ โโ โโ โโ โโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ 80% line โ
โ Takeaway: Top 3 items account for 78% โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.pareto(title='็ผบ้ท็ฑปๅๅๆ๏ผๅธ็ดฏๆ๏ผ',
items=[('UI้ฎ้ข', 45), ('ๆง่ฝ', 28), ('ๅ
ผๅฎนๆง', 15), ('ๅฎๅ
จ', 8), ('ๅ
ถไป', 4)],
max_val=50,
source='Source: ...')
#52 โ Progress Bars / KPI Tracker
Use case: Multiple KPIs with target vs actual progress โ project health, OKR tracking, sales pipeline.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ KPI Name Actual / Target Status โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 78% โ On โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 52% โ Risk โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ 92% โ On โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ 85% โ On โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ 38% โ Off โ
โ Summary / insight text โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.kpi_tracker(title='OKR่ฟๅบฆ่ฟฝ่ธช',
kpis=[('่ฅๆถ็ฎๆ ', 0.78, 'ยฅ7.8ไบฟ / ยฅ10ไบฟ', 'on'),
('ๅฎขๆทๅข้ฟ', 0.92, '184ๅฎถ / 200ๅฎถ', 'on'),
('NPSๆๅ', 0.65, '72ๅ / 80ๅ', 'risk')],
source='Source: ...')
#53 โ Bubble / Scatter Plot
Use case: Two-variable comparison with size encoding โ market attractiveness vs competitive position, impact vs effort.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Y โ High โ
โ โ(large) โ(med) โ
โ โ(small) โ(large) โ
โ โ(med) โ(med) โ
โ 0 โ Low โโโโโโโโโโโโโโโโโโโโ High โ X โ
โ Legend: โ Category A โ Category B โ
โ Takeaway text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.bubble(title='ไธๅก็ปๅๅๆ',
bubbles=[(30, 70, 1.2, 'ไบงๅA', NAVY),
(60, 50, 0.8, 'ไบงๅB', ACCENT_BLUE),
(80, 30, 0.5, 'ไบงๅC', ACCENT_GREEN)],
x_label='ๅธๅบไปฝ้ข โ', y_label='ๅข้ฟ็ โ',
source='Source: ...')
#54 โ Risk / Heat Matrix
Use case: Risk assessment โ impact vs likelihood grid, with color-coded cells. Classic consulting risk register visualization.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Low Impact Med Impact High Impactโ
โ High โ Yellow โ Orange โ Red โ
โ Prob "Risk C" "Risk A" "Risk D" โ
โ Med โ Green โ Yellow โ Orange โ
โ Prob "Risk F" "Risk B" "Risk E" โ
โ Low โ Green โ Green โ Yellow โ
โ Prob "Risk G" โ
โ Action items / mitigation plan โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.risk_matrix(title='้กน็ฎ้ฃ้ฉ่ฏไผฐ็ฉ้ต',
grid_colors=[[ACCENT_GREEN,ACCENT_ORANGE,ACCENT_RED],
[ACCENT_GREEN,ACCENT_ORANGE,ACCENT_ORANGE],
[ACCENT_GREEN,ACCENT_GREEN,ACCENT_ORANGE]],
grid_lights=[[None]*3]*3,
risks=[('ๆฐๆฎๆณ้ฒ', 2, 2), ('็ณป็ปๅฎๆบ', 1, 2)],
y_labels=['้ซ','ไธญ','ไฝ'], x_labels=['ไฝ','ไธญ','้ซ'],
source='Source: ...')
Variant: Matrix + Side Panel โ When the matrix needs an accompanying insight panel (e.g. "Key Changes", "Action Items"), use a compact grid (~60% width) with a side panel (~38% width). This prevents the panel from being crushed by a full-width grid.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Axis โ Col1 Col2 Col3 โ โโโโโโโโโโโโโโโโโโโ โ
โ โโ โ โ โ โ โ โ โ โ โ โ โ โ Insight Panel โ โ
โ โ โ โ โ โ โ โ โ โ โ โ โ โ โข Bullet 1 โ โ
โ โ โ โ โ โ โ โ โ โ โ โ โ โข Bullet 2 โ โ
โ โ โ Axis label โ โ โ โโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ Summary box โ โ โ
โ โ โ โ โโโโโโโโโโโโโโโ โ โ
โ โ โ โโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layout math for the side-panel variant:
eng.risk_matrix(title='้กน็ฎ้ฃ้ฉ่ฏไผฐ็ฉ้ต',
grid_colors=[[ACCENT_GREEN,ACCENT_ORANGE,ACCENT_RED],
[ACCENT_GREEN,ACCENT_ORANGE,ACCENT_ORANGE],
[ACCENT_GREEN,ACCENT_GREEN,ACCENT_ORANGE]],
grid_lights=[[None]*3]*3,
risks=[('ๆฐๆฎๆณ้ฒ', 2, 2), ('็ณป็ปๅฎๆบ', 1, 2)],
y_labels=['้ซ','ไธญ','ไฝ'], x_labels=['ไฝ','ไธญ','้ซ'],
source='Source: ...')
Rule: When a matrix needs a companion panel, shrink cell_w to ~2.15" (from 3.0") and axis_label_w to ~0.65" (from 1.8"). This yields a panel width of ~4.2" โ enough for 6+ bullet items with comfortable reading. Never let the panel shrink below Inches(2.5).
#55 โ Gauge / Dial Chart
Use case: Single KPI health indicator โ customer satisfaction, system uptime, quality score. Visual "speedometer" metaphor.
v2.0: Uses BLOCK_ARC native shapes โ only 3 shapes for the arc (was 180+ rect blocks + white overlay). Horizontal rainbow arc (leftโtopโright). See Guard Rails Rule 9.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โญโโโโ โโ โโ โโ โโ โโโโโฎ โ
โ Redโ Orange Green โ โ
โ โฐโโโโโโโโโโโโโโโโโโโโโโฏ โ
โ 78 / 100 โ
โ โ
โ โ ๅฝๅNPS โ ่กไธๅนณๅ โ ๅปๅนดๅๆ โ ็ฎๆ โ
โ โ 78 โ 52 โ 65 โ 80 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.gauge(title='ๅฎขๆทๆปกๆๅบฆ',
score=78,
benchmarks=[('่กไธๅนณๅ', '65ๅ', ACCENT_ORANGE), ('็ฎๆ ', '85ๅ', ACCENT_GREEN)],
source='Source: ...')
#56 โ Harvey Ball Status Table
Use case: Multi-criteria evaluation matrix โ feature comparison, vendor assessment, capability maturity with visual fill indicators.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Criteria Option A Option B Option C โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ ๅ่ฝๅฎๆดๅบฆ โ โ โ โ
โ ็จๆทไฝ้ช โ โ โ โ
โ ๆๆฏๅฏๆฉๅฑ โ โ โ โ
โ ๅฎๆฝๆๆฌ โ โ โ โ
โ ไพๅบๅๅฎๅ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ Legend: โ Full โ 75% โ 50% โ 25% โ 0% โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.harvey_ball_table(title='ไพๅบๅ่ฝๅ่ฏไผฐ',
headers=['ไพๅบๅ', 'ๆๆฏ', 'ไบคไป', 'ไปทๆ ผ', 'ๆๅก'],
rows=[('ไพๅบๅA', 100, 75, 50, 100),
('ไพๅบๅB', 75, 100, 75, 50)],
source='Source: ...')
Category K: Dashboard Layouts
Dashboard Convention: Dashboards pack multiple visual elements (KPIs, charts, tables) into a single dense slide. Use 3-4 distinct visual blocks minimum. Background panels (BG_GRAY) create clear section boundaries.
#57 โ Dashboard: KPIs + Chart + Takeaways
Use case: Executive summary dashboard โ top KPI cards, a chart in the middle, and key takeaways at the bottom.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโค
โ KPI 1 โ KPI 2 โ KPI 3 โ KPI 4 โ
โ ยฅ8.5B โ +25% โ 78 โ 92% โ
โ ่ฅๆถ โ ๅข้ฟ็ โ NPS โ ็ๅญ็ โ
โโโโโโโโโโดโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโ Bar/Line Chart Area โโโโโโโโโโ โ
โ โ (any chart pattern here) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโ Takeaway Panel โโโโโโโโโโโโโโโ โ
โ โ โข Key insight 1 โข Key insight 2 โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.dashboard_kpi_chart(title='ๆๅบฆ่ฟ่ฅๆฆ่ง',
kpi_cards=[('ยฅ2.3ไบฟ', 'ๆ่ฅๆถ', '+18%', NAVY),
('98.5%', 'ๅฏ็จๆง', '่ถ
SLA', ACCENT_GREEN),
('4.8', 'NPS', '+0.3', ACCENT_BLUE)],
chart_data={'labels':['1ๆ','2ๆ','3ๆ'], 'values':[180,210,230], 'color':NAVY},
source='Source: ...')
#58 โ Dashboard: Table + Chart + Factoids
Use case: Data-dense overview โ left table, right chart, bottom factoid cards. For board-level reporting.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ โโโ Data Table โโโโ โ โโโ Chart โโโโโโโโ โ
โ โ Rows of data โ โ โ Bars or lines โ โ
โ โ with values โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโ โ
โ โ โ
โโโโโโโโโโฌโโโโโโโโโโโฌโโโโดโโโโโโโโโโโฌโโโโโโโโโโโโค
โ Fact 1 โ Fact 2 โ Fact 3 โ Fact 4 โ
โ "120+" โ "ยฅ2.3B" โ "Top 5%" โ "99.9%" โ
โโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.dashboard_table_chart(title='ๅญฃๅบฆไธๅกไปช่กจ็',
table_data={'headers':['ๆๆ ','Q1','Q2','Q3'],
'rows':[('่ฅๆถ','ยฅ1.8ไบฟ','ยฅ2.1ไบฟ','ยฅ2.5ไบฟ'),
('ๅฉๆถฆ','ยฅ0.3ไบฟ','ยฅ0.4ไบฟ','ยฅ0.5ไบฟ')]},
source='Source: ...')
Category L: Visual Storytelling & Special
Storytelling Convention: These layouts emphasize visual narrative patterns commonly found in McKinsey decks โ stakeholder maps, decision trees, checklists, and icon-driven grids. They add variety beyond standard charts and text layouts.
#59 โ Stakeholder Map
Use case: Influence vs interest matrix for stakeholders โ change management, project governance, communication planning.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Interest โ โ
โ High โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ โ
โ โ Keep Informedโ Manage Closelyโ โ
โ โ (name) โ (name) โ โ
โ โโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค โ
โ Low โ Monitor โ Keep Satisfiedโ โ
โ โ (name) โ (name) โ โ
โ โโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ โ
โ Low High โ Influence โ
โ Action plan text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.stakeholder_map(title='ๅนฒ็ณปไบบ็ฉ้ต',
quadrants=[('้ซๅ
ณๆณจ / ้ซๅฝฑๅ', ['CEO', 'CTO']),
('้ซๅ
ณๆณจ / ไฝๅฝฑๅ', ['้กน็ฎ็ป็', 'ไบงๅ็ป็']),
('ไฝๅ
ณๆณจ / ้ซๅฝฑๅ', ['็็ฎกๆบๆ']),
('ไฝๅ
ณๆณจ / ไฝๅฝฑๅ', ['ๆฎ้ๅๅทฅ'])],
source='Source: ...')
#60 โ Issue / Decision Tree
Use case: Breaking down a complex decision into sub-decisions โ problem decomposition, MECE logic tree, diagnostic framework.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโ โ
โ โ Root โโโโฌโโ โโโโโโโโโโโโโฌโโ โโโโโโโโโโ โ
โ โ Issue โ โ โ Branch โ โ โ Leaf 1 โ โ
โ โโโโโโโโโโ โ โ A โ โ โโโโโโโโโโ โ
โ โ โโโโโโโโโโ โโโ โโโโโโโโโโ โ
โ โ โ Leaf 2 โ โ
โ โ โโโโโโโโโโ โ
โ โโโ โโโโโโโโโโโโโฌโโ โโโโโโโโโโ โ
โ โ Branch โ โ โ Leaf 3 โ โ
โ โ B โ โโโ โโโโโโโโโโ โ
โ โโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.decision_tree(title='ๆๆฏ้ๅๅณ็ญๆ ',
root='ๆฏๅฆ้่ฆๅฎๆถๅค็๏ผ',
branches=[('ๆฏ', ['ๆตๅผ่ฎก็ฎ', 'Kafka + Flink']),
('ๅฆ', ['ๆนๅค็', 'Spark + Hive'])],
source='Source: ...')
#61 โ Five-Row Checklist / Status
Use case: Task completion status, implementation checklist, audit findings โ each row with status indicator.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ # โ Task / Item โ Owner โ Status โ
โ โโโผโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโ โ
โ 1 โ Data migration โ TechOpsโ โ Done โ
โ 2 โ UAT testing โ QA โ โ Done โ
โ 3 โ Security audit โ InfoSecโ โ Active โ
โ 4 โ Training rollout โ HR โ โ Pending โ
โ 5 โ Go-live sign-off โ PMO โ โ Pending โ
โ โโโผโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโ โ
โ Progress: 2/5 complete (40%) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.checklist(title='ไธ็บฟๅๅคๆฃๆฅๆธ
ๅ',
columns=['ๆฃๆฅ้กน', '่ด่ดฃไบบ', 'ๆชๆญขๆฅ', '็ถๆ'],
col_widths=[Inches(4.5), Inches(2.0), Inches(2.0), Inches(2.0)],
rows=[('ๅฎๅ
จๅฎก่ฎกๅฎๆ', 'ๅผ ไธ', '3/15', 'done'),
('ๆง่ฝๅๆต้่ฟ', 'ๆๅ', '3/20', 'wip'),
('ๆๆกฃๆดๆฐ', '็ไบ', '3/25', 'todo')],
status_map={'done': ('โ
ๅฎๆ', ACCENT_GREEN, LIGHT_GREEN),
'wip': ('๐ ่ฟ่กไธญ', ACCENT_ORANGE, LIGHT_ORANGE),
'todo': ('โณ ๅพ
ๅผๅง', MED_GRAY, BG_GRAY)},
source='Source: ...')
#62 โ Metric Comparison Row
Use case: Before/after or multi-period comparison with large numbers โ performance review, transformation impact, A/B test results.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโ โ
โ โ BEFORE โ โ AFTER โ โ
โ โ ยฅ5.2ไบฟ โ โ ยฅ8.5ไบฟ โ โ
โ โ ่ฅๆถ โ โ ่ฅๆถ โ โ
โ โโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโ โ
โ โ 45ๅคฉ โ โ 28ๅคฉ โ โ
โ โ ๅบๅญๅจ่ฝฌ โ โ ๅบๅญๅจ่ฝฌ โ โ
โ โโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ Summary text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.metric_comparison(title='ๆฐๅญๅ่ฝฌๅๅๅๅ
ณ้ฎๆๆ ๅฏนๆฏ',
metrics=[('่ฅๆถ่งๆจก', 'ยฅ5.2ไบฟ', 'ยฅ8.5ไบฟ', '+63%'),
('ๅบๅญๅจ่ฝฌ', '45ๅคฉ', '28ๅคฉ', 'โ38%'),
('ๅฎขๆทNPS', '52', '78', '+50%')],
source='Source: ...')
#63 โ Icon Grid (4ร2 or 3ร3)
Use case: Capability overview, service catalog, feature grid โ each cell with icon placeholder + title + description.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโค
โ [icon] โ [icon] โ [icon] โ
โ Title A โ Title B โ Title C โ
โ Description โ Description โ Description โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโค
โ [icon] โ [icon] โ [icon] โ
โ Title D โ Title E โ Title F โ
โ Description โ Description โ Description โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.icon_grid(title='ไบงๅๅ่ฝ็ฉ้ต',
items=[('๐', 'ๆบ่ฝๆ็ดข', 'ๆฏซ็ง็บงๅ
จๆๆฃ็ดข'),
('๐', 'ๆฐๆฎๅๆ', 'ๅฎๆถBIไปช่กจ็'),
('๐ค', 'AIๅฉๆ', '่ช็ถ่ฏญ่จไบคไบ'),
('๐', 'ๅฎๅ
จ้ฒๆค', 'ๅคๅฑๅ ๅฏไฝ็ณป')],
source='Source: ...')
#64 โ Pie Chart (Simple)
Use case: Simple part-of-whole with โค5 segments โ budget allocation, market share, time allocation.
v2.0: Uses BLOCK_ARC native shapes with inner_ratio=0 for solid pie sectors โ only 4 shapes per chart (was 2000+ rect blocks). See Guard Rails Rule 9.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ โโโโโโโโโโโโโ โ โ Segment A 42% โ
โ โ PIE โ โ โ Segment B 28% โ
โ โ (BLOCK_ โ โ โ Segment C 18% โ
โ โ ARC ร4) โ โ โ Segment D 12% โ
โ โโโโโโโโโโโโโ โ โ
โ Insight text box โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.pie(title='ๅธๅบไปฝ้ขๅๅธ',
segments=[(0.35, NAVY, 'ๆไปฌ', ''), (0.25, ACCENT_BLUE, '็ซๅA', ''),
(0.20, ACCENT_GREEN, '็ซๅB', ''), (0.20, ACCENT_ORANGE, 'ๅ
ถไป', '')],
source='Source: ...')
#65 โ SWOT Analysis
Use case: Classic strategic analysis โ Strengths, Weaknesses, Opportunities, Threats in a 2ร2 color-coded grid.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโค
โ STRENGTHS (Blue) โ WEAKNESSES (Orange) โ
โ โข Point 1 โ โข Point 1 โ
โ โข Point 2 โ โข Point 2 โ
โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโค
โ OPPORTUNITIES (Green)โ THREATS (Red) โ
โ โข Point 1 โ โข Point 1 โ
โ โข Point 2 โ โข Point 2 โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.swot(title='SWOTๅๆ',
quadrants=[('ไผๅฟ Strengths', ['ๆๆฏ้ขๅ
', 'ๅข้ไผ็ง', '่ต้ๅ
่ฃ']),
('ๅฃๅฟ Weaknesses', ['ๅ็็ฅๅๅบฆไฝ', '้ๅฎ็ฝ็ปๆ้']),
('ๆบไผ Opportunities', ['ๅธๅบๅฟซ้ๅข้ฟ', 'ๆฟ็ญๅฉๅฅฝ']),
('ๅจ่ Threats', ['ๅทจๅคดๅ
ฅๅบ', 'ไบบๆ็ซไบๆฟ็'])],
source='Source: ...')
#66 โ Agenda / Meeting Outline
Use case: Meeting agenda with time allocations, speaker assignments โ for workshop facilitation, board meetings.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Time โ Topic โ Speaker โ Min โ
โ โโโโโโโโโผโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโ โ
โ 09:00 โ Opening & Context โ CEO โ 15 โ
โ 09:15 โ Market Analysis โ VP Mkt โ 30 โ
โ 09:45 โ Product Roadmap โ CPO โ 30 โ
โ 10:15 โ Break โ โ 15 โ
โ 10:30 โ Financial Review โ CFO โ 30 โ
โ 11:00 โ Q&A & Next Steps โ All โ 30 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.agenda(title='ๅญฃๅบฆๅ้กพไผ่ฎฎ่ฎฎ็จ',
headers=[('่ฎฎ้ข', Inches(5.0)), ('ๆถ้ด', Inches(2.0)),
('่ด่ดฃไบบ', Inches(2.0)), ('ๅคๆณจ', Inches(2.5))],
items=[('Q3ไธ็ปฉๅ้กพ', '09:00-09:30', 'ๅผ ๆป', '', 'key'),
('ไบงๅ่ทฏ็บฟๅพๆดๆฐ', '09:30-10:00', 'ๆๆป', '', 'normal'),
('่ถๆญ', '10:00-10:15', '', '', 'break'),
('2026่งๅ่ฎจ่ฎบ', '10:15-11:00', 'ๅ
จๅ', '', 'key')],
source='Source: ...')
#67 โ Value Chain / Horizontal Flow
Use case: End-to-end value chain visualization โ supply chain, service delivery pipeline, customer journey stages.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโ โ โโโโโโโโโ โ โโโโโโโโโ โ โโโโโโโโโ โ โโโโโโโโโ โ
โ โStage 1โ โStage 2โ โStage 3โ โStage 4โ โStage 5โ โ
โ โ desc โ โ desc โ โ desc โ โ desc โ โ desc โ โ
โ โ KPI โ โ KPI โ โ KPI โ โ KPI โ โ KPI โ โ
โ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโ โ
โ โ
โ Insight / bottleneck analysis โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.value_chain(title='ไปทๅผ้พๅๆ',
stages=[('็ ๅ', 'ไบงๅ่ฎพ่ฎกไธๆๆฏๅผๅ', ACCENT_BLUE),
('็ไบง', '็ฒพ็ๅถ้ ไธ่ดจ้็ฎกๆง', ACCENT_GREEN),
('่ฅ้', 'ๅ็ๅปบ่ฎพไธๆธ ้็ฎก็', ACCENT_ORANGE),
('ๆๅก', 'ๅฎขๆทๆฏๆไธๆ็ปญ่ฟ่ฅ', NAVY)],
source='Source: ...')
#68 โ Two-Column Image + Text Grid
Use case: Visual catalog โ 2 rows ร 2 columns, each cell with image + title + description. Product showcase, location overview.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโโโโโ Title A โ โโโโโโโโ Title B โ
โ โIMAGE โ Description โ โIMAGE โ Description โ
โ โโโโโโโโ โ โโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโค
โ โโโโโโโโ Title C โ โโโโโโโโ Title D โ
โ โIMAGE โ Description โ โIMAGE โ Description โ
โ โโโโโโโโ โ โโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.two_col_image_grid(title='่งฃๅณๆนๆก็ฉ้ต',
items=[('ๆบ่ฝๅฎขๆ', '7ร24ๅฐๆถAIๅฎขๆ', ACCENT_BLUE, 'ๅฎขๆ็ณป็ปๆชๅพ'),
('ๆฐๆฎๅๆ', 'ๅฎๆถBIไปช่กจ็', ACCENT_GREEN, 'ๅๆ้ขๆฟ'),
('ๆต็จ่ชๅจๅ', 'RPAๆบๅจไบบๆต็จ', ACCENT_ORANGE, '่ชๅจๅๆต็จ'),
('ๅฎๅ
จๅ่ง', 'ไธ็ซๅผๅ่ง็ฎก็', NAVY, 'ๅฎๅ
จๆถๆ')],
source='Source: ...')
#69 โ Numbered List with Side Panel
Use case: Key recommendations or findings with a highlighted side panel โ consulting recommendations, audit findings.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ 1 Recommendation A โ โโโโโโโโโโโโโโโโโ โ
โ Detail text... โ โ HIGHLIGHT โ โ
โ โ โ PANEL โ โ
โ 2 Recommendation B โ โ โ โ
โ Detail text... โ โ Key metric โ โ
โ โ โ or quote โ โ
โ 3 Recommendation C โ โ โ โ
โ Detail text... โ โโโโโโโโโโโโโโโโโ โ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.numbered_list_panel(title='ๆ็ฅๅปบ่ฎฎ',
items=[('ไผๅ
ๆจ่ฟAI่ฝๅๅปบ่ฎพ', '็ญๆๅ
้ไธญ่ตๆบๆ้ AIๆ ธๅฟ็ซไบๅ'),
('ๅปบ็ซๆฐๆฎๆฒป็ไฝ็ณป', '็ปไธๆฐๆฎๆ ๅ๏ผๆ้ๆฐๆฎๅญคๅฒ'),
('ๆๅปบๅผๆพ็ๆ', 'ไธๅไฝไผไผดๅ
ฑๅปบ่กไธ่งฃๅณๆนๆก')],
panel=('ๆ็ฅ็ฎๆ ', ['2026ๅนดAIๆธ้็่พพๅฐ60%', 'ๆฐๆฎ่ตไบงไปทๅผๆๅ3ๅ', 'ๅไฝไผไผด่ถ
่ฟ100ๅฎถ']),
source='Source: ...')
#70 โ Stacked Area Chart
Use case: Cumulative trends over time โ market composition, revenue streams, resource allocation showing both individual and total trends.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [Action Title โ full width, NAVY bg] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Y โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ Total โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ Series C โ
โ โโโโโโโโโโโโโโโโโโ Series B โ
โ โโโโโโโโโโ Series A โ
โ 0 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ 2020 2021 2022 2023 2024 2025 โ
โ Takeaway text... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Source | Page N/Total โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
eng.stacked_area(title='็จๆทๅข้ฟ่ถๅฟ',
years=['2022', '2023', '2024', '2025', '2026E'],
series_data=[('ไผไธ็จๆท', [20, 35, 55, 80, 120], NAVY),
('ไธชไบบ็จๆท', [50, 80, 120, 160, 200], ACCENT_BLUE)],
max_val=350, source='Source: ...')
MckEngine API Reference
All 67 public methods on MckEngine. Every method creates exactly one slide (except save()).
Initialization
eng = MckEngine(total_slides=N)
Save
eng.save('output/deck.pptx')
Structure
eng.cover(title, subtitle='', author='', date='', cover_image=None)
#1 Cover Slide โ title, subtitle, author, date, accent line, optional AI-generated cover image.
cover_image: None (no image, default), 'auto' (AI-generated via Hunyuan 2.0), or 'path.png' (custom image file).
When cover_image='auto': generates a McKinsey-style cover illustration automatically.
Requires env vars: TENCENT_SECRET_ID, TENCENT_SECRET_KEY.
eng.toc(title='็ฎๅฝ', items=None, source='')
#6 Table of Contents โ numbered items with descriptions.
items: list of (num, title, description)
eng.section_divider(section_label, title, subtitle='')
#5 Section Divider โ navy left bar, large title.
eng.appendix_title(title, subtitle='')
#7 Appendix Title โ centered title with accent lines.
eng.closing(title, message='', source_text='')
#36 Closing / Thank You slide.
Data & Stats
eng.big_number(title, number, unit='', description='', detail_items=None, source='', bottom_bar=None)
#8 Big Number โ large stat with context.
detail_items: list[str] bullet points shown below.
bottom_bar: (label, text) or None.
eng.two_stat(title, stats, detail_items=None, source='')
#9 Two-Stat Comparison โ two big numbers side by side.
stats: list of (number, label, is_navy:bool)
eng.three_stat(title, stats, detail_items=None, source='')
#10 Three-Stat โ three big numbers in a row.
stats: list of 3 (number, label, is_navy:bool)
eng.data_table(title, headers, rows, col_widths=None, source='', bottom_bar=None)
#11 Data Table โ header row + data rows with separators.
headers: list[str], rows: list[list[str]], col_widths: list[Inches] or auto.
eng.metric_cards(title, cards, source='')
#12 Metric Cards โ 3-4 accent-colored cards.
cards: list of (letter, card_title, description, accent_color, light_bg)
or (letter, card_title, description) โ auto-colors from ACCENT_PAIRS.
eng.metric_comparison(title, metrics, source='')
#62 Metric Comparison โ before/after row cards with delta badges.
metrics: list of (label, before_val, after_val, delta_str).
Frameworks & Matrices
eng.matrix_2x2(title, quadrants, axis_labels=None, source='', bottom_bar=None)
#13 2ร2 Matrix โ four quadrants.
quadrants: list of 4 (label, bg_color, description).
axis_labels: (x_label, y_label) or None.
eng.table_insight(title, headers, rows, insights, col_widths=None, insight_title='ๅฏ็คบ๏ผ', source='', bottom_bar=None)
#71 Table+Insight โ left data table + right insight panel with chevron icon.
headers: list[str], rows: list[list[str]], insights: list[str].
Supports bold markup in cell text. Replaces retired #14 Three-Pillar.
eng.pyramid(title, levels, source='', bottom_bar=None)
#15 Pyramid โ top-down widening layers.
levels: list of (label, description, width_inches:float).
eng.process_chevron(title, steps, source='', bottom_bar=None)
#16 Process Chevron โ horizontal step flow with arrows.
steps: list of (label, step_title, description).
eng.venn(title, circles, overlap_label='', right_text=None, source='')
#17 Venn Diagram โ overlapping rectangles for 2-3 sets.
circles: list of (label, points:list[str], x, y, w, h) positioned rects.
overlap_label: text for overlap zone.
right_text: list[str] explanation on the right side.
eng.temple(title, roof_text, pillar_names, foundation_text, pillar_colors=None, source='')
#18 Temple / House Framework โ roof + pillars + foundation.
pillar_names: list[str], pillar_colors: list[RGBColor] or auto.
Comparison & Evaluation
eng.side_by_side(title, options, source='')
#19 Side-by-Side Comparison โ two columns with navy headers.
options: list of 2 (option_title, points:list[str]).
eng.before_after(title, before_title, before_points, after_title, after_points, source='')
#20 Before/After โ gray (before) + navy (after) with arrow.
eng.pros_cons(title, pros_title, pros, cons_title, cons, conclusion=None, source='')
#21 Pros/Cons โ two-column layout.
pros, cons: list[str].
conclusion: (label, text) or None.
eng.rag_status(title, headers, rows, source='')
#22 RAG Status โ table with red/amber/green status dots.
headers: list[str], rows: list of (name, status_color, *values, note).
eng.scorecard(title, items, source='')
#23 Scorecard โ items with progress bars.
items: list of (name, score_str, pct_float_0_to_1)
eng.checklist(title, columns, col_widths, rows, status_map=None, source='', bottom_bar=None)
#61 Checklist / Status table.
columns: list[str] header labels.
col_widths: list[Inches].
rows: list of tuples โ last element is status key.
status_map: dict of status_key โ (label, color, bg_color).
eng.swot(title, quadrants, source='')
#65 SWOT Analysis โ 2ร2 colored grid.
quadrants: list of 4 (label, accent_color, light_bg, points:list[str]).
Narrative
eng.executive_summary(title, headline, items, source='')
#24 Executive Summary โ navy headline + numbered items.
headline: str, items: list of (num, item_title, description).
eng.key_takeaway(title, left_text, takeaways, source='')
#25 Key Takeaway โ left analysis + right gray panel.
left_text: list[str], takeaways: list[str].
eng.quote(quote_text, attribution='')
#26 Quote Slide โ centered quote with accent lines.
eng.two_column_text(title, columns, source='')
#27 Two-Column Text โ lettered columns with bullet lists.
columns: list of 2 (letter, col_title, points:list[str]).
eng.four_column(title, items, source='')
#28 Four-Column Overview โ 4 vertical cards.
items: list of (num, col_title, description:str_or_list).
eng.numbered_list_panel(title, items, panel=None, source='')
#69 Numbered List + Side Panel โ left numbered list + right accent panel.
items: list of (item_title, description).
panel: dict with 'subtitle','big_number','big_label','metrics':list[(label,value)].
Timeline & Process
eng.timeline(title, milestones, source='', bottom_bar=None)
#29 Timeline / Roadmap โ horizontal line with milestone nodes.
milestones: list of (label, description).
eng.vertical_steps(title, steps, source='', bottom_bar=None)
#30 Vertical Steps โ top-down numbered steps.
steps: list of (num, step_title, description).
eng.cycle(title, phases, right_panel=None, source='')
#31 Cycle Diagram โ rectangular nodes with arrows in a loop.
phases: list of (label, x_inches, y_inches) โ positioned boxes.
right_panel: (panel_title, points:list[str]) or None.
eng.funnel(title, stages, source='')
#32 Funnel โ top-down narrowing bars.
stages: list of (name, count_label, pct_float).
eng.value_chain(title, stages, source='', bottom_bar=None)
#67 Value Chain / Horizontal Flow โ stages with arrows.
stages: list of (stage_title, description, accent_color).
Stages fill the full content width; height fills available vertical space.
Team & Cases
eng.meet_the_team(title, members, source='')
#33 Meet the Team โ profile cards in a row.
members: list of (name, role, bio:str_or_list).
eng.case_study(title, sections, result_box=None, source='')
#34 Case Study โ S/A/R or custom sections.
sections: list of (letter, section_title, description).
result_box: (label, text) or None.
eng.action_items(title, actions, source='')
#35 Action Items โ cards with timeline + owner.
actions: list of (action_title, timeline, description, owner).
eng.case_study_image(title, sections, image_label, kpis=None, source='')
#45 Case Study with Image โ left text sections + right image + KPIs.
sections: list of (label, text, accent_color).
kpis: list of (value, label) or None.
Charts (BLOCK_ARC)
eng.donut(title, segments, center_label='', center_sub='', legend_x=None, summary=None, source='')
#48 Donut Chart โ BLOCK_ARC ring segments.
segments: list of (pct_float, color, label).
eng.pie(title, segments, legend_x=None, summary=None, source='')
#64 Pie Chart โ BLOCK_ARC with inner_ratio=0 (solid).
segments: list of (pct_float, color, label, sub_label).
eng.gauge(title, score, benchmarks=None, source='')
#55 Gauge โ semicircle rainbow arc with center score.
score: int 0-100.
benchmarks: list of (label, value_str, color) shown below gauge.
Charts (Bar/Line)
eng.grouped_bar(title, categories, series, data, max_val=None, y_ticks=None, summary=None, source='')
#37 Grouped Bar Chart โ vertical bars grouped by category.
categories: list[str] x-labels. series: list of (name, color).
data: list[list[int]] โ data[cat_idx][series_idx].
summary: (label, text) or None.
eng.stacked_bar(title, periods, series, data, summary=None, source='')
#38 Stacked Bar Chart โ 100% stacked vertical bars.
periods: list[str] x-labels. series: list of (name, color).
data: list[list[int]] โ percentages, data[period_idx][series_idx].
summary: (label, text) or None.
eng.horizontal_bar(title, items, summary=None, source='')
#39 Horizontal Bar Chart โ labeled bars with percentage.
items: list of (name, pct_int_0_to_100, bar_color).
summary: (label, text) or None.
eng.line_chart(title, x_labels, y_labels, values, legend_label='', summary=None, source='')
#50 Line Chart โ single line with dot approximation.
x_labels: list[str], y_labels: list[str], values: list[float] 0.0-1.0 normalized.
eng.waterfall(title, items, max_val=None, legend_items=None, summary=None, source='')
#49 Waterfall Chart โ bridge from start to end.
items: list of (label, value, type) โ type: 'base'|'up'|'down'.
eng.pareto(title, items, max_val=None, summary=None, source='')
#51 Pareto Chart โ descending bars with value/pct labels.
items: list of (label, value).
eng.stacked_area(title, years, series_data, max_val=None, summary=None, source='')
#70 Stacked Area Chart โ stacked columns for area approximation.
years: list[str] x-labels.
series_data: list of (name, values:list[int], color).
Charts (Advanced)
eng.bubble(title, bubbles, x_label='', y_label='', legend_items=None, summary=None, source='')
#53 Bubble / Scatter โ positioned circles on XY plane.
bubbles: list of (x_pct, y_pct, size_inches, label, color).
eng.kpi_tracker(title, kpis, summary=None, source='')
#52 KPI Tracker โ progress bars with status dots.
kpis: list of (name, pct_float, detail, status_key).
status_key: 'on'|'risk'|'off'.
eng.risk_matrix(title, grid_colors, grid_lights, risks, y_labels=None, x_labels=None, notes=None, source='')
#54 Risk Matrix โ 3ร3 heatmap grid with risk labels.
grid_colors: 3ร3 list[list[RGBColor]] dot colors.
grid_lights: 3ร3 list[list[RGBColor]] cell backgrounds.
risks: list of (row, col, name).
notes: list[str] or None for bottom panel.
eng.harvey_ball_table(title, criteria, options, scores, legend_text=None, summary=None, source='')
#56 Harvey Ball Table โ matrix with Harvey Ball indicators.
criteria: list[str] row labels. options: list[str] column headers.
scores: list[list[int]] โ scores[row][col], 0-4.
Dashboards
eng.dashboard_kpi_chart(title, kpi_cards, chart_data=None, summary=None, source='')
#57 Dashboard KPI + Chart โ top KPI cards + bottom mini chart.
kpi_cards: list of (value, label, detail, accent_color).
chart_data: dict with 'labels','actual','target','max_val','legend'.
eng.dashboard_table_chart(title, table_data, chart_data=None, factoids=None, source='')
#58 Dashboard Table + Chart โ left table + right mini chart + bottom facts.
table_data: dict with 'headers','col_widths','rows'.
chart_data: dict with 'title','items':(name, value, max_val).
factoids: list of (value, label, color).
Image Layouts
eng.content_right_image(title, subtitle, bullets, takeaway='', image_label='Image', source='')
#40 Content + Right Image.
eng.three_images(title, items, source='')
#42 Three Images โ three image+caption columns.
items: list of (caption_title, description, image_label).
eng.image_four_points(title, image_label, points, source='')
#43 Image + 4 Points โ center image with 4 corner cards.
points: list of 4 (point_title, description, accent_color).
eng.full_width_image(title, image_label, overlay_text='', attribution='', source='')
#44 Full-Width Image โ edge-to-edge image with text overlay.
eng.quote_bg_image(image_label, quote_text, attribution='', source='')
#46 Quote with Background Image โ image top + quote bottom.
eng.goals_illustration(title, goals, image_label, source='')
#47 Goals with Illustration โ left numbered goals + right image.
goals: list of (goal_title, description, accent_color).
eng.two_col_image_grid(title, items, source='')
#68 Two-Column Image + Text Grid โ 2ร2 image-text cards.
items: list of (card_title, description, accent_color, image_label).
Special
eng.icon_grid(title, items, cols=3, source='')
#63 Icon Grid โ grid of icon cards.
items: list of (item_title, description, accent_color).
eng.stakeholder_map(title, quadrants, x_label='ๅฝฑๅๅ โ', y_label='ๅ
ณๆณจๅบฆ โ', summary=None, source='')
#59 Stakeholder Map โ 2ร2 quadrant with stakeholder lists.
quadrants: list of 4 (label_cn, label_en, bg_color, members:list[str]).
eng.decision_tree(title, root, branches, right_panel=None, source='')
#60 Decision Tree โ root โ L1 โ L2 hierarchy with connector lines.
root: (label,).
branches: list of (L1_title, L1_metric, L1_color, children:list[(name, metric)]).
right_panel: (panel_title, points:list[str]) or None.
eng.agenda(title, headers, items, footer_text='', source='')
#66 Agenda โ table-style meeting agenda.
headers: list of (label, width).
items: list of (*values, item_type) โ type: 'key'|'normal'|'break'.
Common Issues & Solutions
Problem 1: PPT Won't Open / "File Needs Repair"
Cause: Shapes or connectors carry <p:style> with effectRef idx="2", referencing theme effects (shadows/3D)
Solution (three-layer defense):
- Never use connectors โ use
add_hline() (thin rectangle) instead of add_connector()
- Inline cleanup โ every
add_rect() and add_oval() calls _clean_shape() to remove p:style
- Post-save cleanup โ
full_cleanup() removes ALL <p:style> from every slide XML + theme effects
Problem 2: Text Not Displaying Correctly in PowerPoint
Cause: Chinese characters rendered as English font instead of KaiTi
Solution:
Problem 3: Font Sizes Inconsistent Across Slides
Cause: Using custom sizes instead of defined hierarchy
Solution:
Problem 4: Columns/Lists Not Aligning Vertically
Cause: Mixing different line spacing or not accounting for text height
Solution:
- Use consistent
line_spacing=Pt(N) in add_text() calls
- Calculate row heights in tables based on actual text size:
- For 14pt text with spacing: use 1.0" height minimum
- For lists with bullets: use 0.35" height per line + 8pt spacing
- Test by saving and opening in PowerPoint to verify alignment
Problem 5: Chinese Multi-Line Text Overlapping (v1.5.0 Fix)
Cause: add_text() only set space_before (paragraph spacing) but did NOT set p.line_spacing (the actual line height / <a:lnSpc> in OOXML). When Chinese text wraps within a paragraph, lines overlap because PowerPoint has no explicit line height to follow.
Solution (fixed in v1.5.0, refined in v1.10.3):
add_text() sets p.line_spacing for every paragraph with a two-tier strategy:
- Titles (font_size โฅ 18pt):
p.line_spacing = 0.93 โ multiple spacing for tighter, more professional title rendering
- Body text (font_size < 18pt):
p.line_spacing = Pt(font_size.pt * 1.35) โ fixed Pt spacing to prevent CJK overlap
- Title multiple spacing (
0.93) maps to <a:lnSpc><a:spcPct val="93000"/> in OOXML
- Body fixed spacing maps to
<a:lnSpc><a:spcPts> in OOXML
Problem 6: Content Overflowing Container Boxes (v1.9.0)
Cause: Text placed inside a colored rectangle (add_rect) with identical coordinates to the box itself, so text runs to the very edge and may visually overflow, especially with CJK characters that have wider natural widths.
Solution: Always inset text boxes by at least 0.15" on left/right within their container:
add_rect(s, box_x, box_y, box_w, box_h, BG_GRAY)
add_text(s, box_x + Inches(0.3), box_y, box_w - Inches(0.6), box_h, text, ...)
For tight spaces, reduce font_size by 1-2pt rather than reducing padding below 0.15".
Problem 7: Chart Legend Colors Mismatch (v1.9.0)
Cause: Legend text uses Unicode "โ " character in black, while actual chart bars/areas use NAVY/ACCENT_RED/ACCENT_GREEN โ creating confusion about which color maps to which series.
Solution: Replace text-only legends with add_rect() color squares. See Production Guard Rails Rule 4 for the standard pattern. Each legend item = colored square (0.15" ร 0.15") + label text.
Problem 8: Inconsistent Title Bar Styles (v1.9.0)
Cause: Mixing add_navy_title_bar() (navy background + white text) and add_action_title() (white background + black text + underline) on different slides within the same deck, creating visual inconsistency.
Solution: Use add_action_title() exclusively for all content slides. Remove add_navy_title_bar() usage. See Production Guard Rails Rule 5.
Migration: When converting add_navy_title_bar() โ add_action_title(), adjust content start position from Inches(1.0) to Inches(1.25) since add_action_title() occupies slightly more vertical space.
Problem 9: Axis Labels Off-Center in Matrix Charts (v1.9.0)
Cause: Y-axis label positioned at a fixed left offset, X-axis label at a fixed bottom offset โ neither centered on the actual grid dimensions when grid position/size changes.
Solution: Calculate axis label positions from actual grid dimensions. See Production Guard Rails Rule 6 for the centering formula.
Problem 10: Bottom Whitespace Under Charts (v1.9.0)
Cause: Chart height calculated independently of the bottom summary bar position, leaving 0.5-1.0" of dead space between chart bottom and the summary bar.
Solution: Either extend chart height to fill the gap or move the bottom bar up. Target maximum 0.3" gap. See Production Guard Rails Rule 3.
Problem 11: Cover Slide Title/Subtitle Overlap (v1.10.4)
Cause: Cover slide title textbox height is fixed (e.g. Inches(1.0)), but when the title contains \n (multi-line), two lines of 44pt text require ~1.66" of vertical space. The subtitle is positioned at a fixed y coordinate (e.g. Inches(3.5)), so the title overflows its textbox and visually overlaps the subtitle.
Solution: Calculate title height dynamically based on line count, then position subtitle/author/date relative to title bottom:
lines = title.split('\n') if isinstance(title, str) else title
n_lines = len(lines) if isinstance(lines, list) else title.count('\n') + 1
title_h = Inches(0.8 + 0.65 * max(n_lines - 1, 0))
add_text(s, Inches(1), Inches(1.2), Inches(11), title_h,
title, font_size=Pt(44), font_color=NAVY, bold=True, font_name='Georgia')
sub_y = Inches(1.2) + title_h + Inches(0.3)
if subtitle:
add_text(s, Inches(1), sub_y, Inches(11), Inches(0.8),
subtitle, font_size=Pt(24), font_color=DARK_GRAY)
sub_y += Inches(1.0)
Rule: Never use fixed y coordinates for cover slide elements below the title. Always compute positions relative to title bottom.
Problem 12: Action Title Text Not Flush Against Separator Line (v1.10.4)
Cause: add_action_title() uses anchor=MSO_ANCHOR.MIDDLE (vertical center alignment), so single-line titles float in the middle of the title bar, leaving a visible gap between the text baseline and the separator line at Inches(1.05).
Solution: Change the text anchor from MSO_ANCHOR.MIDDLE to MSO_ANCHOR.BOTTOM so the text sits flush against the bottom of the textbox, right above the separator line:
def add_action_title(slide, text, title_size=Pt(22)):
add_text(s, Inches(0.8), Inches(0.15), Inches(11.7), Inches(0.9), text,
font_size=title_size, font_color=BLACK, bold=True, font_name='Georgia',
anchor=MSO_ANCHOR.BOTTOM)
add_hline(s, Inches(0.8), Inches(1.05), Inches(11.7), BLACK, Pt(0.5))
Problem 13: Checklist Rows Overflowing Page Bottom (v1.10.4)
Cause: #61 Checklist / Status uses a fixed row_h = Inches(0.55) or Inches(0.85). With 7+ rows, total height = 0.85 * 7 = 5.95", starting from ~Inches(1.45) extends to Inches(7.4) โ exceeding page height (7.5") and overlapping with source/page number areas.
Solution: Calculate row_h dynamically based on available vertical space, and switch to smaller font when rows are tight:
bottom_limit = BOTTOM_BAR_Y - Inches(0.1) if bottom_bar else SOURCE_Y - Inches(0.05)
available_h = bottom_limit - (header_y + Inches(0.5))
row_h = min(Inches(0.85), available_h / max(len(rows), 1))
row_font = SMALL_SIZE if row_h < Inches(0.65) else BODY_SIZE
Rule: For any layout with a variable number of rows/items, ALWAYS compute item height dynamically: item_h = min(MAX_ITEM_H, available_space / n_items). Never use a fixed height that assumes a specific item count.
Problem 14: Value Chain Stages Not Filling Content Area (v1.10.4)
Cause: #67 Value Chain uses a fixed stage_w = Inches(2.0) and centers stages. With 4 stages, total width = 4*2.0 + 3*0.4 = 9.2", centered in CW=11.73" leaves ~1.27" empty on each side. Stage height is also fixed at Inches(2.8), leaving ~3.3" of dead space below.
Solution: Calculate stage width and height dynamically to fill the entire content area:
n = len(stages)
arrow_w = Inches(0.35)
stage_w = (CW - arrow_w * (n - 1)) / n
stage_y = CONTENT_TOP + Inches(0.1)
stage_h = (BOTTOM_BAR_Y - Inches(0.15) - stage_y) if bottom_bar else (SOURCE_Y - Inches(0.15) - stage_y)
Rule: For layouts with N equally-sized elements arranged horizontally, compute width as (CW - gap * (N-1)) / N, not a fixed Inches(2.0). For vertical space, fill down to the bottom bar or source line.
Problem 15: Closing Slide Bottom Line Too Short (v1.10.4)
Cause: The closing slide's bottom decorative line uses a fixed width like Inches(3), which only spans a small portion of the slide โ looking unfinished and asymmetric.
Solution: Use CW (content width) as the line width, and LM (left margin) as the starting x, so the line spans the full content area:
add_hline(s, Inches(1), Inches(6.8), Inches(3), NAVY, Pt(2))
add_hline(s, LM, Inches(6.8), CW, NAVY, Pt(2))
Rule: Decorative horizontal lines on structural slides (cover, closing) should span the full content width (CW), not arbitrary fixed widths.
Problem 16: Donut/Pie Charts Made of Hundreds of Tiny Rect Blocks (v2.0)
Cause: Using nested loops with math.cos/sin + add_rect() to approximate circles/arcs creates 100-2800 shapes per chart. This inflates PPTX file size by 60-80%, causes generation timeouts (2+ minutes), and produces visible gaps and jagged edges.
Solution: Use BLOCK_ARC preset shapes with XML adj parameter control. Each segment = 1 shape:
for deg in range(0, 360, 2):
rad = math.radians(deg)
for r in range(0, int(radius), int(block_sz)):
bx = cx + int(r * math.cos(rad))
add_rect(s, bx, by, block_sz, block_sz, color)
add_block_arc(s, cx - r, cy - r, r * 2, r * 2,
start_deg, end_deg, inner_ratio, color)
See Production Guard Rails Rule 9 for the complete add_block_arc() helper and usage patterns.
Problem 17: Gauge Arc Renders Vertically Instead of Horizontally (v2.0)
Cause: Using math convention angles (0ยฐ=right, 90ยฐ=top, CCW) instead of PPT convention (0ยฐ=top, 90ยฐ=right, CW). A "horizontal rainbow" gauge using math.radians(0) to math.radians(180) renders as a vertical arc in PowerPoint because the coordinate systems are incompatible.
Solution: Use PPT's native clockwise-from-12-o'clock coordinate system directly:
ppt_angle = (90 - math_angle) % 360
ppt_cum = 270
for pct, color in gauge_segs:
sweep = pct * 180
add_block_arc(s, ..., ppt_cum % 360, (ppt_cum + sweep) % 360, ...)
ppt_cum += sweep
Problem 18: Donut Center Text Unreadable Against Colored Ring (v2.0)
Cause: Center labels (e.g., "ยฅ7,013ไบฟ", "ๆป่ฅๆถ") use NAVY or MED_GRAY font color, which is invisible or low-contrast against the colored BLOCK_ARC ring segments behind them.
Solution: Use WHITE for center labels inside donut charts. The colored ring provides enough contrast:
add_text(s, ..., 'ยฅ7,013ไบฟ', font_color=NAVY, ...)
add_text(s, ..., 'ยฅ7,013ไบฟ', font_color=WHITE, bold=True,
font_name='Georgia', ...)
add_text(s, ..., 'ๆป่ฅๆถ', font_color=WHITE, ...)
Problem 19: Chart Elements Overlapping Title Bar โ Body Content Too High (v2.0)
Cause: Chart area chart_top set to Inches(1.0) or Inches(1.2), which places chart elements above the title separator line at Inches(1.05). Applies to waterfall charts, line charts, bar charts, and other data visualization layouts.
Solution: All chart/content body areas must start at or below Inches(1.3):
chart_top = Inches(1.0)
chart_top = Inches(1.3)
Rule: Apply Inches(1.3) as minimum content start for ALL content slides (charts, tables, text blocks). The title bar occupies Inches(0) โ Inches(1.05), and Inches(0.25) gap is mandatory.
Problem 20: Waterfall Chart Connector Lines Look Like Dots (v2.0)
Cause: Connector lines between waterfall bars are drawn using add_hline() with very short length (< 0.1"), making them appear as small dots instead of visible connection lines.
Solution: Ensure connector lines span the full gap between bars, and use consistent thin styling:
connector_x = bx + bar_w
connector_w = gap
connector_y = running_top
add_hline(s, connector_x, connector_y, connector_w, LINE_GRAY, Pt(0.75))
Rule: Waterfall connector lines must have width >= gap_between_bars and use Pt(0.75) line weight for visibility.
Edge Cases
Handling Large Presentations (20+ Slides)
- Break generation into batches of 5-8 slides, saving and verifying after each batch
- Always call
full_cleanup() once at the end, not per-batch
- Memory: python-pptx holds the entire presentation in memory; for 50+ slides, monitor usage
Font Availability
- KaiTi / SimSun may not be installed on non-Chinese systems โ the presentation will render but fall back to a default CJK font
- Georgia is available on Windows/macOS by default; on Linux, install
ttf-mscorefonts-installer
- If target audience uses macOS only, consider using
PingFang SC as ea_font fallback
Slide Dimensions
- All layouts assume 13.333" ร 7.5" (widescreen 16:9). Using 4:3 or custom sizes will break coordinate calculations
- If custom dimensions are required, scale all
Inches() values proportionally
PowerPoint vs LibreOffice
- Generated files are optimized for Microsoft PowerPoint (Windows/macOS)
- LibreOffice Impress may render fonts and spacing slightly differently
full_cleanup() is still recommended for LibreOffice compatibility
Best Practices
- Use MckEngine โ Never write raw
add_shape() / coordinate code. Call eng.xxx() methods.
- One script, all slides โ Generate ALL planned slides in a single script run. Do not truncate.
- Set
total_slides accurately โ This controls page number display (e.g., "Page 5/12").
- Use constants โ Import from
mck_ppt.constants: NAVY, ACCENT_BLUE, BG_GRAY, Inches, etc.
- Layout diversity โ Each content slide MUST use a DIFFERENT layout from its neighbors.
- Chart priority โ When data has dates + values, use chart methods (
eng.grouped_bar, eng.donut, etc.).
- Image priority โ For case studies / product showcases, use image layouts (
eng.content_right_image, etc.).
- TOC completeness โ The TOC slide must list ALL content sections by number and title.
eng.save() is sufficient โ It auto-runs full_cleanup(). No manual XML processing needed.
Code Efficiency with MckEngine
MckEngine already handles constants, helpers, and cleanup internally. Your script only needs:
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
from mck_ppt import MckEngine
from mck_ppt.constants import *
from pptx.util import Inches
eng = MckEngine(total_slides=N)
eng.save('output/deck.pptx')
No need to define add_text(), add_rect(), add_hline(), _clean_shape(), full_cleanup() โ they are all encapsulated in the engine.
Dependencies
- python-pptx >= 0.6.21
- lxml โ XML processing for theme cleanup
- Python 3.8+
pip install python-pptx lxml
Example: Complete Minimal Presentation
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills/mck-ppt-design'))
from mck_ppt import MckEngine
from mck_ppt.constants import *
eng = MckEngine(total_slides=5)
eng.cover(title='็คบไพๆผ็คบ', subtitle='McKinsey Design Framework', date='2026')
eng.toc(items=[('1', 'ๆฐๆฎๆฆ่ง', 'ๆ ธๅฟๆๆ '), ('2', 'ๅๆ', '่ถๅฟๆด่ง')])
eng.big_number(title='ๆ ธๅฟๅ็ฐ', number='42%', description='ๅนดๅข้ฟ็',
source='Source: ๅ
้จๆฐๆฎ')
eng.table_insight(title='ๆ ธๅฟๅ็ฐ',
headers=['็ปดๅบฆ', '็ฐ็ถ', '็ฎๆ '],
rows=[['ๅๆฐ', 'ไบงๅ่ฟญไปฃไธญ', 'AI่ต่ฝ'],
['ๅข้ฟ', 'ๅธๅบๆฉๅผ ไธญ', 'ๅฎขๆทๆทฑ่'],
['ๆ็', 'ๆต็จไผๅไธญ', 'ๅ
จ้ข่ชๅจๅ']],
insights=['ๅๆฐ้ฉฑๅจๅข้ฟ', 'ๆ็ไฟ้ๅฏๆ็ปญ'],
source='Source: ๆ็ฅ้จ')
eng.closing(title='่ฐข่ฐข')
eng.save('output/demo.pptx')
File References
~/.workbuddy/skills/mck-ppt-design/
โโโ SKILL.md # This file (design spec + API reference)
โโโ mck_ppt/
โ โโโ __init__.py # from mck_ppt import MckEngine
โ โโโ engine.py # 67 layout methods
โ โโโ core.py # Drawing primitives + XML cleanup
โ โโโ constants.py # Colors, typography, grid constants
โโโ output/ # Default output directory
Channel Delivery (v1.10)
When users interact via a messaging channel (Feishu/้ฃไนฆ, Telegram, WhatsApp, Discord, Slack, etc.), the generated PPTX file MUST be sent back to the chat โ not just saved to disk.
Why This Matters
Users on mobile or messaging channels cannot access server file paths. Saving a file to ./output/ is invisible to them. The file must be delivered through the same channel the user is talking on.
Delivery Method
After prs.save(outpath) and full_cleanup(outpath), use the OpenClaw media pipeline to send the file:
openclaw message send --media <outpath> --message "โ
PPT generated โ <N> slides, <size> bytes"
Python Helper
import subprocess, shutil
def deliver_to_channel(outpath, slide_count):
"""Send generated PPTX back to user's chat channel via OpenClaw media pipeline.
Falls back gracefully if not running in a channel context."""
if not shutil.which('openclaw'):
print(f'[deliver] openclaw CLI not found, skipping channel delivery')
print(f'[deliver] File saved locally: {outpath}')
return False
size_kb = os.path.getsize(outpath) / 1024
caption = f'โ
PPT generated โ {slide_count} slides, {size_kb:.0f} KB'
try:
result = subprocess.run(
['openclaw', 'message', 'send',
'--media', outpath,
'--message', caption],
capture_output=True, text=True, timeout=30
)
if result.returncode == 0:
print(f'[deliver] Sent to channel: {outpath}')
return True
else:
print(f'[deliver] Channel send failed: {result.stderr}')
print(f'[deliver] File saved locally: {outpath}')
return False
except Exception as e:
print(f'[deliver] Error: {e}')
print(f'[deliver] File saved locally: {outpath}')
return False
Integration with Generation Flow
The complete post-generation sequence is:
prs.save(outpath)
full_cleanup(outpath)
slide_count = len(prs.slides)
deliver_to_channel(outpath, slide_count)
print(f'Created: {outpath} ({os.path.getsize(outpath):,} bytes)')
Rules
- Always attempt delivery โ after every successful generation, call
deliver_to_channel()
- Graceful fallback โ if
openclaw CLI is not available (e.g., running in IDE or CI), skip silently and print the local path
- Caption required โ always include slide count and file size so the user knows what they received
- No duplicate sends โ call
deliver_to_channel() exactly once per generation
- File type โ
.pptx is classified as "document" in OpenClaw's media pipeline (max 100MB), well within limits for any presentation
Channel-Specific Notes
| Channel | File Support | Max Size | Notes |
|---|
| Feishu/้ฃไนฆ | โ
Document | 100MB | Renders as downloadable file card |
| Telegram | โ
Document | 100MB | Shows as file attachment |
| WhatsApp | โ
Document | 100MB | Delivered as document message |
| Discord | โ
Attachment | 100MB | Appears in chat as file |
| Slack | โ
File | 100MB | Shared as file snippet |
| Signal | โ
Attachment | 100MB | Sent as generic attachment |
| Others | โ
Document | 100MB | All OpenClaw channels support document type |
Version History
| Version | Date | Changes |
|---|
| 2.3.0 | 2026-03-27 | Guard Rail Rule 10 โ Horizontal Item Overflow Protection: Fixed process_chevron() negative-gap crash when Nโฅ5 steps (step_wรN > CW โ negative arrow width โ PowerPoint "file needs repair"). Now computes step_w dynamically: min(PREFERRED, (CW - MIN_GAP*(N-1))/N). Adaptive font sizing (sub-headerโbodyโsmall) when boxes shrink. Arrow width floor at 0.2". Documented as Rule 10 in Production Guard Rails with root-cause analysis, validation formula, and affected-methods list. Updated Process Chevron spec: 2โ7 steps supported (was 3โ5). |
| 2.2.0 | 2026-03-22 | AI Cover Image Generation: New mck_ppt/cover_image.py module. eng.cover() gains cover_image parameter (None/'auto'/'path.png'). When 'auto': Tencent Hunyuan 2.0 async API (SubmitHunyuanImageJob) generates 1024ร1024 product photo โ rembg professional background removal โ cool grey-blue tint (desat 30%, Rร0.85/Gร0.92/Bร1.18) + 50% lighten โ subject placed at right-center of 1920ร1080 transparent canvas โ 24 McKinsey-style cubic Bรฉzier ribbon curves with silk-fold twist at center โ full-bleed RGBA PNG embedded as bottom layer. _METAPHOR_MAP maps 24 industry keywords to realistic product descriptions (GPU, capsules, bank card, solar panel, etc.). Prompt enforces: real product photography, sharp edges, white background, studio lighting. __init__.py exports generate_cover_image. Dependencies: tencentcloud-sdk-python, rembg, pillow, numpy. |
| 2.0.5 | 2026-03-21 | #15 Staircase Evolution v3: PNG icon support (auto-detect .png paths, overlay on navy circle with 0.08" inset). Single-line detail_rows = no bullet; multi-line = bullet. Icon library (6 icons in assets/icons/). New example: staircase_civilization.py. Unified release: merged v2.0.4 engine + v2.1 SKILL.md rewrite + #14โ#71 cleanup. |
| 2.0.4 | 2026-03-19 | #14 Three-Pillar RETIRED: Removed three_pillar method from engine.py and its documentation from SKILL.md. All former #14 use cases now served by #71 Table+Insight Panel (table_insight). Updated Layout Diversity table, Opening Slide Priority Rule, and recommended slide structure. |
| 2.0.3 | 2026-03-19 | 3 Template Updates โ Category M: Editorial Narrative: (1) #20 Before/After rewrite (v2.0.1) โ replaced BG_GRAY+NAVY color blocks with clean white-bg + black vertical divider + black circle > arrow + structured data rows (dict: label/brand/val/extra) + formula cards (dict: title/desc/cases with underline), new params: corner_label, bottom_bar, left_summary, right_summary, right_summary_color; (2) #71 Table+Insight Panel (NEW) โ left data table (~60%) + middle CHEVRON shape icon (0.7") + right gray-bg (#F2F2F2) insight panel (~32%) with "ๅฏ็คบ๏ผ" title + โข bullet points, supports **bold** markup in cells, self-adaptive row height; (3) #72 Multi-Bar Panel Chart (NEW) โ 2-3 side-by-side bar panels with auto-numbered titles, CAGR trend arrows following actual bar-top slopes (RIGHT_ARROW shape, ~1.5px shaft, ยฑ0.27" offset), per-bar value labels, green/red CAGR coloring. OPENING SLIDE PRIORITY RULE added: Slides 2-5 strongly prefer #71, #8, #14, #25. New Category M in layout-catalog.md. Total patterns: 72. |
| 2.0.2 | 2026-03-19 | Adaptive Row Height: data_table / vertical_steps dynamically calculate row_h to prevent overflow. Font shrinks to Pt(10) for compact rows. |
| 2.0.1 | 2026-03-19 | Before/After Rewrite: White editorial layout with structured data rows (label/brand/val/extra), formula cards, left/right summaries. Fixed set_ea_font import in core.py. |
| 2.0.0 | 2026-03-19 | BLOCK_ARC Chart Engine: Donut (#48), Pie (#64), and Gauge (#55) charts rewritten from hundreds of add_rect() blocks to native BLOCK_ARC shapes โ 3-4 shapes per chart instead of 100-2800. File size reduced 60-80%. New add_block_arc() helper function with PPT coordinate system documentation. Guard Rail Rule 9: mandatory BLOCK_ARC for all circular charts. 5 new Common Issues (Problems 16-20): rect-block charts, vertical gauge, unreadable donut center text, body content above title bar, waterfall connector dots. Donut center labels changed to WHITE for contrast. Gauge uses correct PPT angle mapping (270ยฐโ0ยฐโ90ยฐ for horizontal rainbow). |
| 1.10.4 | 2026-03-19 | 5 New Bug Fixes + Guard Rail Rule 8: (1) Cover slide title/subtitle overlap โ dynamic title height from line count; (2) Action title anchor changed to MSO_ANCHOR.BOTTOM for flush separator alignment; (3) Checklist #61 dynamic row_h prevents page overflow with 7+ rows; (4) Value Chain #67 dynamic stage_w and stage_h fill content area instead of fixed 2.0" width; (5) Closing #36 bottom line changed from Inches(3) to CW for full-width. New Production Guard Rails Rule 8: dynamic sizing for variable-count layouts. 5 new Common Issues (Problems 11-15). Updated code examples for #1, #36, #61, #67. |
| 1.10.3 | 2026-03-18 | Title Line Spacing Optimization: Titles (โฅ18pt) now use 0.93 multiple spacing instead of fixed Pt(fs*1.35), producing tighter, more professional title rendering. Body text (<18pt) retains fixed Pt spacing. Updated Problem 5 documentation. Thanks to ๅฏๆข่ช Denzel for detailed feedback. |
| 1.10.2 | 2026-03-18 | #54 Matrix Side Panel Variant: Added compact grid + side panel layout variant for Pattern #54 (Risk/Heat Matrix). When matrix needs a companion insight panel, cell_w shrinks from 3.0" to 2.15" and axis_label_w from 1.8" to 0.65", yielding ~4.2" panel width. Includes layout math, ASCII wireframe, code example, and minimum-width rule. |
| 1.10.1 | 2026-03-18 | Frontmatter Fix: Fixed "malformed YAML frontmatter" error on Claude install. Removed unsupported fields (license, version, metadata with emoji, etc.) โ Claude only supports name + description. Used YAML folded block scalar (>-) for description. Metadata relocated to document body. |
| 1.10.0 | 2026-03-18 | Channel Delivery: New deliver_to_channel() helper sends generated PPTX back to user's chat via openclaw message send --media. Supports Feishu/้ฃไนฆ, Telegram, WhatsApp, Discord, Slack, Signal and all OpenClaw channels. Graceful fallback when not in channel context. Updated example scripts. |
| 1.9.0 | 2026-03-15 | Production Guard Rails: 7 mandatory rules derived from real-world feedback โ spacing/overflow protection, legend color consistency, title style uniformity (add_action_title() only), axis label centering, image placeholder page requirement, bottom whitespace elimination, content overflow detection. Code Efficiency Guidelines: variable reuse, helper function patterns, short abbreviation table, batch data structures, auto page numbering. 5 new Common Issues (Problems 6-10). |
| 1.8.0 | 2026-03-15 | Massive layout expansion: 39 โ 70 patterns across 8 โ 12 categories. Added Category I (Image+Content, #40-#47), Category J (Advanced Data Viz, #48-#56), Category K (Dashboards, #57-#58), Category L (Visual Storytelling, #59-#70). New add_image_placeholder() helper. Image Priority Rule added. Layout Diversity table expanded. Based on McKinsey PowerPoint Template 2023 analysis. |
| 1.7.0 | 2026-03-13 | Category H: Data Charts: Added 3 new chart layout patterns (#37 Grouped Bar, #38 Stacked Bar, #39 Horizontal Bar) using pure add_rect() drawing. Added Chart Priority Rule to Layout Diversity table โ when data contains dates + values/percentages, chart patterns are mandatory. Total patterns: 39. |
| 1.6.0 | 2026-03-08 | Cross-model quality alignment: Added Accent Color System (4 accent + 4 light BG colors), Presentation Planning section (structure templates, layout diversity rules, content density requirements, mandatory slide elements, page number helper). Based on comparative analysis across Opus/Minimax/Hunyuan/GLM5 outputs. |
| 1.5.0 | 2026-03-08 | Critical fix: add_text() now sets p.line_spacing = Pt(font_size.pt * 1.35) to prevent Chinese multi-line text overlap. Added Problem 5 to Common Issues. |
| 1.3.0 | 2026-03-04 | ClawHub release: optimized description for discoverability, added metadata/homepage, added Edge Cases & Error Handling sections |
| 1.2.0 | 2026-03-04 | Fixed circle shape number font inconsistency; add_oval() now sets font_name='Arial' + set_ea_font() for consistent typography |
| | - Circle numbers simplified: use 1, 2, 3 instead of 01, 02, 03 |
| | - Removed product-specific references from skill description |
| 1.1.0 | 2026-03-03 | Breaking: Replaced connector-based lines with rectangle-based add_hline() |
| | - add_line() deprecated, use add_hline() instead |
| | - add_circle_label() renamed to add_oval() with bg/fg params |
| | - add_rect() now auto-removes p:style via _clean_shape() |
| | - cleanup_theme() upgraded to full_cleanup() (sanitizes all slide XML) |
| | - Three-layer defense against file corruption |
| | - add_text() bullet param removed; use '\u2022 ' prefix in text |
| 1.0.0 | 2026-03-02 | Initial complete specification, all refinements documented |
| | - Color palette finalized (NAVY primary) |
| | - Typography hierarchy locked (22pt title, 14pt body) |
| | - Line treatment standardized (no shadows) |
| | - Theme cleanup process documented |
| | - All helper functions optimized |