Apply text replacements from JSON to PowerPoint presentation.
(pptx_file: str, json_file: str, output_file: str)
| 212 | |
| 213 | |
| 214 | def apply_replacements(pptx_file: str, json_file: str, output_file: str): |
| 215 | """Apply text replacements from JSON to PowerPoint presentation.""" |
| 216 | |
| 217 | # Load presentation |
| 218 | prs = Presentation(pptx_file) |
| 219 | |
| 220 | # Get inventory of all text shapes (returns ShapeData objects) |
| 221 | # Pass prs to use same Presentation instance |
| 222 | inventory = extract_text_inventory(Path(pptx_file), prs) |
| 223 | |
| 224 | # Detect text overflow in original presentation |
| 225 | original_overflow = detect_frame_overflow(inventory) |
| 226 | |
| 227 | # Load replacement data with duplicate key detection |
| 228 | with open(json_file, "r") as f: |
| 229 | replacements = json.load(f, object_pairs_hook=check_duplicate_keys) |
| 230 | |
| 231 | # Validate replacements |
| 232 | errors = validate_replacements(inventory, replacements) |
| 233 | if errors: |
| 234 | print("ERROR: Invalid shapes in replacement JSON:") |
| 235 | for error in errors: |
| 236 | print(f" - {error}") |
| 237 | print("\nPlease check the inventory and update your replacement JSON.") |
| 238 | print( |
| 239 | "You can regenerate the inventory with: python inventory.py <input.pptx> <output.json>" |
| 240 | ) |
| 241 | raise ValueError(f"Found {len(errors)} validation error(s)") |
| 242 | |
| 243 | # Track statistics |
| 244 | shapes_processed = 0 |
| 245 | shapes_cleared = 0 |
| 246 | shapes_replaced = 0 |
| 247 | |
| 248 | # Process each slide from inventory |
| 249 | for slide_key, shapes_dict in inventory.items(): |
| 250 | if not slide_key.startswith("slide-"): |
| 251 | continue |
| 252 | |
| 253 | slide_index = int(slide_key.split("-")[1]) |
| 254 | |
| 255 | if slide_index >= len(prs.slides): |
| 256 | print(f"Warning: Slide {slide_index} not found") |
| 257 | continue |
| 258 | |
| 259 | # Process each shape from inventory |
| 260 | for shape_key, shape_data in shapes_dict.items(): |
| 261 | shapes_processed += 1 |
| 262 | |
| 263 | # Get the shape directly from ShapeData |
| 264 | shape = shape_data.shape |
| 265 | if not shape: |
| 266 | print(f"Warning: {shape_key} has no shape reference") |
| 267 | continue |
| 268 | |
| 269 | # ShapeData already validates text_frame in __init__ |
| 270 | text_frame = shape.text_frame # type: ignore |
| 271 |
no test coverage detected