dsh-office-kit 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/skills/excel-live-control/SKILL.md +119 -152
- package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
- package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
- package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
- package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
- package/assets/skills/excel-live-control/references/office-automation.md +127 -153
- package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
- package/assets/skills/excel-live-control/style_guidelines.md +56 -64
- package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
- package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
- package/assets/skills/office-documents/SKILL.md +24 -60
- package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
- package/assets/skills/office-documents/ooxml/comments.md +8 -8
- package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
- package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
- package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
- package/assets/skills/office-documents/references/docx-structure.md +11 -13
- package/assets/skills/office-documents/references/template-elicitation.md +11 -13
- package/assets/skills/office-documents/references/writing-quality.md +20 -20
- package/assets/skills/office-documents/scripts/add_tracked_replacements.py +4 -3
- package/assets/skills/office-documents/scripts/docx_kit.py +68 -27
- package/assets/skills/office-documents/scripts/heading_audit.py +3 -4
- package/assets/skills/office-documents/scripts/internal_nav.py +3 -1
- package/assets/skills/office-documents/scripts/merge_docx_append.py +104 -0
- package/assets/skills/office-documents/scripts/table_geometry.py +13 -3
- package/assets/skills/office-documents/scripts/watermark_add.py +6 -5
- package/assets/skills/office-documents/scripts/watermark_audit_remove.py +6 -4
- package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
- package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
- package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
- package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
- package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
- package/assets/skills/office-documents/tasks/create_edit.md +14 -16
- package/assets/skills/office-documents/tasks/equations.md +17 -28
- package/assets/skills/office-documents/tasks/fields_update.md +14 -16
- package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
- package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
- package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
- package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
- package/assets/skills/office-documents/tasks/images_figures.md +15 -25
- package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
- package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
- package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
- package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
- package/assets/skills/office-documents/tasks/read_review.md +9 -20
- package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
- package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
- package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
- package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
- package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
- package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
- package/assets/skills/office-documents/tasks/verify_render.md +11 -23
- package/assets/skills/office-documents/tasks/watermarks_background.md +10 -14
- package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
- package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
- package/assets/skills/office-pdf/SKILL.md +36 -51
- package/assets/skills/office-pdf/references/form-fields.md +20 -20
- package/assets/skills/office-pdf/references/geometry.md +10 -10
- package/assets/skills/office-pdf/references/layout-quality.md +13 -13
- package/assets/skills/office-pdf/references/limits.md +12 -56
- package/assets/skills/office-pdf/tasks/annotations.md +5 -5
- package/assets/skills/office-pdf/tasks/create.md +6 -9
- package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
- package/assets/skills/office-pdf/tasks/forms.md +15 -15
- package/assets/skills/office-pdf/tasks/read.md +9 -9
- package/assets/skills/office-pdf/tasks/redact.md +18 -18
- package/assets/skills/office-pdf/tasks/stamp.md +10 -10
- package/assets/skills/office-presentations/SKILL.md +71 -91
- package/assets/skills/office-presentations/container_tools/preview_render.py +4 -1
- package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
- package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
- package/assets/skills/office-presentations/recipes/README.md +24 -35
- package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
- package/assets/skills/office-presentations/recipes/connectors.md +11 -12
- package/assets/skills/office-presentations/recipes/images.md +11 -12
- package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
- package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
- package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
- package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
- package/assets/skills/office-presentations/recipes/tables.md +14 -14
- package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
- package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
- package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
- package/assets/skills/office-presentations/references/finalization.md +10 -12
- package/assets/skills/office-presentations/references/native-bullets.md +14 -18
- package/assets/skills/office-presentations/references/native-evidence.md +18 -32
- package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
- package/assets/skills/office-presentations/references/templates.md +31 -60
- package/assets/skills/office-presentations/routing/google_slides.md +4 -4
- package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
- package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
- package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
- package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
- package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
- package/assets/skills/office-presentations/tasks/template-following.md +23 -28
- package/assets/skills/office-spreadsheets/SKILL.md +32 -39
- package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
- package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
- package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
- package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
- package/assets/skills/office-spreadsheets/references/charts.md +15 -34
- package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
- package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
- package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
- package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
- package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
- package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
- package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
- package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
- package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
- package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
- package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
- package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
- package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
- package/assets/skills/shared/annotation-recipes.md +98 -120
- package/assets/skills/shared/common-workflow.md +70 -80
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/python/office_cli.py +38 -4
|
@@ -1,36 +1,21 @@
|
|
|
1
1
|
# Google Sheets
|
|
2
2
|
|
|
3
|
-
This runtime works on local files with openpyxl. There are no Google credentials,
|
|
4
|
-
no Drive API, and no live link to a browser sheet, so "update my Google Sheet"
|
|
5
|
-
cannot be done directly.
|
|
3
|
+
This runtime works on local files with openpyxl. There are no Google credentials, no Drive API, and no live link to a browser sheet, so "update my Google Sheet" cannot be done directly.
|
|
6
4
|
|
|
7
5
|
## What to do instead
|
|
8
6
|
|
|
9
|
-
1. Say plainly what is possible: the work is done on a local `.xlsx` file the user
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for `.xlsx` unless the sheet is truly one flat table.
|
|
14
|
-
3. Do the work on the exported file with this skill, then hand back the `.xlsx`.
|
|
15
|
-
The user re-uploads or imports it. State that formulas recalculate when Sheets
|
|
16
|
-
opens the file.
|
|
17
|
-
4. Do not promise a round trip that keeps Sheets-specific features. Named
|
|
18
|
-
functions, Apps Script, and connected sheets do not survive export.
|
|
7
|
+
1. Say plainly what is possible: the work is done on a local `.xlsx` file the user opens in Sheets, or the user exports the sheet and shares the file.
|
|
8
|
+
2. Ask for an export when the source lives in Sheets: `File > Download > Microsoft Excel (.xlsx)`. A single-sheet CSV loses formulas and formats, so ask for `.xlsx` unless the sheet is truly one flat table.
|
|
9
|
+
3. Do the work on the exported file with this skill, then hand back the `.xlsx`. The user re-uploads or imports it. State that formulas recalculate when Sheets opens the file.
|
|
10
|
+
4. Do not promise a round trip that keeps Sheets-specific features. Named functions, Apps Script, and connected sheets do not survive export.
|
|
19
11
|
|
|
20
|
-
##
|
|
12
|
+
## Formulas for a file that goes back to Sheets
|
|
21
13
|
|
|
22
|
-
- Keep to functions both engines share: `SUMIFS`, `INDEX/MATCH`, `XLOOKUP`,
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
- Array formulas and dynamic spills behave differently in the two engines. Avoid
|
|
27
|
-
them in shared files.
|
|
28
|
-
- Number formats, conditional-formatting rules, and charts mostly survive an
|
|
29
|
-
export; images and pivot tables often do not. Check them after the round trip
|
|
30
|
-
with `container_tools/inspect_workbook.py`.
|
|
14
|
+
- Keep to functions both engines share: `SUMIFS`, `INDEX/MATCH`, `XLOOKUP`, `IFERROR`, `EDATE`, `TEXT`.
|
|
15
|
+
- Newer functions that Excel stores with an `_xlfn.` prefix are a common source of `#NAME?` after a round trip. If a function is genuinely new, say so.
|
|
16
|
+
- Array formulas and dynamic spills behave differently in the two engines. Avoid them in shared files.
|
|
17
|
+
- Number formats, conditional-formatting rules, and charts mostly survive an export; images and pivot tables often do not. Check them after the round trip with `container_tools/inspect_workbook.py`.
|
|
31
18
|
|
|
32
19
|
## Links
|
|
33
20
|
|
|
34
|
-
A sheet shared by URL is not a workbook on this machine. Do not fetch a Google
|
|
35
|
-
Sheets URL and pretend it is a file: without a published CSV or an export, there
|
|
36
|
-
is nothing to read.
|
|
21
|
+
A sheet shared by URL is not a workbook on this machine. Do not fetch a Google Sheets URL and pretend it is a file: without a published CSV or an export, there is nothing to read.
|
|
@@ -1,37 +1,22 @@
|
|
|
1
1
|
# Answer questions about an existing workbook
|
|
2
2
|
|
|
3
|
-
This is a read-only job. Do not "improve" the file, do not recalculate it in
|
|
4
|
-
place, and do not save a copy unless the user asked for one.
|
|
3
|
+
This is a read-only job. Do not "improve" the file, do not recalculate it in place, and do not save a copy unless the user asked for one.
|
|
5
4
|
|
|
6
5
|
## Procedure
|
|
7
6
|
|
|
8
|
-
1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` —
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
file was last written by a script), say so and quote the formula instead of a
|
|
13
|
-
number, or recalculate into a copy first (`tasks/recalc-and-check.md`).
|
|
14
|
-
3. `container_tools/inspect_workbook.py --input "<book.xlsx>" --sample 8` when the
|
|
15
|
-
question touches structure: which cells are formulas, merged ranges, totals
|
|
16
|
-
rows, conditional formats, defined names, hidden rows, extra sheets.
|
|
17
|
-
4. Answer with the cells you used: "`Pipeline!B4:B13`, the Amount column, sums to
|
|
18
|
-
`812,000`" beats "the pipeline is about 800k". Name the sheet, the range, and
|
|
19
|
-
the figure.
|
|
7
|
+
1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` — sheet names, used ranges, and cell contents.
|
|
8
|
+
2. Read **values**, not formulas, when the question is about numbers: `xlsx read --data-only` returns cached results. If the cache is empty (the file was last written by a script), say so and quote the formula instead of a number, or recalculate into a copy first (`tasks/recalc-and-check.md`).
|
|
9
|
+
3. `container_tools/inspect_workbook.py --input "<book.xlsx>" --sample 8` when the question touches structure: which cells are formulas, merged ranges, totals rows, conditional formats, defined names, hidden rows, extra sheets.
|
|
10
|
+
4. Answer with the cells you used: "`Pipeline!B4:B13`, the Amount column, sums to `812,000`" beats "the pipeline is about 800k". Name the sheet, the range, and the figure.
|
|
20
11
|
|
|
21
12
|
## Judgement calls
|
|
22
13
|
|
|
23
|
-
- A number that disagrees with the user's expectation is usually a real answer,
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
- Two tabs with the same title and different numbers: report both and ask which
|
|
28
|
-
one the user means before averaging or picking.
|
|
29
|
-
- Empty cells are not zeros. "Not reported" and "zero" are different answers, and
|
|
30
|
-
a missing month in a total usually means a filter, not a zero.
|
|
14
|
+
- A number that disagrees with the user's expectation is usually a real answer, not an error to fix. Explain the calculation and stop.
|
|
15
|
+
- Pre-existing `#REF!`/`#DIV/0!` cells are part of the answer. Point at them, say what breaks, and wait for instructions.
|
|
16
|
+
- Two tabs with the same title and different numbers: report both and ask which one the user means before averaging or picking.
|
|
17
|
+
- Empty cells are not zeros. "Not reported" and "zero" are different answers, and a missing month in a total usually means a filter, not a zero.
|
|
31
18
|
- If the workbook has a case selector, check it. The answer depends on it.
|
|
32
19
|
|
|
33
20
|
## Output shape
|
|
34
21
|
|
|
35
|
-
Short answer first (one line with the figure), then the cells behind it, then any
|
|
36
|
-
caveat about missing data or stale cache. No file changes, no new workbook, no
|
|
37
|
-
chart unless asked.
|
|
22
|
+
Short answer first (one line with the figure), then the cells behind it, then any caveat about missing data or stale cache. No file changes, no new workbook, no chart unless asked.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Resolve an `office-annotations` region to cells
|
|
2
2
|
|
|
3
|
-
The user drags a box on the rendered workbook and types a requirement. The
|
|
4
|
-
payload for spreadsheets is:
|
|
3
|
+
The user drags a box on the rendered workbook and types a requirement. The payload for spreadsheets is:
|
|
5
4
|
|
|
6
5
|
```json
|
|
7
6
|
{
|
|
@@ -15,37 +14,20 @@ payload for spreadsheets is:
|
|
|
15
14
|
}
|
|
16
15
|
```
|
|
17
16
|
|
|
18
|
-
There is no `page`, no `sheet`, and no `range`: the preview client cannot turn a
|
|
19
|
-
pixel rectangle into a cell address and will not fake one. Read it as "look at
|
|
20
|
-
this area of this sheet and do this", not as a cell reference.
|
|
17
|
+
There is no `page`, no `sheet`, and no `range`: the preview client cannot turn a pixel rectangle into a cell address and will not fake one. Read it as "look at this area of this sheet and do this", not as a cell reference.
|
|
21
18
|
|
|
22
19
|
## Procedure
|
|
23
20
|
|
|
24
|
-
1. `read_image` the attachment named `imageName`. It is the screenshot of the
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
sheets more often than you expect — match on a combination (a row label plus
|
|
30
|
-
two numbers), not on one number.
|
|
31
|
-
3. When the numbers are ambiguous, `container_tools/inspect_workbook.py` adds
|
|
32
|
-
formulas, merges, tables, and names; formats often disambiguate ("the only
|
|
33
|
-
column with a `%` format").
|
|
34
|
-
4. State what you resolved, in the user's terms: "`Pipeline!D2:D13`, the Amount
|
|
35
|
-
column — 12 rows of whole dollars". Ask only if two sheets or two columns
|
|
36
|
-
match equally well.
|
|
37
|
-
5. Apply the smallest change that satisfies `requirement` with the mutation tools
|
|
38
|
-
(`tasks/edit-workbook.md`), re-render, and confirm the region now looks right.
|
|
21
|
+
1. `read_image` the attachment named `imageName`. It is the screenshot of the area the user marked: read the visible headers, row labels, and the numbers around the box.
|
|
22
|
+
2. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"`, then match the visible values to sheets and A1 addresses. Values repeat across sheets more often than you expect — match on a combination (a row label plus two numbers), not on one number.
|
|
23
|
+
3. When the numbers are ambiguous, `container_tools/inspect_workbook.py` adds formulas, merges, tables, and names; formats often disambiguate ("the only column with a `%` format").
|
|
24
|
+
4. State what you resolved, in the user's terms: "`Pipeline!D2:D13`, the Amount column — 12 rows of whole dollars". Ask only if two sheets or two columns match equally well.
|
|
25
|
+
5. Apply the smallest change that satisfies `requirement` with the mutation tools (`tasks/edit-workbook.md`), re-render, and confirm the region now looks right.
|
|
39
26
|
|
|
40
27
|
## What not to do
|
|
41
28
|
|
|
42
|
-
- Do not compute a cell from the rectangle's coordinates. Header width, frozen
|
|
43
|
-
|
|
44
|
-
- Do not
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
surrounding convention and change the cells the requirement names.
|
|
48
|
-
- If the region covers a chart or a picture, the change is to the object, not the
|
|
49
|
-
cells behind it — check `charts`/`images` in the inspect output first.
|
|
50
|
-
- If nothing on the page carries the values in the screenshot, say which image
|
|
51
|
-
you looked at and what you could not locate. Do not guess a sheet.
|
|
29
|
+
- Do not compute a cell from the rectangle's coordinates. Header width, frozen panes, hidden columns, and zoom all move cells under the same pixel.
|
|
30
|
+
- Do not edit the first sheet because it was the default. The visible page may be the fourth sheet.
|
|
31
|
+
- Do not re-style the whole sheet to make the marked area consistent. Match the surrounding convention and change the cells the requirement names.
|
|
32
|
+
- If the region covers a chart or a picture, the change is to the object, not the cells behind it — check `charts`/`images` in the inspect output first.
|
|
33
|
+
- If nothing on the page carries the values in the screenshot, say which image you looked at and what you could not locate. Do not guess a sheet.
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
|
|
41
41
|
## Order of work
|
|
42
42
|
|
|
43
|
-
1. Sketch
|
|
44
|
-
2. Put
|
|
45
|
-
3. Write
|
|
43
|
+
1. Sketch sheets as roles, not tabs: inputs, calculations, outputs, checks. A five-line model belongs on one sheet with labelled blocks.
|
|
44
|
+
2. Put number formats on the cells, not on a copy of the values. `#,##0` for currency-ish amounts, `0.0%` for percentages, `yyyy-mm-dd` for real dates.
|
|
45
|
+
3. Write calculations as visible steps (quantity × rate, opening + movements = closing) and link the output to the build rather than repeating the arithmetic.
|
|
46
46
|
4. Add a chart only when it answers a comparison question the numbers alone answer slowly; see `references/charts.md`.
|
|
47
47
|
5. Render and read the PNG, then recalc if formulas exist.
|
|
48
48
|
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
## Pitfalls
|
|
61
61
|
|
|
62
62
|
- Values written through the CLI keep their type: `1840000` is a number, `"1,840,000"` is text and will not sum. Format numbers, never pre-format them as strings.
|
|
63
|
-
- A chart whose `max_row`
|
|
64
|
-
- `anchor` is where the chart's top-left corner sits; a chart outside the print area gets cut off by `xlsx render`. Put it below or beside the data inside the printed range.
|
|
63
|
+
- A chart whose `max_row` exceeds the data plots empty points as zero, which reads as a collapse to the floor. Match the range to the data.
|
|
64
|
+
- `anchor` is where the chart's top-left corner sits; a chart outside the print area gets cut off by `xlsx render`. Put it below or beside the data, inside the printed range.
|
|
65
65
|
- Dates must be real dates (`date(2026, 1, 31)` via a snippet, or Excel serial numbers), never `"Jan-26"` strings, or period filters fail silently.
|
|
66
66
|
- Set the font family explicitly if the file will be opened on another machine; a missing Calibri falls back to a serif in some renderers and every column width shifts.
|
|
@@ -25,8 +25,8 @@ Exit code `0` means the files match at the requested level, `1` means difference
|
|
|
25
25
|
|
|
26
26
|
Run it as `--before original --after original-edited` immediately after any edit, and read the "changed" sections as the diff you are about to describe to the user:
|
|
27
27
|
|
|
28
|
-
1.
|
|
29
|
-
2. A sheet, table, name, or chart
|
|
28
|
+
1. Cells you did not intend to touch are collateral damage — revert and redo with a narrower edit.
|
|
29
|
+
2. A sheet, table, name, or chart under "removed" is a lost object; rebuild it from `recipes/charts.md` / `recipes/named-ranges.md` before presenting.
|
|
30
30
|
3. Formatting-only differences across many rows usually mean a style object was reapplied to a range instead of a cell.
|
|
31
31
|
|
|
32
32
|
Diffing a file against itself is a useful sanity check that the tool and the file load cleanly: it should return `identical: true`.
|
|
@@ -5,7 +5,7 @@ The file is the specification. Read its conventions before writing a cell, then
|
|
|
5
5
|
## Procedure
|
|
6
6
|
|
|
7
7
|
1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` — every sheet, its used range, and its formulas.
|
|
8
|
-
2. `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — what the read verb
|
|
8
|
+
2. `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — what the read verb hides: merged ranges, conditional formatting, defined names, Excel Tables, charts and their series, freeze panes, protections. It prints JSON; `--no-values` skips the second load that looks for cached results.
|
|
9
9
|
3. Render the sheets you are about to touch and look at them: `xlsx render`, then `read_image`. Match the surrounding format, not your personal default.
|
|
10
10
|
4. Apply the edit with the narrowest tool that fits (below), or with an openpyxl snippet when the change is not one of those shapes.
|
|
11
11
|
5. Read back and re-check structure, recalculate if formulas changed, render again, compare.
|
|
@@ -24,11 +24,11 @@ There is no `xlsx edit` verb. Each tool loads the workbook, changes only what yo
|
|
|
24
24
|
| Add a native chart | `add_chart.py --input "<book.xlsx>" --sheet Trend --type line --title "Monthly revenue (USD)" --anchor A6 --data-min-col 2 --data-min-row 3 --data-max-col 13 --data-max-row 3 --cat-min-row 2 --cat-max-row 2` |
|
|
25
25
|
| Embed an image | `add_image.py --input "<book.xlsx>" --sheet Cover --path logo.png --anchor B2 --width 320` |
|
|
26
26
|
|
|
27
|
-
Each tool writes `<input>-edited.xlsx` unless you pass `--out`, so chain by naming outputs
|
|
27
|
+
Each tool writes `<input>-edited.xlsx` unless you pass `--out`, so chain by naming outputs — never edit the file you just read and lose the step in between.
|
|
28
28
|
|
|
29
29
|
`cells.json` is `{"sheet": "Model", "cells": {"B3": 0.07, "D9": "=SUM(D2:D8)"}}` or a list of those. `styles.json` is `{"sheet": "Model", "styles": {"A11:B11": {"bold": true}, "C11:C14": {"number_format": "0.0%"}}}`.
|
|
30
30
|
|
|
31
|
-
Two tool limits are deliberate: `append_rows.py` does not extend an Excel Table, copy the formula from the row above, or grow a chart —
|
|
31
|
+
Two tool limits are deliberate: `append_rows.py` does not extend an Excel Table, copy the formula from the row above, or grow a chart — use a snippet from `recipes/data-tables.md` and `recipes/charts.md`, or the new rows sit outside the table and the chart stops at the old last row. `add_chart.py` treats a one-row data range as one series of many points (what a monthly row means) but cannot set axis number formats or series colours; fix those in the same snippet.
|
|
32
32
|
|
|
33
33
|
## What must survive an edit
|
|
34
34
|
|
|
@@ -48,7 +48,7 @@ New conditional formatting that covers a whole table must extend to the rows you
|
|
|
48
48
|
## Cells: the smallest change
|
|
49
49
|
|
|
50
50
|
- Write to the sheet and address you resolved; never "the first empty row" of an unnamed sheet.
|
|
51
|
-
- A text edit changes run-level text only
|
|
51
|
+
- A text edit changes run-level text only; the cell format stays unless the request names it.
|
|
52
52
|
- A number-format change is a format change, not a value change: do not replace `0.0649` with `6.5%` text.
|
|
53
53
|
- Do not autofit every column or restyle a table to fix one clipped cell. Widen the column, or shrink the font only for that block.
|
|
54
54
|
- Do not add spacer rows, helper sheets, or "Notes" tabs unless the request needs them.
|
|
@@ -66,4 +66,4 @@ If `xlsx read` shows `#REF!`, `#DIV/0!`, or a formula pointing at a sheet that n
|
|
|
66
66
|
"<python>" "<cli>" xlsx render --input "<book-edited.xlsx>" --out-dir "<render-dir>"
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
The diff is the closest thing to a guarantee that nothing else moved: it reports changed cells and formulas, changed formatting unless you pass `--no-formats`, and structure changes (sheets, merges, widths, tables, charts, defined names). Exit code `1` means differences — not failure. Use `--sheet` to narrow and `--limit` to cap the per-sheet cell list.
|
|
69
|
+
The diff is the closest thing to a guarantee that nothing else moved: it reports changed cells and formulas, changed formatting unless you pass `--no-formats`, and structure changes (sheets, merges, widths, tables, charts, defined names). Exit code `1` means differences — not failure. Use `--sheet` to narrow and `--limit` to cap the per-sheet cell list. Gate flags and exit codes: `tasks/recalc-and-check.md`.
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Two readers, different jobs:
|
|
4
4
|
|
|
5
|
-
- `"<python>" "<cli>" xlsx read --input "<book.xlsx>" [--data-only]` —
|
|
6
|
-
- `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — the structure around the cells: formats that govern how they read, objects
|
|
5
|
+
- `"<python>" "<cli>" xlsx read --input "<book.xlsx>" [--data-only]` — cell values per sheet, as arrays without coordinates. `--data-only` returns cached results instead of formula text.
|
|
6
|
+
- `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — the structure around the cells: the formats that govern how they read, the objects beside them, and whether the formulas were ever computed.
|
|
7
7
|
|
|
8
|
-
Run both before editing, and after
|
|
8
|
+
Run both before editing, and again after to prove nothing was lost.
|
|
9
9
|
|
|
10
10
|
## What the inspector reports
|
|
11
11
|
|
|
@@ -19,20 +19,20 @@ Run both before editing, and after editing to prove nothing was lost.
|
|
|
19
19
|
| `sheets[].print_area`, `freeze_panes`, `gridlines` | Layout choices a render will honour |
|
|
20
20
|
| `sheets[].merged` | Merged ranges; a value lives in the top-left cell only |
|
|
21
21
|
| `sheets[].tables` | Excel Table names and refs; rows appended below a `ref` land outside the table |
|
|
22
|
-
| `sheets[].charts[].anchor`, `.kind`, `.series` | Where a chart sits and what it plots; `anchor` outside `print_area`
|
|
22
|
+
| `sheets[].charts[].anchor`, `.kind`, `.series` | Where a chart sits and what it plots; an `anchor` outside `print_area` is cut off when printed |
|
|
23
23
|
| `sheets[].conditional_formats[].rules` | `type` (`cellIs`, `colorScale`, `dataBar`, `expression`), `operator`, `formula`, `priority`. A rule whose range stops short of new rows silently stops applying |
|
|
24
24
|
| `sheets[].data_validations` | Dropdowns and constraints an edit must preserve |
|
|
25
25
|
| `sheets[].hidden_rows`, `hidden_columns` | Content the user deliberately folded away |
|
|
26
26
|
| `sheets[].formulas.shared`, `.array`, `.data_tables` | Non-trivial formula storage; re-saving can materialise or drop these |
|
|
27
27
|
| `sheets[].values.cached`, `.missing`, `.errors` | How many formula cells carry a cached result, carry none, or carry an error value |
|
|
28
28
|
|
|
29
|
-
`--no-values` skips the second load that reads cached results (faster on big files, blind to whether formulas
|
|
29
|
+
`--no-values` skips the second load that reads cached results (faster on big files, blind to whether formulas ever computed). `--sample N` sets how many formula samples per sheet are printed (default 5).
|
|
30
30
|
|
|
31
31
|
## How to read it
|
|
32
32
|
|
|
33
33
|
- `values.missing` equal to `formulas.count` means nothing has ever calculated this file. Do not quote any formula result; recalculate first (`tasks/recalc-and-check.md`).
|
|
34
|
-
- `values.errors` non-empty is pre-existing damage (or a
|
|
35
|
-
- `container.pivot_tables > 0` or `has_vba_project: true` means a plain openpyxl rewrite is risky: back up, change the fewest cells possible,
|
|
34
|
+
- `values.errors` non-empty is pre-existing damage (or a deliberate `#N/A` sentinel). Report it; do not fix it unasked.
|
|
35
|
+
- `container.pivot_tables > 0` or `has_vba_project: true` means a plain openpyxl rewrite is risky: back up, change the fewest cells possible, re-inspect after saving.
|
|
36
36
|
- `formulas.shared > 0` means a spreadsheet app wrote the file; copy an existing formula down rather than inventing a new pattern.
|
|
37
|
-
- A
|
|
38
|
-
- `print_area` and chart `anchor`
|
|
37
|
+
- A huge `dimensions` with few real cells is a formatting artefact (fill applied to whole columns). Do not "clean" it; note it if the user asks why the file is slow.
|
|
38
|
+
- `print_area` and chart `anchor` explain most render surprises: charts clipped at the page edge, or whole data blocks missing from a PDF because they fall outside the print range.
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
# Recalculate and gate consistency
|
|
2
2
|
|
|
3
|
-
A workbook written by openpyxl or by a script has formula text and no cached
|
|
4
|
-
results. Open it in a viewer that does not calculate and every formula cell shows
|
|
5
|
-
blank. `xlsx recalc` runs the real engine to fill the cache; the gate then proves
|
|
6
|
-
every formula cell got a value and none of them is an error.
|
|
3
|
+
A workbook written by openpyxl or by a script has formula text and no cached results. Open it in a viewer that does not calculate and every formula cell shows blank. `xlsx recalc` runs the real engine to fill the cache; the gate then proves every formula cell got a value and none is an error.
|
|
7
4
|
|
|
8
5
|
```bash
|
|
9
6
|
"<python>" "<cli>" xlsx recalc --input "<book.xlsx>" --out "<book-recalculated.xlsx>"
|
|
10
7
|
"<python>" "<skill>/container_tools/recalc_gate.py" --input "<book-recalculated.xlsx>"
|
|
11
8
|
```
|
|
12
9
|
|
|
13
|
-
- `recalc` needs the DSH LibreOffice kit (the same renderer used for images)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- `recalc_gate.py` runs `recalc` for you when given `--cli`: it takes
|
|
17
|
-
`--input`, writes `<stem>-recalculated.xlsx` unless `--out` is given, then
|
|
18
|
-
scans every formula cell.
|
|
19
|
-
- It exits `0` clean, `1` with failures, `2` on a usage or file error, and `3`
|
|
20
|
-
when recalculation was requested but no engine exists. Exit `3` with
|
|
21
|
-
`verdict: unverified` is an honest result — report it as "structure verified,
|
|
22
|
-
numbers not recalculated", never as "numbers verified".
|
|
10
|
+
- `recalc` needs the DSH LibreOffice kit (the same renderer used for images) and runs on Windows, macOS and Linux. Without the kit the verb fails with a plain message and changes nothing.
|
|
11
|
+
- `recalc_gate.py --cli` runs `recalc` for you: it takes `--input`, writes `<stem>-recalculated.xlsx` unless `--out` is given, then scans every formula cell.
|
|
12
|
+
- It exits `0` clean, `1` with failures, `2` on a usage or file error, and `3` when recalculation was requested but no engine exists. Exit `3` with `verdict: unverified` is an honest result — report it as "structure verified, numbers not recalculated", never as "numbers verified".
|
|
23
13
|
|
|
24
14
|
## What the gate flags
|
|
25
15
|
|
|
@@ -30,28 +20,18 @@ every formula cell got a value and none of them is an error.
|
|
|
30
20
|
| `dangling` | Formula references a sheet that does not exist | Renaming a sheet without updating formulas does this; restore the name or repoint the reference |
|
|
31
21
|
| `ignored` | Cells you passed with `--ignore` | Pre-existing errors the user asked you to leave alone |
|
|
32
22
|
|
|
33
|
-
`--strict` treats missing values as failures instead of notes, which is what you
|
|
34
|
-
want after a successful recalc. `--ignore 'Rates!B7,B9'` keeps a known,
|
|
35
|
-
user-accepted error out of the verdict without hiding the rest.
|
|
23
|
+
`--strict` treats missing values as failures instead of notes, which is what you want after a successful recalc. `--ignore 'Rates!B7,B9'` keeps a known, user-accepted error out of the verdict without hiding the rest.
|
|
36
24
|
|
|
37
25
|
## Consistency checks the gate cannot do
|
|
38
26
|
|
|
39
27
|
Recalculation proves formulas evaluate, not that they are right. Check by hand:
|
|
40
28
|
|
|
41
|
-
- Totals equal the sum of the rows above them, and detail rows add to the
|
|
42
|
-
summary — not just that both computed something.
|
|
29
|
+
- Totals equal the sum of the rows above them, and detail rows add to the summary — not just that both computed something.
|
|
43
30
|
- Percentages are stored as fractions and formatted, not typed as `6.4`.
|
|
44
|
-
- A case selector drives every tab that claims to follow the case. Two tabs
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
formula path still exists. If an override replaced a formula, the workbook can
|
|
48
|
-
no longer update.
|
|
49
|
-
- Every input the user expects to change is in a cell they can find, not inside a
|
|
50
|
-
formula constant.
|
|
31
|
+
- A case selector drives every tab that claims to follow the case. Two tabs showing different cases is the most expensive defect in a model.
|
|
32
|
+
- Hard-coded overrides are visible (a different fill or a comment) and the formula path still exists. If an override replaced a formula, the workbook can no longer update.
|
|
33
|
+
- Every input the user expects to change is in a cell they can find, not inside a formula constant.
|
|
51
34
|
|
|
52
35
|
## When there is no engine
|
|
53
36
|
|
|
54
|
-
Report exactly what happened: the file was created and structurally verified, the
|
|
55
|
-
numbers are formulas, and they will populate the first time the user opens the
|
|
56
|
-
file in Excel, LibreOffice, or Sheets. Offer to render so the user sees the layout
|
|
57
|
-
and labels. Do not invent values to make the preview look complete.
|
|
37
|
+
Report exactly what happened: the file was created and structurally verified, the numbers are formulas, and they will populate the first time the user opens the file in Excel, LibreOffice, or Sheets. Offer to render so the user sees the layout and labels. Do not invent values to make the preview look complete.
|