xlsx — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited xlsx (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You already know openpyxl and pandas. This skill adds what you can't see from the code: a recalculation step that reports what is actually wrong in the workbook, and the behaviours of openpyxl and LibreOffice that silently break files.
<skill> is the directory containing this file. Run bundled scripts by absolute path from the user's working directory, so relative paths to their files keep working:
uv run <skill>/scripts/recalc.py model.xlsxRun Python you write with its dependencies declared, either uv run --with openpyxl script.py or a PEP 723 header. Recalculation needs LibreOffice (soffice).
.xlsm, load with load_workbook(path, keep_vba=True), or the macros are lost on save.Anything derived belongs in the sheet as a formula, so the workbook stays correct when its inputs change. Compute in Python only what has no spreadsheet form, then write it as a labelled input.
ws["B10"] = "=SUM(B2:B9)" # not ws["B10"] = df["Sales"].sum()
ws["C5"] = "=(C4-C2)/C2" # growth, from the cells it depends on
ws["D3"] = "=B3*(1+$B$1)" # assumptions live in their own cellsopenpyxl writes formulas without values, so a file is not finished until it has been recalculated. Run this after every save that touched formulas, and fix what it reports before delivering:
uv run <skill>/scripts/recalc.py model.xlsxIt recalculates in LibreOffice, writes the values back into the file, and prints JSON. The exit status is 0 when clean, 1 when there are problems, and 2 when it could not run.
| Field | Meaning and fix |
|---|---|
errors | Error values by type, e.g. {"#DIV/0!": {"count": 3, "locations": ["Model!C7", …]}}, with at most 50 locations per type. Fix the formulas at those cells. |
missing_prefix | Newer functions written without the prefix the file format requires (see below). The file is left untouched, and each entry carries the corrected formula in fix. |
circular_references | Groups of cells that depend on each other. LibreOffice shows these as #VALUE!, so fix the cycle first. |
uncalculated | Formulas LibreOffice left without a value. Usually a function LibreOffice does not implement; the workbook may still work in Excel, but tell the user. |
Links to other workbooks make it stop, because recalculating would overwrite the linked values. Pass --force only if the user accepts that.
=_xlfn.XLOOKUP(…), =_xlfn.TEXTJOIN(…), =_xlfn.IFS(…), and =_xlfn._xlws.FILTER(…) and =_xlfn._xlws.SORT(…). Without it, Excel and LibreOffice both show #NAME?. recalc catches these before they do damage. LibreOffice older than 24.8 (soffice --version) lacks XLOOKUP, XMATCH, FILTER, SORT, SORTBY, UNIQUE, SEQUENCE and LET, so recalc flags them even when prefixed; the workbook still computes in Excel, so tell the user rather than rewriting the formulas.insert_rows, delete_rows, insert_cols and delete_cols move cells but do not rewrite any formula that refers to them. =SUM(B1:B4) stays =SUM(B1:B4) after a row is inserted above it. Rewrite the affected formulas yourself, or lay out the sheet so nothing needs inserting.@. Prefer formulas that return one value per cell.get_column_letter and column_index_from_string; never count letters by hand past column Z.Use openpyxl's native charts (openpyxl.chart) for charts that belong in the workbook; they stay linked to the cells. Render matplotlib images only when the chart is going somewhere else.
Study the file before changing it, and match its fonts, fills, number formats, column widths and layout exactly. Its conventions override everything below.
Unless the user or the template says otherwise:
0000FF for hard-coded inputs, black for formulas, green 008000 for links to other sheets, red FF0000 for links to other files. A yellow FFFF00 fill marks key assumptions.$#,##0;($#,##0);-, with units in the header, e.g. "Revenue ($mm)".0.0%.0.0x.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.