Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Create, read, edit, and format Excel (.xlsx) spreadsheets with formulas, color coding, and financial model standards
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/recalc.py
1"""2Excel Formula Recalculation Script3Recalculates all formulas in an Excel file using LibreOffice4"""56import json7import os8import platform9import subprocess10import sys11from pathlib import Path1213from office.soffice import get_soffice_env1415from openpyxl import load_workbook1617MACRO_DIR_MACOS = "~/Library/Application Support/LibreOffice/4/user/basic/Standard"18MACRO_DIR_LINUX = "~/.config/libreoffice/4/user/basic/Standard"19MACRO_FILENAME = "Module1.xba"2021RECALCULATE_MACRO = """<?xml version="1.0" encoding="UTF-8"?>22<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">23<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">24Sub RecalculateAndSave()25ThisComponent.calculateAll()26ThisComponent.store()27ThisComponent.close(True)28End Sub29</script:module>"""303132def has_gtimeout():33try:34subprocess.run(35["gtimeout", "--version"], capture_output=True, timeout=1, check=False36)37return True38except (FileNotFoundError, subprocess.TimeoutExpired):39return False404142def setup_libreoffice_macro():43macro_dir = os.path.expanduser(44MACRO_DIR_MACOS if platform.system() == "Darwin" else MACRO_DIR_LINUX45)46macro_file = os.path.join(macro_dir, MACRO_FILENAME)4748if (49os.path.exists(macro_file)50and "RecalculateAndSave" in Path(macro_file).read_text()51):52return True5354if not os.path.exists(macro_dir):55subprocess.run(56["soffice", "--headless", "--terminate_after_init"],57capture_output=True,58timeout=10,59env=get_soffice_env(),60)61os.makedirs(macro_dir, exist_ok=True)6263try:64Path(macro_file).write_text(RECALCULATE_MACRO)65return True66except Exception:67return False686970def recalc(filename, timeout=30):71if not Path(filename).exists():72return {"error": f"File {filename} does not exist"}7374abs_path = str(Path(filename).absolute())7576if not setup_libreoffice_macro():77return {"error": "Failed to setup LibreOffice macro"}7879cmd = [80"soffice",81"--headless",82"--norestore",83"vnd.sun.star.script:Standard.Module1.RecalculateAndSave?language=Basic&location=application",84abs_path,85]8687if platform.system() == "Linux":88cmd = ["timeout", str(timeout)] + cmd89elif platform.system() == "Darwin" and has_gtimeout():90cmd = ["gtimeout", str(timeout)] + cmd9192result = subprocess.run(cmd, capture_output=True, text=True, env=get_soffice_env())9394if result.returncode != 0 and result.returncode != 124:95error_msg = result.stderr or "Unknown error during recalculation"96if "Module1" in error_msg or "RecalculateAndSave" not in error_msg:97return {"error": "LibreOffice macro not configured properly"}98return {"error": error_msg}99100try:101wb = load_workbook(filename, data_only=True)102103excel_errors = [104"#VALUE!",105"#DIV/0!",106"#REF!",107"#NAME?",108"#NULL!",109"#NUM!",110"#N/A",111]112error_details = {err: [] for err in excel_errors}113total_errors = 0114115for sheet_name in wb.sheetnames:116ws = wb[sheet_name]117for row in ws.iter_rows():118for cell in row:119if cell.value is not None and isinstance(cell.value, str):120for err in excel_errors:121if err in cell.value:122location = f"{sheet_name}!{cell.coordinate}"123error_details[err].append(location)124total_errors += 1125break126127wb.close()128129result = {130"status": "success" if total_errors == 0 else "errors_found",131"total_errors": total_errors,132"error_summary": {},133}134135for err_type, locations in error_details.items():136if locations:137result["error_summary"][err_type] = {138"count": len(locations),139"locations": locations[:20],140}141142wb_formulas = load_workbook(filename, data_only=False)143formula_count = 0144for sheet_name in wb_formulas.sheetnames:145ws = wb_formulas[sheet_name]146for row in ws.iter_rows():147for cell in row:148if (149cell.value150and isinstance(cell.value, str)151and cell.value.startswith("=")152):153formula_count += 1154wb_formulas.close()155156result["total_formulas"] = formula_count157158return result159160except Exception as e:161return {"error": str(e)}162163164def main():165if len(sys.argv) < 2:166print("Usage: python recalc.py <excel_file> [timeout_seconds]")167print("\nRecalculates all formulas in an Excel file using LibreOffice")168print("\nReturns JSON with error details:")169print(" - status: 'success' or 'errors_found'")170print(" - total_errors: Total number of Excel errors found")171print(" - total_formulas: Number of formulas in the file")172print(" - error_summary: Breakdown by error type with locations")173print(" - #VALUE!, #DIV/0!, #REF!, #NAME?, #NULL!, #NUM!, #N/A")174sys.exit(1)175176filename = sys.argv[1]177timeout = int(sys.argv[2]) if len(sys.argv) > 2 else 30178179result = recalc(filename, timeout)180print(json.dumps(result, indent=2))181182183if __name__ == "__main__":184main()185