🎁 Why generate documents programmatically
The client doesn't open a .md. It opens a .docx, a .pptx, a spreadsheet .xlsx or one .pdf. Generating with code means formatted, repeatable output with your branding—that’s exactly what makes the package feel like elite consulting, not a chat draft.
The foundation is simple: a virtual environment with the four libraries installed. Claude Code sets it up for you once—then all you have to do is generate.
// setup: venv + the 4 libraries
python3 -m venv venv source venv/bin/activate pip install python-docx reportlab openpyxl python-pptx
✗ Raw Markdown
- ✗Client sees chat text, not a deliverable
- ✗No branding, no formatted table, no formula
- ✗Doesn’t open directly in Word/PowerPoint/Excel
✓ Generated document
- ✓Formatted with your visual identity
- ✓Repeatable: same code, new client
- ✓Opens right away—it feels like an elite consulting firm
💡 Practical tip
You don’t type this code by hand. Ask Claude Code “create the venv and install the 4 document libraries” — it runs everything, resolves system Python conflicts, and gets you ready to generate. Your job is to direct the output format, not memorize the API.
brand + style
1 codebase, N clients
docx/pptx/xlsx/pdf
what the client opens
📘 python-docx — Word reports
This is the report library. You create a Document(), stacks headings (level 0 = title, 1-9 = sections), paragraphs, tables, and runs formatted (bold, color). At the end, doc.save(). It’s what generates the Factory’s final Report and SOW.
// python-docx: title, section, table, and formatted run
from docx import Document
from docx.shared import Pt, RGBColor
doc = Document()
doc.add_heading('Relatório de Estratégia de IA', level=0)
doc.add_heading('Sumário Executivo', level=1)
doc.add_paragraph('Texto do relatório aqui.')
table = doc.add_table(rows=4, cols=3)
table.style = 'Table Grid'
p = doc.add_paragraph()
run = p.add_run('Destaque')
run.bold = True
run.font.color.rgb = RGBColor(0x00, 0x00, 0xFF)
doc.save('relatorio.docx')
Notice three things: the level controls the hierarchy, table.style = 'Table Grid' sets the boundaries, and the run is the smallest unit where you apply bold and color. That same structure becomes the final Report and the proposal document (SOW).
💡 Note
Ready-made styles save work: 'List Bullet' e 'List Number' for lists, 'Heading 1' / 'Heading 2' for sections. You describe the report structure; Claude Code chooses the styles.
creates the doc
level 0–9
Table Grid
Report + SOW
📙 python-pptx — presentations (RGBColor, layouts)
The presentation library. You create a Presentation(), adds slides by choosing a layout (0 = Title, 6 = Blank, the most flexible), and draws text boxes with bullets and colors via RGBColor. It’s what generates the executive deck—the material that closes the sale in Track 5.
// python-pptx: blank slide with centered title
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor # NÃO RgbColor
from pptx.enum.text import PP_ALIGN
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6]) # branco
box = slide.shapes.add_textbox(Inches(0.5), Inches(2), Inches(9), Inches(1.5))
p = box.text_frame.paragraphs[0]
p.text = "Estratégia de IA"
p.font.size = Pt(44)
p.font.bold = True
p.font.color.rgb = RGBColor(31, 78, 121) # azul escuro
p.alignment = PP_ALIGN.CENTER
prs.save('deck.pptx')
The layout 6 (Blank) is the most commonly used because it gives you full control: you position each box in inches. The first paragraph already exists in paragraphs[0]; for the following bullets, use add_paragraph().
💡 The gotcha that trips everyone up
É RGBColor (uppercase RGB), not RgbColor. Getting this capitalization wrong causes an ImportError that seems mysterious. Color is specified with RGB integers: RGBColor(31, 78, 121) = professional dark blue.
creates the deck
white, flexible
not RgbColor
executive deck
📊 openpyxl — Excel with a color convention
The spreadsheet library—and this is where the ROI calculator lives. Three golden rules: indexing 1-based (A1 = row 1, column 1), formulas instead of fixed values, and the color convention financial. Anyone who delivers Excel without formulas delivers a screenshot, not a model.
// openpyxl: formula + input/formula colors
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
wb = Workbook(); ws = wb.active
ws.title = "ROI"
ws['A1'] = 'Premissa' # 1-based: A1
ws['B5'] = '=SUM(B1:B4)' # fórmula, nunca valor fixo
input_font = Font(color='0000FF') # azul = input do usuário
formula_font = Font(color='000000') # preto = fórmula
ws['B1'].font = input_font
ws['B5'].font = formula_font
wb.save('roi.xlsx')
The color convention below is standard in financial modeling—any analyst who opens the spreadsheet will immediately understand what’s an input, what’s a calculation, and what comes from outside. Always apply it in the ROI calculator:
🎨 Color convention (required)
- Blue
0000FF— user inputs (adjustable assumptions) - Black
000000— formulas and calculations - Green
008000— links between tabs (other worksheets) - Red
FF0000— references to external files - Yellow (background)
FFFF00— key assumptions highlighted
💡 Practical tip
Never calculate in Python and paste in the number. Put assumptions in their own cells (blue) and reference them with formulas (black). That way, the client can change an assumption and the entire spreadsheet recalculates—that’s what separates a model from a dead report.
creates the spreadsheet
A1 = (1,1)
never a fixed value
ROI calculator
📕 reportlab — PDF (Platypus)
The PDF library. The recommended method is Platypus: you build a story (list of elements—paragraphs, spacers, tables) and calls doc.build(story) at the end. The PDF only exists after the build.
// reportlab: assembles the story and builds at the end
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.units import inch
doc = SimpleDocTemplate('saida.pdf', pagesize=letter)
styles = getSampleStyleSheet()
story = []
story.append(Paragraph('Estratégia de IA', styles['Heading1']))
story.append(Spacer(1, 0.5 * inch))
story.append(Paragraph('Corpo do documento.', styles['Normal']))
doc.build(story) # constrói no fim
💡 Practical tip
O build comes in the END. Everything you want in the PDF needs to be in the story before of calling doc.build(). Forgot to append something? It won’t show up in the file.
Notice that the pattern is always the same across the four libs—and you can diagram the skill flow gerar-entregavel as four linear steps:
Input Markdown
The skill receives the deliverable in Markdown and the desired target format.
Choose the format
docx / pptx / xlsx / pdf → selects the right library.
Build the elements
Headings, tables, formulas, colors—according to each format's conventions.
Save the file
.save() in all three; .build(story) in the PDF. It goes in the client’s folder.
element story
move it into the story
at the end, always
Client PDF
📦 Package as a Skill gerar-entregavel
You don’t want to remember four APIs every time. Wrap the four libraries in a single skill: "given a Markdown file, generate the .docx/.pptx/.xlsx/.pdf". The skill provides the knowledge; you just specify the format. It's the Factory's output engine.
// SKILL.md — gerar-entregavel
--- name: gerar-entregavel description: Use para transformar um entregável em Markdown num arquivo final — .docx, .pptx, .xlsx ou .pdf — usando python-docx, python-pptx, openpyxl ou reportlab. --- # Gerar Entregável ## Passos 1. Ler o Markdown e o formato-alvo. 2. Escolher a biblioteca (docx / pptx / xlsx / pdf). 3. Montar o documento (headings, tabelas, cores). 4. Salvar na pasta de saída do cliente.
A description well-written is what makes Claude Code trigger the skill at the right time. The steps are the playbook it follows. From now on, “turn this diagnosis into a PowerPoint” is a command—not a project.
✓ Good docs skill
- ✓Choose the right format for the deliverable
- ✓Uses formulas in Excel, with a color-coding convention
- ✓Import
RGBColorcorrect in the pptx
✗ Common mistakes
- ✗Deliver raw Markdown without generating a file
- ✗Fixed values in Excel instead of formulas
- ✗Write
RgbColorand breaks the import
4 libraries
triggers right away
fixed script
output engine
✅ Module summary
🎯 Mission 3.3 — Markdown becomes a package
Turn a single Markdown file into two client files:
- Get 1 deliverable in Markdown (e.g., a mini-diagnosis from 3.2).
- Generate 1
.docxwith python-docx. - Generate 1
.pptxwith python-pptx (watch out: RGBColor). - Wrap it in the gerar-entregavel skill.
Success: 1 .docx + 1 .pptx generated from the same Markdown. What you gained: the Factory's output engine—any prompt becomes a client file.
Next module:
3.4 — Build your subagent (researcher & writer)