XLSX guide · OOXML inspection
When a workbook arrives from an upload, an automated export, or a vendor, you often need facts before opening it. These command-line techniques inspect the ZIP-based OOXML package or call the XLSX Inspector API. They are useful on CI runners and headless servers because they do not launch Excel or execute VBA.
PRACTICAL · COMMAND LINE READYA macro-enabled workbook normally has the .xlsm extension and contains a VBA project part named `xl/vbaProject.bin`. An ordinary .xlsx should not contain that part. Checking the package is a fast, low-risk first pass; it tells you whether VBA is present, not whether the VBA is safe.
unzip -l workbook.xlsm | grep -i 'xl/vbaProject.bin'
# API alternative
curl -F 'file=@workbook.xlsx' https://api.lifestep.io/inspect | jq '{has_macros, macro_parts}'Why it works: OOXML files are ZIP containers. The central directory exposes member names without opening the workbook in a spreadsheet application. `vbaProject.bin` is the binary VBA project relationship used by macro-enabled Office files. Keep the extension and package result together: a renamed file can still reveal its contents, while a malformed archive may fail inspection. Never infer that “no macros” means “safe”; external links, formulas, embedded objects, and malformed XML are separate concerns.
List the external-link XML parts and inspect their relationship targets. For a quick answer, the API reports external-link parts; for forensic detail, search the relationships and workbook XML for URLs or workbook paths.
unzip -l workbook.xlsx | grep -Ei 'externalLinks|externalLink' unzip -p workbook.xlsx xl/_rels/workbook.xml.rels | grep -Ei 'Target=|external'
Why it works: Excel stores external workbook references in dedicated `xl/externalLinks/` parts and relationships from the workbook package. The target may be a URL, UNC path, or local path, so search output is evidence rather than a complete dependency graph. Relationship XML is escaped and namespaced, which is why a real XML parser is preferable for production tooling. The inspector’s bounded ZIP parsing gives you a safe summary before you decide whether to process the file further.
Use a small Python script with the standard library to read `xl/workbook.xml` and resolve the spreadsheet namespace. It prints names in workbook order, including hidden sheets.
python3 - <<'PY'
from zipfile import ZipFile
from xml.etree import ElementTree as ET
with ZipFile("workbook.xlsx") as z:
root = ET.fromstring(z.read("xl/workbook.xml"))
ns = {"x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
for sheet in root.findall("x:sheets/x:sheet", ns):
print(sheet.attrib["name"], sheet.attrib.get("state", "visible"))
PYWhy it works: The workbook manifest is the authoritative place for sheet names and visibility state. Worksheet files can be numbered differently from the visible names, so reading `workbook.xml` avoids guessing from filenames. This script does not calculate formulas or load cell data. If the file came from an untrusted source, combine this metadata pass with archive-size limits and XML hardening before processing it in a larger pipeline.
Make the command deterministic before putting it in automation. Pin the input hostname or filename, set a timeout, capture the exit status, and emit a concise error that a build log can explain. Treat an empty answer differently from a transport failure: an empty DNS record, a workbook with no matching package member, and an unavailable endpoint are different states. Test one known-good fixture and one deliberately bad fixture so a future dependency or API change cannot silently turn a failure into a pass. Prefer machine-readable JSON when an API provides it, but retain the original command for local diagnosis. If the result controls a user-facing decision, show the reason and a timestamp rather than only a green or red label. These habits keep a useful one-liner understandable when it becomes a scheduled check.
The habit above — one known-good fixture and one deliberately bad one — is the same rule that decides whether an agent’s own verification means anything. A check exercised only on its passing case is indistinguishable from one that returns a constant, and that is how a green suite ships an inverted result.
Two free collections built from the incidents behind that: adversarial review prompts (assume the diff is broken and prove it) and CLAUDE.md rules that bind (trigger, check, stop, evidence). Both MIT. The full set is the Complete Agent Ops Kit, $29.