Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Create, read, edit, and manipulate Word (.docx) documents with formatting, tables, and tracked changes
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/accept_changes.py
1"""Accept all tracked changes in a DOCX file using LibreOffice.23Requires LibreOffice (soffice) to be installed.4"""56import argparse7import logging8import shutil9import subprocess10from pathlib import Path1112from office.soffice import get_soffice_env1314logger = logging.getLogger(__name__)1516LIBREOFFICE_PROFILE = "/tmp/libreoffice_docx_profile"17MACRO_DIR = f"{LIBREOFFICE_PROFILE}/user/basic/Standard"1819ACCEPT_CHANGES_MACRO = """<?xml version="1.0" encoding="UTF-8"?>20<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">21<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">22Sub AcceptAllTrackedChanges()23Dim document As Object24Dim dispatcher As Object2526document = ThisComponent.CurrentController.Frame27dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")2829dispatcher.executeDispatch(document, ".uno:AcceptAllTrackedChanges", "", 0, Array())30ThisComponent.store()31ThisComponent.close(True)32End Sub33</script:module>"""343536def accept_changes(37input_file: str,38output_file: str,39) -> tuple[None, str]:40input_path = Path(input_file)41output_path = Path(output_file)4243if not input_path.exists():44return None, f"Error: Input file not found: {input_file}"4546if not input_path.suffix.lower() == ".docx":47return None, f"Error: Input file is not a DOCX file: {input_file}"4849try:50output_path.parent.mkdir(parents=True, exist_ok=True)51shutil.copy2(input_path, output_path)52except Exception as e:53return None, f"Error: Failed to copy input file to output location: {e}"5455if not _setup_libreoffice_macro():56return None, "Error: Failed to setup LibreOffice macro"5758cmd = [59"soffice",60"--headless",61f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}",62"--norestore",63"vnd.sun.star.script:Standard.Module1.AcceptAllTrackedChanges?language=Basic&location=application",64str(output_path.absolute()),65]6667try:68result = subprocess.run(69cmd,70capture_output=True,71text=True,72timeout=30,73check=False,74env=get_soffice_env(),75)76except subprocess.TimeoutExpired:77return (78None,79f"Successfully accepted all tracked changes: {input_file} -> {output_file}",80)8182if result.returncode != 0:83return None, f"Error: LibreOffice failed: {result.stderr}"8485return (86None,87f"Successfully accepted all tracked changes: {input_file} -> {output_file}",88)899091def _setup_libreoffice_macro() -> bool:92macro_dir = Path(MACRO_DIR)93macro_file = macro_dir / "Module1.xba"9495if macro_file.exists() and "AcceptAllTrackedChanges" in macro_file.read_text():96return True9798if not macro_dir.exists():99subprocess.run(100[101"soffice",102"--headless",103f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}",104"--terminate_after_init",105],106capture_output=True,107timeout=10,108check=False,109env=get_soffice_env(),110)111macro_dir.mkdir(parents=True, exist_ok=True)112113try:114macro_file.write_text(ACCEPT_CHANGES_MACRO)115return True116except Exception as e:117logger.warning(f"Failed to setup LibreOffice macro: {e}")118return False119120121if __name__ == "__main__":122parser = argparse.ArgumentParser(123description="Accept all tracked changes in a DOCX file"124)125parser.add_argument("input_file", help="Input DOCX file with tracked changes")126parser.add_argument(127"output_file", help="Output DOCX file (clean, no tracked changes)"128)129args = parser.parse_args()130131_, message = accept_changes(args.input_file, args.output_file)132print(message)133134if "Error" in message:135raise SystemExit(1)136