dsh-office-kit 0.4.2 → 0.4.3

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.
Files changed (113) hide show
  1. package/assets/skills/excel-live-control/SKILL.md +119 -152
  2. package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
  3. package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
  4. package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
  5. package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
  6. package/assets/skills/excel-live-control/references/office-automation.md +127 -153
  7. package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
  8. package/assets/skills/excel-live-control/style_guidelines.md +56 -64
  9. package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
  10. package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
  11. package/assets/skills/office-documents/SKILL.md +24 -60
  12. package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
  13. package/assets/skills/office-documents/ooxml/comments.md +8 -8
  14. package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
  15. package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
  16. package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
  17. package/assets/skills/office-documents/references/docx-structure.md +11 -13
  18. package/assets/skills/office-documents/references/template-elicitation.md +11 -13
  19. package/assets/skills/office-documents/references/writing-quality.md +20 -20
  20. package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
  21. package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
  22. package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
  23. package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
  24. package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
  25. package/assets/skills/office-documents/tasks/create_edit.md +14 -16
  26. package/assets/skills/office-documents/tasks/equations.md +17 -28
  27. package/assets/skills/office-documents/tasks/fields_update.md +14 -16
  28. package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
  29. package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
  30. package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
  31. package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
  32. package/assets/skills/office-documents/tasks/images_figures.md +15 -25
  33. package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
  34. package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
  35. package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
  36. package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
  37. package/assets/skills/office-documents/tasks/read_review.md +9 -20
  38. package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
  39. package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
  40. package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
  41. package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
  42. package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
  43. package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
  44. package/assets/skills/office-documents/tasks/verify_render.md +11 -23
  45. package/assets/skills/office-documents/tasks/watermarks_background.md +11 -15
  46. package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
  47. package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
  48. package/assets/skills/office-pdf/SKILL.md +36 -51
  49. package/assets/skills/office-pdf/references/form-fields.md +20 -20
  50. package/assets/skills/office-pdf/references/geometry.md +10 -10
  51. package/assets/skills/office-pdf/references/layout-quality.md +13 -13
  52. package/assets/skills/office-pdf/references/limits.md +12 -56
  53. package/assets/skills/office-pdf/tasks/annotations.md +5 -5
  54. package/assets/skills/office-pdf/tasks/create.md +6 -9
  55. package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
  56. package/assets/skills/office-pdf/tasks/forms.md +15 -15
  57. package/assets/skills/office-pdf/tasks/read.md +9 -9
  58. package/assets/skills/office-pdf/tasks/redact.md +18 -18
  59. package/assets/skills/office-pdf/tasks/stamp.md +10 -10
  60. package/assets/skills/office-presentations/SKILL.md +71 -91
  61. package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
  62. package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
  63. package/assets/skills/office-presentations/recipes/README.md +24 -35
  64. package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
  65. package/assets/skills/office-presentations/recipes/connectors.md +11 -12
  66. package/assets/skills/office-presentations/recipes/images.md +11 -12
  67. package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
  68. package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
  69. package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
  70. package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
  71. package/assets/skills/office-presentations/recipes/tables.md +14 -14
  72. package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
  73. package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
  74. package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
  75. package/assets/skills/office-presentations/references/finalization.md +10 -12
  76. package/assets/skills/office-presentations/references/native-bullets.md +14 -18
  77. package/assets/skills/office-presentations/references/native-evidence.md +18 -32
  78. package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
  79. package/assets/skills/office-presentations/references/templates.md +31 -60
  80. package/assets/skills/office-presentations/routing/google_slides.md +4 -4
  81. package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
  82. package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
  83. package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
  84. package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
  85. package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
  86. package/assets/skills/office-presentations/tasks/template-following.md +23 -28
  87. package/assets/skills/office-spreadsheets/SKILL.md +32 -39
  88. package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
  89. package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
  90. package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
  91. package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
  92. package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
  93. package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
  94. package/assets/skills/office-spreadsheets/references/charts.md +15 -34
  95. package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
  96. package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
  97. package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
  98. package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
  99. package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
  100. package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
  101. package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
  102. package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
  103. package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
  104. package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
  105. package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
  106. package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
  107. package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
  108. package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
  109. package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
  110. package/assets/skills/shared/annotation-recipes.md +98 -120
  111. package/assets/skills/shared/common-workflow.md +70 -80
  112. package/dist/index.js +1 -1
  113. package/package.json +1 -1
@@ -1,7 +1,6 @@
1
1
  # Formula patterns
2
2
 
3
- Spreadsheet formulas are read by people who did not write them and recalculated
4
- by engines that disagree at the edges. Prefer the direct, boring form.
3
+ People who did not write a formula have to read it, and engines that disagree at the edges recalculate it. Prefer the direct, boring form.
5
4
 
6
5
  ## Anchoring
7
6
 
@@ -12,67 +11,38 @@ by engines that disagree at the edges. Prefer the direct, boring form.
12
11
  | `$A8` | right only | A column of item labels |
13
12
  | `$B$3` | never | One rate, a case selector, a fixed constant |
14
13
 
15
- `=SUMIFS(Amount,Month,C$4,Item,$A8)` reads the period from the header and the item
16
- from the label. `=C8*$B$3` multiplies by one fixed rate; `=C8*C$3` multiplies by
17
- the rate in that column. Getting this backwards is the most common silent error in
18
- a copied model — check one filled row and one filled column by hand.
14
+ `=SUMIFS(Amount,Month,C$4,Item,$A8)` reads the period from the header and the item from the label. `=C8*$B$3` multiplies by one fixed rate; `=C8*C$3` multiplies by the rate in that column. Getting this backwards is the most common silent error in a copied model — check one filled row and one filled column by hand.
19
15
 
20
16
  ## Aggregation
21
17
 
22
- - `SUM` for a column, `SUMIFS` for filtered totals, `COUNTIFS` for counts,
23
- `AVERAGEIFS` for averages.
24
- - Use `SUMIFS`/`COUNTIFS` even with one criterion; they read the same and extend
25
- cleanly.
26
- - `SUMPRODUCT(qty_range, rate_range)` for paired multiplication; it does not
27
- collapse to a single cell the way array arithmetic would.
28
- - `PRODUCT` for multiplied factors, but it skips blanks: a missing input silently
29
- removes a factor. Check the inputs before trusting the result.
30
- - `INDEX`/`MATCH`, `VLOOKUP(...,FALSE)`, or `XLOOKUP` — all fine. Keep the exact
31
- match flag explicit. A matched key is not a filled value: check the returned
32
- cell for blank as well as for the key existing.
33
- - Long category lists belong in a mapping table with a lookup, not in a nested
34
- `IF` chain.
18
+ - `SUM` for a column, `SUMIFS` for filtered totals, `COUNTIFS` for counts, `AVERAGEIFS` for averages.
19
+ - Use `SUMIFS`/`COUNTIFS` even with one criterion; they read the same and extend cleanly.
20
+ - `SUMPRODUCT(qty_range, rate_range)` for paired multiplication; it does not collapse to a single cell the way array arithmetic would.
21
+ - `PRODUCT` for multiplied factors, but it skips blanks: a missing input silently removes a factor. Check the inputs before trusting the result.
22
+ - `INDEX`/`MATCH`, `VLOOKUP(...,FALSE)`, or `XLOOKUP` — all fine. Keep the exact-match flag explicit. A matched key is not a filled value: check the returned cell for blank as well as for the key existing.
23
+ - Long category lists belong in a mapping table with a lookup, not in a nested `IF` chain.
35
24
 
36
25
  ## Dates and periods
37
26
 
38
- - Use the date the source gives; `TODAY()` only when the workbook should track
39
- today, and label it when it does.
27
+ - Use the date the source gives; `TODAY()` only when the workbook should track today, and label it when it does.
40
28
  - Store real dates with a date number format. Text dates do not calculate.
41
- - Derive period filters from one header row so a new month is a copy, not an edit:
42
- `=SUMIFS(Amount,Date,">="&C$4,Date,"<"&EDATE(C$4,1),Item,$A8)`.
43
- - Week starting on the first business day (Monday unless the business says
44
- otherwise); say which in the header.
45
- - Time scales run left to right coarse to fine: Annual, Quarterly, Monthly,
46
- Weekly — with narrow unfilled spacer columns, not merged headers over hidden
47
- helpers.
29
+ - Derive period filters from one header row so a new month is a copy, not an edit: `=SUMIFS(Amount,Date,">="&C$4,Date,"<"&EDATE(C$4,1),Item,$A8)`.
30
+ - Week starting on the first business day (Monday unless the business says otherwise); say which in the header.
31
+ - Time scales run left to right coarse to fine: Annual, Quarterly, Monthly, Weekly — with narrow unfilled spacer columns, not merged headers over hidden helpers.
48
32
 
49
33
  ## Missing data
50
34
 
51
- - A real zero is zero. A missing value is blank, or honestly `n.a.`/`N/A` where
52
- the reader expects text. Never substitute one for the other to make a chart look
53
- complete.
54
- - `IFERROR` only around a failure you understand, never wrapped around a whole
55
- block to hide it. `IFERROR(x,0)` turns a broken reference into a plausible zero.
56
- - Guards must not swallow the failure they guard against: `=IF(C8=0,"n.a.",B8/C8)`
57
- is a clear answer, `=IFERROR(B8/C8,0)` is a lie.
58
- - Missing keys in a lookup should show as missing (`=IFNA(...,"not found")`), not
59
- as zero.
35
+ - A real zero is zero. A missing value is blank, or honestly `n.a.`/`N/A` where the reader expects text. Never substitute one for the other to make a chart look complete.
36
+ - `IFERROR` only around a failure you understand, never around a whole block to hide it. `IFERROR(x,0)` turns a broken reference into a plausible zero.
37
+ - Guards must not swallow the failure they guard against: `=IF(C8=0,"n.a.",B8/C8)` is a clear answer, `=IFERROR(B8/C8,0)` is a lie.
38
+ - Missing keys in a lookup should show as missing (`=IFNA(...,"not found")`), not as zero.
60
39
 
61
40
  ## Things not to write
62
41
 
63
- - `LET`, dynamic arrays/spills, `MAP`, `REDUCE`, `LAMBDA`: the engines that read
64
- these files implement them unevenly, and openpyxl stores text without
65
- validating it.
66
- - `INDIRECT` for everything. It breaks traceability and does not update when a
67
- sheet is renamed. Keep it only where the existing file already relies on it.
68
- - Volatile functions (`TODAY`, `NOW`, `RAND`, `OFFSET`) in a calculation grid:
69
- every keystroke recalculates them, and the value changes when the file is
70
- reopened.
42
+ - `LET`, dynamic arrays/spills, `MAP`, `REDUCE`, `LAMBDA`: the engines that read these files implement them unevenly, and openpyxl stores text without validating it.
43
+ - `INDIRECT` for everything. It breaks traceability and does not update when a sheet is renamed. Keep it only where the existing file already relies on it.
44
+ - Volatile functions (`TODAY`, `NOW`, `RAND`, `OFFSET`) in a calculation grid: every keystroke recalculates them, and the value changes when the file is reopened.
71
45
 
72
46
  ## Circular references
73
47
 
74
- Avoid unintended cycles; Excel flags them for a reason. If a cycle is deliberate
75
- (interest on average balance, iterative allocation), document it in the sheet,
76
- confirm iteration is enabled, and verify the result converges to the expected
77
- number. A model that only "works" because the last recalc happened to stop at
78
- iteration 100 is not verified.
48
+ Avoid unintended cycles; Excel flags them for a reason. If a cycle is deliberate (interest on average balance, iterative allocation), document it in the sheet, confirm iteration is enabled, and verify the result converges to the expected number. A model that only "works" because the last recalc happened to stop at iteration 100 is not verified.
@@ -1,69 +1,44 @@
1
1
  # Style guidelines
2
2
 
3
- Precedence: the user's request, then the workbook or template being edited, then a
4
- domain convention, then these defaults. Defaults apply to new sheets, or to
5
- restyling the user asked for — never to a sheet you were not asked to touch.
3
+ Precedence: the user's request, then the workbook or template being edited, then a domain convention, then these defaults. Defaults apply to new sheets, or to restyling the user asked for — never to a sheet you were not asked to touch.
6
4
 
7
5
  ## Page furniture
8
6
 
9
- - One blank row at the top, then a short unfilled title, left aligned, in a size
10
- clearly larger than the body. No full-width filled banner.
7
+ - One blank row at the top, then a short unfilled title, left aligned, in a size clearly larger than the body. No full-width filled banner.
11
8
  - A thin rule under the title separates it from the table; nothing else.
12
- - Notes sit in ordinary cells to the right of the data, at least one blank column
13
- away from the last header fill, with wrap off.
9
+ - Notes sit in ordinary cells to the right of the data, at least one blank column away from the last header fill, with wrap off.
14
10
  - No footer blocks, no "Prepared by" furniture, no date stamps nobody asked for.
15
- - Gridlines off on new sheets. Do not change gridlines on a sheet you are editing
16
- for another reason.
11
+ - Gridlines off on new sheets. Do not change gridlines on a sheet you are editing for another reason.
17
12
 
18
13
  ## Structure
19
14
 
20
- - Freeze the header row of any table that scrolls, plus the identifying column(s)
21
- when horizontal scrolling hides them. Freeze the smallest useful area and never
22
- move content to make freezing convenient.
23
- - Header row: bold, centred horizontally and vertically, dark fill with white text
24
- or a light grey band, thin white separators between header cells.
25
- - Section bands: one continuous fill with a single outline around the block; no
26
- internal borders inside the band, no full-cell grid.
27
- - Spacer columns are genuinely empty (no values, no borders), not narrow columns
28
- of spaces.
29
- - Keep working titles, headers, and input areas unmerged. Center Across Selection
30
- gives the look of a merge without breaking sorting, filtering, and references.
15
+ - Freeze the header row of any table that scrolls, plus the identifying column(s) when horizontal scrolling hides them. Freeze the smallest useful area and never move content to make freezing convenient.
16
+ - Header row: bold, centred horizontally and vertically, dark fill with white text or a light grey band, thin white separators between header cells.
17
+ - Section bands: one continuous fill with a single outline around the block; no internal borders inside the band, no full-cell grid.
18
+ - Spacer columns are genuinely empty (no values, no borders), not narrow columns of spaces.
19
+ - Keep working titles, headers, and input areas unmerged. Center Across Selection gives the look of a merge without breaking sorting, filtering, and references.
31
20
 
32
21
  ## Numbers, inputs, calcs
33
22
 
34
23
  - Typed values with explicit number formats — see `recipes/number-formats.md`.
35
- - Left-align text, right-align numbers, centre headers, middle-align vertically;
36
- top-align long wrapped descriptions.
37
- - Distinguish inputs from calculations consistently: inputs get a light fill or a
38
- colour cue the sheet already uses, calculations stay white. Yellow/amber marks an
39
- input that still needs updating; keep that cue separate from calculated warnings.
40
- - When cases exist, show `Case Selected:` plus the linked value near the top of
41
- each output and build tab, in a restrained dashed outline, and highlight the
42
- active row in the driver table.
24
+ - Left-align text, right-align numbers, centre headers, middle-align vertically; top-align long wrapped descriptions.
25
+ - Distinguish inputs from calculations consistently: inputs get a light fill or a colour cue the sheet already uses, calculations stay white. Yellow/amber marks an input that still needs updating; keep that cue separate from calculated warnings.
26
+ - When cases exist, show `Case Selected:` plus the linked value near the top of each output and build tab, in a restrained dashed outline, and highlight the active row in the driver table.
43
27
  - Technical helper rows above a model are italic and grouped/collapsed.
44
28
 
45
29
  ## Conditional formatting as a cue
46
30
 
47
- - Bound the rule to the data, and use it for status, risk, variance, and
48
- exceptions — not decoration.
49
- - Critical errors: light red fill, bold dark red text. Valid checks stay neutral;
50
- no static green "PASS" paint over a range.
51
- - Reuse the sheet's existing rule style before inventing a new colour. Two similar
52
- reds in one workbook look like two different severities.
31
+ - Bound the rule to the data, and use it for status, risk, variance, and exceptions — not decoration.
32
+ - Critical errors: light red fill, bold dark red text. Valid checks stay neutral; no static green "PASS" paint over a range.
33
+ - Reuse the sheet's existing rule style before inventing a new colour. Two similar reds in one workbook look like two different severities.
53
34
 
54
35
  ## Typography
55
36
 
56
37
  - One family across the workbook: Helvetica Neue, Helvetica, Arial, then Aptos.
57
- - Two sizes at most (three counting the title). Largest size no more than six
58
- points above body. A 10pt body with an 11pt header and a 14pt title is enough.
59
- - Bold for headers and totals, italic for short context notes — never both on
60
- the same line, never on every row.
61
- - Tighten row heights after content fits; do not shrink the font to win an
62
- argument with a column width.
38
+ - Two sizes at most (three counting the title). Largest size no more than six points above body. A 10pt body with an 11pt header and a 14pt title is enough.
39
+ - Bold for headers and totals, italic for short context notes — never both on the same line, never on every row.
40
+ - Tighten row heights after content fits; do not shrink the font to win an argument with a column width.
63
41
 
64
42
  ## Tab colours
65
43
 
66
- Use colours only to help navigation: a darker brand tone on output tabs, one
67
- level lighter on assumptions, a distinct muted tone on a ReadMe, a divider tab
68
- coloured while its children stay plain. Financial Actuals tabs are traditionally
69
- light tan. Never recolour tabs during an unrelated edit.
44
+ Use colour only to help navigation: a darker brand tone on output tabs, one level lighter on assumptions, a distinct muted tone on a ReadMe, a divider tab coloured while its children stay plain. Financial Actuals tabs are traditionally light tan. Never recolour tabs during an unrelated edit.
@@ -1,9 +1,6 @@
1
1
  # Workbook structure
2
2
 
3
- Tab roles describe what a sheet *does*, not what tabs a workbook must have. A
4
- simple workbook can carry several roles as labelled blocks on one sheet; a large
5
- one separates them because the readers, the refresh cadence, or the audit trail
6
- differ.
3
+ Tab roles describe what a sheet *does*, not what tabs a workbook must have. A simple workbook can carry several roles as labelled blocks on one sheet; a large one separates them because the readers, the refresh cadence, or the audit trail differ.
7
4
 
8
5
  | Role | Holds | Feeds |
9
6
  | --- | --- | --- |
@@ -16,45 +13,25 @@ differ.
16
13
 
17
14
  Rules that keep a workbook readable a year later:
18
15
 
19
- - Inputs flow forward: source → build → output. A source tab never reads a
20
- downstream result back in; when it seems to, the value belongs on a build tab.
21
- - Builds show the steps: quantity × rate, capacity used ÷ capacity available,
22
- opening + movements = closing. One dense formula that jumps from input to final
23
- number cannot be reviewed and will be wrong the first time an input changes.
24
- - Outputs consolidate and roll up. They do not repeat a calculation that already
25
- exists on a build tab; they reference it.
26
- - Checks are terminal. Nothing depends on a check tab, and a passing check stays
27
- neutral — a wall of green PASS fills trains the reader to ignore the one red
28
- cell that matters.
29
- - Combine roles when the workbook is small. Three assumption cells do not need a
30
- Settings tab; a short labelled block beside the calculation is easier to audit.
31
- - Add a tab when the reader differs, the data grain differs, the refresh
32
- boundary differs, or the user asks. Not because a template had one.
16
+ - Inputs flow forward: source → build → output. A source tab never reads a downstream result back in; when it seems to, the value belongs on a build tab.
17
+ - Builds show the steps: quantity × rate, capacity used ÷ capacity available, opening + movements = closing. One dense formula that jumps from input to final number cannot be reviewed and will be wrong the first time an input changes.
18
+ - Outputs consolidate and roll up. They reference the calculation on the build tab; they do not repeat it.
19
+ - Checks are terminal. Nothing depends on a check tab, and a passing check stays neutral — a wall of green PASS fills trains the reader to ignore the one red cell that matters.
20
+ - Combine roles when the workbook is small. Three assumption cells do not need a Settings tab; a short labelled block beside the calculation is easier to audit.
21
+ - Add a tab when the reader differs, the data grain differs, the refresh boundary differs, or the user asks. Not because a template had one.
33
22
 
34
23
  ## Physical order
35
24
 
36
- For multi-tab workbooks, left to right: outputs, the assumption control panel
37
- (usually just after the primary output so a reader sees the switch), builds,
38
- then inputs and sources, with a divider tab such as `Internal >>` guarding the
39
- tail. The reader gets the answer first; the machinery lives to the right.
25
+ For multi-tab workbooks, left to right: outputs, the assumption control panel (usually just after the primary output so a reader sees the switch), builds, then inputs and sources, with a divider tab such as `Internal >>` guarding the tail. The reader gets the answer first; the machinery lives to the right.
40
26
 
41
- Separate schedules when inputs, grain, or owners differ (revenue vs cost bases,
42
- monthly vs weekly). A single mega-sheet that mixes both grains is where
43
- double-counting starts.
27
+ Separate schedules when inputs, grain, or owners differ (revenue vs cost bases, monthly vs weekly). A single mega-sheet that mixes both grains is where double-counting starts.
44
28
 
45
29
  ## Names
46
30
 
47
- Short, descriptive, and about the content: `Pipeline`, `Revenue build`,
48
- `Monthly forecast`. Not `Sheet3`, not `Data2`, not a sentence. A forecast review
49
- tab is `Forecast review`, `Forecast variance`, or `Sensitivity`; never `Movement`,
50
- which says nothing about what moved.
31
+ Short, descriptive, and about the content: `Pipeline`, `Revenue build`, `Monthly forecast`. Not `Sheet3`, not `Data2`, not a sentence. A forecast review tab is `Forecast review`, `Forecast variance`, or `Sensitivity`; never `Movement`, which says nothing about what moved.
51
32
 
52
- Divider tabs are labels, not data: `Inputs >>` with its children uncoloured reads
53
- as a section marker; a coloured tab on every sheet reads as noise.
33
+ Divider tabs are labels, not data: `Inputs >>` with its children uncoloured reads as a section marker; a coloured tab on every sheet reads as noise.
54
34
 
55
35
  ## The case selector
56
36
 
57
- When a workbook has cases, there is exactly one editable selector, on the cover
58
- or assumptions tab, with its current value shown as `Case Selected:` near the top
59
- of every output and build tab. Two selectors, or a selector plus hard-coded
60
- per-tab values, is how a model ends up reporting two different cases.
37
+ When a workbook has cases, there is exactly one editable selector, on the cover or assumptions tab, with its current value shown as `Case Selected:` near the top of every output and build tab. Two selectors, or a selector plus hard-coded per-tab values, is how a model ends up reporting two different cases.
@@ -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
- opens in Sheets, or the user exports the sheet and shares the file.
11
- 2. Ask for an export when the source lives in Sheets: `File > Download >
12
- Microsoft Excel (.xlsx)`. A single-sheet CSV loses formulas and formats, so ask
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
- ## When writing formulas for a file that will go back to Sheets
12
+ ## Formulas for a file that goes back to Sheets
21
13
 
22
- - Keep to functions both engines share: `SUMIFS`, `INDEX/MATCH`, `XLOOKUP`,
23
- `IFERROR`, `EDATE`, `TEXT`.
24
- - Newer functions that Excel stores with an `_xlfn.` prefix are a common source of
25
- `#NAME?` after a round trip. If a function is genuinely new, say so.
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
- sheet names, used ranges, and cell contents.
10
- 2. Read **values**, not formulas, when the question is about numbers:
11
- `xlsx read --data-only` returns cached results. If the cache is empty (the
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
- not an error to fix. Explain the calculation and stop.
25
- - Pre-existing `#REF!`/`#DIV/0!` cells are part of the answer. Point at them, say
26
- what breaks, and wait for instructions.
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
- area the user marked: read the visible headers, row labels, and the numbers
26
- around the box.
27
- 2. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"`,
28
- then match the visible values to sheets and A1 addresses. Values repeat across
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
- panes, hidden columns, and zoom all move cells under the same pixel.
44
- - Do not edit the first sheet because it was the default. The visible page may be
45
- the fourth sheet.
46
- - Do not re-style the whole sheet to make the marked area consistent. Match the
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 the sheets as roles, not tabs: inputs, calculations, outputs, checks. A five-line model belongs on one sheet with labelled blocks.
44
- 2. Put the 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 the calculation as visible steps (quantity × rate, opening + movements = closing) and link the output to the build rather than repeating the arithmetic.
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` is larger than 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.
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. Anything under cells that you did not intend to touch is collateral damage — revert and redo with a narrower edit.
29
- 2. A sheet, table, name, or chart in "removed" is a lost object; rebuild it from `recipes/charts.md` / `recipes/named-ranges.md` before presenting.
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 does not show: 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.
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, never by editing the file you just read and forgetting the step in between.
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 — do those with a snippet from `recipes/data-tables.md` and `recipes/charts.md`, or the new rows will sit outside the table and the chart will stop at the old last row. `add_chart.py` treats a one-row data range as one series of many points (which is what a monthly row means) but cannot set axis number formats or series colours; fix those in the same snippet.
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 in a cell; the format stays unless the request names it.
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]` — the 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: formats that govern how they read, objects that live beside them, and whether the formulas were ever computed.
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 editing to prove nothing was lost.
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` means the chart is cut off when printed |
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 were ever computed). `--sample N` sets how many formula samples per sheet are printed (default 5).
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 deliberately `#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, and re-inspect after saving.
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 sheet with a huge `dimensions` and 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` are the two fields that explain most render surprises: charts clipped at the page edge, or entire data blocks missing from a PDF because they fall outside the print range.
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.