office-automation 0.3.2

Windows CLI tool that automates PowerPoint and Excel via COM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# oa — Office Automation CLI Reference

Windows-only CLI tool that automates Microsoft Office (PowerPoint + Excel) via COM.

## Quick Start

```bash
# Update a single presentation with new Excel data
oa update report.pptx -e data.xlsx

# Batch process 26 countries from a runfile
oa run batch.toml

# Validate all outputs against Excel
oa check batch.toml

# Inspect a PPTX file (read-only)
oa info report.pptx

# Per-slide shape breakdown
oa info -v report.pptx

# Show all config keys and defaults
oa config

# Kill zombie Office processes
oa clean
```

---

## Commands

### `oa update` — Run the update pipeline

The main command. Processes PPTX files by re-linking OLE objects, populating tables, swapping delta indicators, applying color coding, and updating charts.

```
oa update <FILES...> [OPTIONS]
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `<FILES>` | One or more PPTX files (glob patterns like `*.pptx` supported) |

**Options:**

| Flag | Description |
|------|-------------|
| `-e, --excel <PATH>` | Excel data file. Auto-detected from OLE links if omitted |
| `-p, --pick` | Open native file dialog to select Excel file |
| `--pair <PPT=XLSX>` | Explicit PPTX=XLSX pair (repeatable) |
| `-o, --output <PATH>` | Output file or directory. Default: in-place |
| `--steps <STEP,...>` | Run only these steps (comma-separated) |
| `--skip <STEP,...>` | Skip these steps (mutually exclusive with --steps) |
| `--set <KEY=VALUE>` | Override a config value (repeatable) |
| `--check` | Run validation against Excel after processing |
| `--dry-run` | Show what would happen without saving |
| `-v, --verbose` | Enable debug logging |
| `-q, --quiet` | Suppress all output except errors |

**Pipeline Steps** (executed in this order):

| Step | Requires Excel | Description |
|------|---------------|-------------|
| `links` | Yes | Re-point OLE links to new Excel file |
| `tables` | Yes | Populate PPT tables from Excel ranges |
| `deltas` | Yes | Swap delta indicator arrows based on sign |
| `coloring` | No | Apply sign-based color coding (_ccst shapes) |
| `charts` | Yes | Update chart data links |

**Pre-pipeline ZIP operations** (run before COM, no PowerPoint needed):

| Operation | Description |
|-----------|-------------|
| ZIP pre-relink | Rewrite OLE/chart paths in PPTX XML (0.1s vs 100s via COM) |
| ZIP chart pre-update | Rewrite chart numCache values directly in XML |

**Examples:**

```bash
# Basic: update template with new data
oa update template.pptx -e quarterly_data.xlsx

# Save to output directory (original unchanged)
oa update template.pptx -e data.xlsx -o output/report.pptx

# Only update tables and charts (skip links, deltas, coloring)
oa update report.pptx -e data.xlsx --steps tables,charts

# Skip chart updates (everything else runs)
oa update report.pptx -e data.xlsx --skip charts

# Update multiple files with the same Excel
oa update "reports/*.pptx" -e data.xlsx

# Explicit pairs (different Excel per PPTX)
oa update --pair us_report.pptx=us_data.xlsx --pair mx_report.pptx=mx_data.xlsx

# Override config values
oa update report.pptx -e data.xlsx --set ccst.positive_color=#00FF00

# Dry run: see what would happen without saving
oa update report.pptx -e data.xlsx --dry-run

# Update and validate results
oa update report.pptx -e data.xlsx --check

# Auto-detect Excel from OLE links in the PPTX
oa update report.pptx

# Open file dialog to select Excel
oa update report.pptx --pick
```

---

### `oa run` — Execute a TOML runfile

Batch processing from a TOML configuration file. Processes all jobs sequentially using a single shared COM session (avoids 0x80010001 errors from rapid COM create/destroy).

Prints a rich summary table after all jobs complete showing per-job pass/fail, object counts, timing, and totals.

```
oa run <RUNFILE.toml> [OPTIONS]
```

**Options:**

| Flag | Description |
|------|-------------|
| `--check` | Run validation after each job |
| `--dry-run` | Don't save changes |
| `-v, --verbose` | Debug logging |
| `-q, --quiet` | Errors only |

**TOML Runfile Format:**

```toml
# output/{name}.pptx — {name} is replaced with the job key
default_output = "output/{name}.pptx"

# Optional: limit which pipeline steps run (default: all)
steps = ["links", "tables", "deltas", "coloring", "charts"]

# Optional: config overrides (same keys as --set)
[config]
ccst.positive_prefix = ""
links.set_manual = true

# Jobs: template path → { job_name = excel_path }
[jobs."templates/region1_template.pptx"]
australia = "data/tracking_australia.xlsx"
japan = "data/tracking_japan.xlsx"
indonesia = "data/tracking_indonesia.xlsx"

[jobs."templates/region2_template.pptx"]
germany = "data/tracking_germany.xlsx"
france = "data/tracking_france.xlsx"

# Per-job output override (use inline table)
[jobs."templates/special_template.pptx"]
usa = "data/tracking_usa.xlsx"
canada = { data = "data/tracking_canada.xlsx", output = "special/canada_report.pptx" }
```

**Examples:**

```bash
# Run all jobs in the runfile
oa run batch.toml

# Dry run: see what would happen
oa run batch.toml --dry-run

# Run and validate each output
oa run batch.toml --check

# Quiet mode for CI
oa run batch.toml -q
```

**Example output:**

```
Runfile: batch.toml (26 jobs)

--- Job 1/26: Argentina ---
  ▸ template.pptx
    ← tracking_argentina.xlsx
  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
  • Relink ·······················  411   0.1s
  • Tables ·······················  155   1.2s
  • Deltas ·······················    5   0.4s
  • Coloring ·····················    5   0.1s
  • Charts ·······················  257   0.3s
  ✓ completed · 577 objects · 5.9s

[... 24 more jobs ...]

  ═══════════════════════════════════════
  Job summary

  ✓ Argentina ··················  577 objects   5.9s
  ✓ Australia ··················  577 objects   5.7s
  ✗ Brazil ····················· Excel file not found
  ...

  ✓ all jobs complete · 26/26 files · 15262 objects · 2m 36.1s · avg 5.9s/file
```

---

### `oa check` — Validate PPT against Excel

Cell-by-cell comparison of table values, delta sign verification, and chart data validation. Supports both single PPTX files and batch validation via runfiles.

Exit code 0 = pass, 1 = mismatches found.

```
oa check <FILE> [OPTIONS]
```

**Arguments:**

| Argument | Description |
|----------|-------------|
| `<FILE>` | PPTX file or runfile (`.toml`/`.py`) to validate |

**Options:**

| Flag | Description |
|------|-------------|
| `-e, --excel <PATH>` | Excel to check against (auto-detected if omitted) |
| `--set <KEY=VALUE>` | Override config values (repeatable) |
| `-v, --verbose` | Show per-cell comparison details |

**What it checks:**
- **Tables**: Every cell in every linked table compared to its Excel source
- **Transposed tables**: Handles row/col swap correctly
- **_ccst tables**: Applies the same transform (prefix, symbol removal) before comparing
- **Deltas**: Verifies shape sign suffix (_pos/_neg/_none) matches Excel value
- **Charts**: Link targets, series counts, series values (cached vs Excel)

**Examples:**

```bash
# Check a single file against specific Excel
oa check report.pptx -e data.xlsx

# Auto-detect Excel from OLE links
oa check report.pptx

# Batch check all jobs from a runfile
oa check batch.toml

# Verbose: see every cell comparison
oa check report.pptx -e data.xlsx -v

# Use in CI: exit code 1 on mismatch
oa check report.pptx -e data.xlsx || echo "VALIDATION FAILED"
```

**Example output (single file):**

```
  ▸ report.pptx
    ← data.xlsx
  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  ✓ Tables ·············· 234 checked                    ·     0 mismatches  PASS
  ✓ Deltas ··············   5 checked                    ·     0 mismatches  PASS
  ✓ Charts ·············· 257 checked (546 series)       ·     0 mismatches  PASS

  ✓ check passed · 785 checked · 0 mismatches · 4.3s
```

**Example output (batch via runfile):**

```
  ═══════════════════════════════════════
  Check summary

  ✓ Argentina ··································  785 checked   4.5s
  ✗ Australia ·································· 4 mismatches   4.4s
  ✓ Brazil ·····································  785 checked   4.2s
  ...

  ✗ 1 check failed · 5/6 files · 4740 checked · 27.8s
```

---

### `oa info` — Inspect a PPTX file

Read-only inspection. Shows slide count, OLE links, charts (linked/unlinked), special shapes, and delta templates. With `-v`, adds a per-slide shape breakdown table.

```
oa info <FILE> [-v]
```

**Options:**

| Flag | Description |
|------|-------------|
| `-v, --verbose` | Show per-slide breakdown table |

**Example (normal):**

```bash
oa info template.pptx
```

```
  ▸ template.pptx
  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

  File size ···································· 2.7 MB
  Slides ·······································   68

  OLE links ····································  155
    ╰ tracking_data.xlsx ························  155

  Charts ·······································  258
    ╰ Linked ···································  257
    ╰ Unlinked ·································    1

  Special shapes ·······························  165
    ╰ ntbl_ normal tables ······················  122
    ╰ htmp_ heatmap tables ·····················    0
    ╰ trns_ transposed tables ··················   33
    ╰ delt_ delta indicators ···················    5
    ╰ _ccst color-coded ························    5

  Delta templates
    ╰ tmpl_delta_pos ···························    ✓
    ╰ tmpl_delta_neg ···························    ✓
    ╰ tmpl_delta_none ··························    ✓
```

**Example (verbose — per-slide breakdown):**

```bash
oa info -v template.pptx
```

Appends after the normal output:

```
  Per-slide breakdown
  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
   slide    ole  chart   ntbl   htmp   trns   delt   ccst  total

       1      ·      ·      ·      ·      ·      ·      ·      ·
       2      5      ·      5      ·      ·      5      5     20
       3      ·     19      ·      ·      ·      ·      ·     19
       4      7      ·      5      ·      2      ·      ·     14
       ...
      68      ·     19      ·      ·      ·      ·      ·     19
  ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
  68 slides · 42 active · 26 empty
```

Columns: `slide` (slide number), `ole` (OLE objects), `chart` (linked charts only), `ntbl` (normal tables), `htmp` (heatmap tables), `trns` (transposed tables), `delt` (delta indicators), `ccst` (color-coded shapes), `total` (sum). Zero values shown as `·`. All slides shown including empty ones.

---

### `oa diff` — Compare two PPTX files

Side-by-side comparison of two presentations. Read-only, no Excel needed.

```
oa diff <A.pptx> <B.pptx> [-v]
```

**What it compares:**
- Shape inventory counts (ntbl_, htmp_, trns_, delt_, _ccst); numbered delta sets (`delt2_`, ...) get their own count row and `tmpl<N>_delta_*` template rows when present
- Table cell values for matching shapes
- Chart counts

**Examples:**

```bash
# Compare template vs updated version
oa diff template.pptx updated_report.pptx

# Compare two country reports
oa diff us_report.pptx mx_report.pptx
```

---

### `oa config` — Show config keys and defaults

Prints all available `--set` keys with their default values.

```
oa config
```

**Config Sections:**

| Section | Keys | Description |
|---------|------|-------------|
| `heatmap.*` | 5 keys | Colors for 3-color scale heatmap tables (htmp_) |
| `ccst.*` | 5 keys | Sign-based color coding (_ccst tables) |
| `delta.*` | 4 keys | Delta indicator template shape names and source slide |
| `links.*` | 1 key | OLE link update behavior |

---

### `oa clean` — Kill zombie Office processes

Finds and kills orphaned POWERPNT.EXE and EXCEL.EXE processes left over from crashes. Shows found processes with PIDs, prompts for confirmation before killing.

```
oa clean [-f]
```

**Options:**

| Flag | Description |
|------|-------------|
| `-f, --force` | Kill without prompting for confirmation |

**Examples:**

```bash
# Interactive: lists processes and prompts before killing
oa clean

# Force kill (for scripts)
oa clean -f
```

**Example output:**

```
  Found 2 Office processes

  EXCEL.EXE ························ PID 95448
  POWERPNT.EXE ····················· PID 99640

  Kill all? [y/N] y

  ✓ Killed EXCEL.EXE ················· PID 95448
  ✓ Killed POWERPNT.EXE ·············· PID 99640

  ✓ cleaned · 2 processes killed
```

When no processes found:

```
  Found 0 Office processes

  ✓ No Office processes found
```

---

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Validation failure (`oa check` found mismatches) |
| 2 | Runtime error (bad arguments, missing files, COM failure) |

---

## Special Shape Naming Conventions

The pipeline identifies shapes by name prefix/suffix:

| Prefix/Suffix | Type | Behavior |
|---------------|------|----------|
| `ntbl_` | Normal table | Preserves formatting, only updates cell text |
| `htmp_` | Heatmap table | Recalculates 3-color scale from Excel |
| `trns_` | Transposed table | Swaps rows/columns from Excel range |
| `delt_` | Delta indicator | Arrow shape, swapped based on value sign (set 1; `delt1_` is an alias) |
| `delt<N>_` | Delta indicator, set N | Same behaviour, copies from `tmpl<N>_delta_*` (N ≥ 2, e.g. `delt2_Rev_DE_pos`) |
| `_ccst` | Color-coded table | Cells colored by sign (positive/negative/neutral) |
| `tmpl_delta_pos` | Template | Positive delta arrow template on slide 1 |
| `tmpl_delta_neg` | Template | Negative delta arrow template on slide 1 |
| `tmpl_delta_none` | Template | Neutral delta template on slide 1 |
| `tmpl<N>_delta_pos` / `_neg` / `_none` | Template, set N | Templates for `delt<N>_` shapes, same slide as set 1. A set with any template missing is skipped with a warning, never mapped to set 1. |

**Shape-OLE matching:** Table names like `ntbl_Object 1_ccst` are matched to OLE shapes like `Object 1` using word-boundary token matching (the `ntbl_` prefix and `_ccst` suffix are stripped during matching).

**Delta empty data handling:** When the Excel cell for a delta indicator is empty/missing, the delta shape is set to `_none` (neutral indicator) rather than being skipped.

---

## Performance

| Scenario | Time |
|----------|------|
| Single 68-slide PPTX (155 OLE, 257 charts) | ~6s |
| Batch 26 files via `oa run` | ~2m 36s |
| ZIP pre-relink (411 links) | 0.1s |
| ZIP chart pre-update (257 charts) | 0.3s |
| `oa info` inspection | ~3s |
| `oa check` single file | ~4s |
| `oa check` batch (6 files via runfile) | ~28s |
| `oa clean` (no processes) | instant |

**Key optimization:** COM session reuse across batch jobs saves ~28s on 26 jobs by avoiding rapid COM create/destroy (GOTCHA #39).

**Limitation:** PowerPoint is a single-instance COM server (GOTCHA #40). Multiple threads all share one POWERPNT.EXE process, so multi-threaded parallelism provides no speedup for PowerPoint operations.