dsh-office-kit 0.2.0 → 0.3.0
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/CAPABILITY.md +147 -68
- package/README.md +3 -1
- package/assets/skills/excel-live-control/SKILL.md +234 -0
- package/assets/skills/excel-live-control/container_tools/live_excel.py +1589 -0
- package/assets/skills/excel-live-control/domain_guidance/financial_models.md +86 -0
- package/assets/skills/excel-live-control/domain_guidance/healthcare.md +58 -0
- package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +53 -0
- package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +53 -0
- package/assets/skills/excel-live-control/references/office-automation.md +207 -0
- package/assets/skills/excel-live-control/references/read_only_qna.md +59 -0
- package/assets/skills/excel-live-control/style_guidelines.md +87 -0
- package/assets/skills/excel-live-control/workflows/create_workflows.md +78 -0
- package/assets/skills/excel-live-control/workflows/edit_workflows.md +72 -0
- package/assets/skills/office-documents/SKILL.md +90 -77
- package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +86 -0
- package/assets/skills/office-documents/ooxml/comments.md +40 -0
- package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +66 -0
- package/assets/skills/office-documents/ooxml/rels_and_content_types.md +62 -0
- package/assets/skills/office-documents/ooxml/tracked_changes.md +53 -0
- package/assets/skills/office-documents/references/docx-structure.md +83 -0
- package/assets/skills/office-documents/references/template-elicitation.md +49 -0
- package/assets/skills/office-documents/references/writing-quality.md +49 -0
- package/assets/skills/office-documents/render_docx.py +92 -0
- package/assets/skills/office-documents/scripts/a11y_audit.py +194 -0
- package/assets/skills/office-documents/scripts/accept_tracked_changes.py +151 -0
- package/assets/skills/office-documents/scripts/add_tracked_replacements.py +148 -0
- package/assets/skills/office-documents/scripts/append_blocks.py +108 -0
- package/assets/skills/office-documents/scripts/apply_template_styles.py +104 -0
- package/assets/skills/office-documents/scripts/captions_and_crossrefs.py +102 -0
- package/assets/skills/office-documents/scripts/comments_add.py +136 -0
- package/assets/skills/office-documents/scripts/comments_apply_patch.py +114 -0
- package/assets/skills/office-documents/scripts/comments_extract.py +85 -0
- package/assets/skills/office-documents/scripts/comments_strip.py +74 -0
- package/assets/skills/office-documents/scripts/content_controls.py +192 -0
- package/assets/skills/office-documents/scripts/core_properties.py +124 -0
- package/assets/skills/office-documents/scripts/docx_kit.py +587 -0
- package/assets/skills/office-documents/scripts/docx_ooxml_patch.py +225 -0
- package/assets/skills/office-documents/scripts/docx_table_to_csv.py +99 -0
- package/assets/skills/office-documents/scripts/fields_materialize.py +66 -0
- package/assets/skills/office-documents/scripts/fields_report.py +59 -0
- package/assets/skills/office-documents/scripts/flatten_ref_fields.py +62 -0
- package/assets/skills/office-documents/scripts/footnotes_report.py +77 -0
- package/assets/skills/office-documents/scripts/google_docs_title_sanitize.py +96 -0
- package/assets/skills/office-documents/scripts/heading_audit.py +81 -0
- package/assets/skills/office-documents/scripts/images_audit.py +80 -0
- package/assets/skills/office-documents/scripts/insert_note.py +126 -0
- package/assets/skills/office-documents/scripts/insert_ref_fields.py +90 -0
- package/assets/skills/office-documents/scripts/insert_toc.py +84 -0
- package/assets/skills/office-documents/scripts/internal_nav.py +146 -0
- package/assets/skills/office-documents/scripts/make_fixtures.py +169 -0
- package/assets/skills/office-documents/scripts/merge_docx_append.py +239 -0
- package/assets/skills/office-documents/scripts/privacy_scrub.py +131 -0
- package/assets/skills/office-documents/scripts/redact_docx.py +113 -0
- package/assets/skills/office-documents/scripts/render_and_diff.py +101 -0
- package/assets/skills/office-documents/scripts/replace_text.py +154 -0
- package/assets/skills/office-documents/scripts/section_audit.py +91 -0
- package/assets/skills/office-documents/scripts/set_protection.py +92 -0
- package/assets/skills/office-documents/scripts/style_lint.py +111 -0
- package/assets/skills/office-documents/scripts/style_normalize.py +103 -0
- package/assets/skills/office-documents/scripts/table_geometry.py +167 -0
- package/assets/skills/office-documents/scripts/watermark_add.py +48 -0
- package/assets/skills/office-documents/scripts/watermark_audit_remove.py +67 -0
- package/assets/skills/office-documents/scripts/xlsx_to_docx_table.py +117 -0
- package/assets/skills/office-documents/tasks/accessibility_a11y.md +45 -0
- package/assets/skills/office-documents/tasks/captions_crossrefs.md +49 -0
- package/assets/skills/office-documents/tasks/clean_tracked_changes.md +49 -0
- package/assets/skills/office-documents/tasks/comments_manage.md +59 -0
- package/assets/skills/office-documents/tasks/compare_diff.md +40 -0
- package/assets/skills/office-documents/tasks/create_edit.md +107 -0
- package/assets/skills/office-documents/tasks/equations.md +59 -0
- package/assets/skills/office-documents/tasks/fields_update.md +44 -0
- package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +50 -0
- package/assets/skills/office-documents/tasks/footnotes_endnotes.md +38 -0
- package/assets/skills/office-documents/tasks/forms_content_controls.md +48 -0
- package/assets/skills/office-documents/tasks/headings_numbering.md +55 -0
- package/assets/skills/office-documents/tasks/images_figures.md +63 -0
- package/assets/skills/office-documents/tasks/multi_doc_merge.md +43 -0
- package/assets/skills/office-documents/tasks/navigation_internal_links.md +38 -0
- package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +45 -0
- package/assets/skills/office-documents/tasks/protection_restrict_editing.md +41 -0
- package/assets/skills/office-documents/tasks/read_review.md +50 -0
- package/assets/skills/office-documents/tasks/redaction_anonymization.md +42 -0
- package/assets/skills/office-documents/tasks/sections_layout.md +54 -0
- package/assets/skills/office-documents/tasks/style_lint_normalize.md +44 -0
- package/assets/skills/office-documents/tasks/tables_spreadsheets.md +64 -0
- package/assets/skills/office-documents/tasks/templates_style_packs.md +53 -0
- package/assets/skills/office-documents/tasks/toc_workflow.md +39 -0
- package/assets/skills/office-documents/tasks/verify_render.md +50 -0
- package/assets/skills/office-documents/tasks/watermarks_background.md +35 -0
- package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +47 -0
- package/assets/skills/office-documents/troubleshooting/run_splitting.md +36 -0
- package/assets/skills/office-pdf/SKILL.md +73 -56
- package/assets/skills/office-pdf/references/form-fields.md +56 -0
- package/assets/skills/office-pdf/references/geometry.md +44 -0
- package/assets/skills/office-pdf/references/layout-quality.md +41 -0
- package/assets/skills/office-pdf/references/limits.md +58 -0
- package/assets/skills/office-pdf/scripts/extract_text.py +172 -0
- package/assets/skills/office-pdf/scripts/forms.py +556 -0
- package/assets/skills/office-pdf/scripts/metadata.py +161 -0
- package/assets/skills/office-pdf/scripts/page_ops.py +198 -0
- package/assets/skills/office-pdf/scripts/redact_region.py +347 -0
- package/assets/skills/office-pdf/scripts/render_pages.py +207 -0
- package/assets/skills/office-pdf/scripts/split_pages.py +155 -0
- package/assets/skills/office-pdf/scripts/stamp_overlay.py +199 -0
- package/assets/skills/office-pdf/tasks/annotations.md +98 -0
- package/assets/skills/office-pdf/tasks/create.md +75 -0
- package/assets/skills/office-pdf/tasks/edit-pages.md +71 -0
- package/assets/skills/office-pdf/tasks/forms.md +67 -0
- package/assets/skills/office-pdf/tasks/read.md +62 -0
- package/assets/skills/office-pdf/tasks/redact.md +72 -0
- package/assets/skills/office-pdf/tasks/stamp.md +60 -0
- package/assets/skills/office-presentations/SKILL.md +141 -87
- package/assets/skills/office-presentations/container_tools/add_slides.py +136 -0
- package/assets/skills/office-presentations/container_tools/core_properties.py +120 -0
- package/assets/skills/office-presentations/container_tools/create_montage.py +126 -0
- package/assets/skills/office-presentations/container_tools/inspect_presentation_layout_geometry.py +285 -0
- package/assets/skills/office-presentations/container_tools/inspect_presentation_package_integrity.py +157 -0
- package/assets/skills/office-presentations/container_tools/native_chart_title_gate.py +144 -0
- package/assets/skills/office-presentations/container_tools/native_quantitative_chart_gate.py +199 -0
- package/assets/skills/office-presentations/container_tools/native_table_arithmetic_gate.py +212 -0
- package/assets/skills/office-presentations/container_tools/ooxml_helpers.py +345 -0
- package/assets/skills/office-presentations/container_tools/preview_render.py +375 -0
- package/assets/skills/office-presentations/container_tools/render_slides.py +139 -0
- package/assets/skills/office-presentations/container_tools/replace_text.py +168 -0
- package/assets/skills/office-presentations/container_tools/template_source_fidelity_gate.py +229 -0
- package/assets/skills/office-presentations/domain_guidance/finance.md +66 -0
- package/assets/skills/office-presentations/recipes/README.md +71 -0
- package/assets/skills/office-presentations/recipes/autolayout.md +88 -0
- package/assets/skills/office-presentations/recipes/connectors.md +83 -0
- package/assets/skills/office-presentations/recipes/images.md +80 -0
- package/assets/skills/office-presentations/recipes/master-and-layouts.md +127 -0
- package/assets/skills/office-presentations/recipes/native-charts.md +87 -0
- package/assets/skills/office-presentations/recipes/rich-text-runs.md +86 -0
- package/assets/skills/office-presentations/recipes/speaker-notes.md +65 -0
- package/assets/skills/office-presentations/recipes/tables.md +88 -0
- package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +71 -0
- package/assets/skills/office-presentations/recipes/theme-tokens.md +87 -0
- package/assets/skills/office-presentations/references/authoring-workflow.md +65 -0
- package/assets/skills/office-presentations/references/finalization.md +63 -0
- package/assets/skills/office-presentations/references/native-bullets.md +78 -0
- package/assets/skills/office-presentations/references/native-evidence.md +67 -0
- package/assets/skills/office-presentations/references/style-guidelines.md +66 -0
- package/assets/skills/office-presentations/references/templates.md +76 -0
- package/assets/skills/office-presentations/routing/google_slides.md +45 -0
- package/assets/skills/office-presentations/tasks/apply-annotations.md +83 -0
- package/assets/skills/office-presentations/tasks/charts-tables-notes.md +79 -0
- package/assets/skills/office-presentations/tasks/create-deck.md +106 -0
- package/assets/skills/office-presentations/tasks/edit-deck.md +93 -0
- package/assets/skills/office-presentations/tasks/inspect-and-verify.md +107 -0
- package/assets/skills/office-presentations/tasks/template-following.md +132 -0
- package/assets/skills/office-presentations/template_following_scripts/check_template_fidelity.py +176 -0
- package/assets/skills/office-presentations/template_following_scripts/inspect_template_deck.py +154 -0
- package/assets/skills/office-presentations/template_following_scripts/make_contact_sheet.py +111 -0
- package/assets/skills/office-presentations/template_following_scripts/prepare_template_starter_deck.py +239 -0
- package/assets/skills/office-presentations/template_following_scripts/validate_template_plan.py +185 -0
- package/assets/skills/office-spreadsheets/SKILL.md +105 -101
- package/assets/skills/office-spreadsheets/container_tools/add_chart.py +236 -0
- package/assets/skills/office-spreadsheets/container_tools/add_image.py +107 -0
- package/assets/skills/office-spreadsheets/container_tools/append_rows.py +122 -0
- package/assets/skills/office-spreadsheets/container_tools/diff_workbooks.py +306 -0
- package/assets/skills/office-spreadsheets/container_tools/inspect_workbook.py +398 -0
- package/assets/skills/office-spreadsheets/container_tools/recalc_gate.py +275 -0
- package/assets/skills/office-spreadsheets/container_tools/set_cells.py +135 -0
- package/assets/skills/office-spreadsheets/container_tools/sheet_ops.py +134 -0
- package/assets/skills/office-spreadsheets/container_tools/style_cells.py +133 -0
- package/assets/skills/office-spreadsheets/recipes/charts.md +66 -0
- package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +69 -0
- package/assets/skills/office-spreadsheets/recipes/data-tables.md +58 -0
- package/assets/skills/office-spreadsheets/recipes/named-ranges.md +41 -0
- package/assets/skills/office-spreadsheets/recipes/number-formats.md +72 -0
- package/assets/skills/office-spreadsheets/recipes/sparklines.md +43 -0
- package/assets/skills/office-spreadsheets/references/charts.md +63 -0
- package/assets/skills/office-spreadsheets/references/domain/financial-models.md +40 -0
- package/assets/skills/office-spreadsheets/references/domain/healthcare.md +22 -0
- package/assets/skills/office-spreadsheets/references/domain/marketing.md +28 -0
- package/assets/skills/office-spreadsheets/references/domain/research.md +22 -0
- package/assets/skills/office-spreadsheets/references/formula-patterns.md +78 -0
- package/assets/skills/office-spreadsheets/references/style-guidelines.md +69 -0
- package/assets/skills/office-spreadsheets/references/workbook-structure.md +60 -0
- package/assets/skills/office-spreadsheets/routing/google-sheets.md +36 -0
- package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +37 -0
- package/assets/skills/office-spreadsheets/tasks/annotations.md +51 -0
- package/assets/skills/office-spreadsheets/tasks/create-workbook.md +66 -0
- package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +38 -0
- package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +69 -0
- package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +38 -0
- package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +57 -0
- package/assets/skills/shared/annotation-recipes.md +252 -0
- package/assets/skills/shared/check_runtime.py +253 -0
- package/assets/skills/shared/common-workflow.md +139 -0
- package/assets/skills/shared/scripts/ensure_raster_image.py +187 -0
- package/dist/client.js +4 -4
- package/dist/client.js.map +1 -1
- package/dist/index.js +239 -89
- package/package.json +1 -1
- package/postinstall.mjs +92 -82
- package/python/office_cli.py +171 -246
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Number formats
|
|
2
|
+
|
|
3
|
+
A number format changes how a stored value is displayed, never the value. The
|
|
4
|
+
cell keeps full precision; `0.0%` shows `6.4%` for `0.06398`. Never store a
|
|
5
|
+
rounded number to make a column look tidy, and never store `"6.4%"` as text —
|
|
6
|
+
it stops summing.
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
import sys
|
|
10
|
+
from openpyxl import load_workbook
|
|
11
|
+
|
|
12
|
+
wb = load_workbook(sys.argv[1])
|
|
13
|
+
ws = wb["Model"]
|
|
14
|
+
|
|
15
|
+
formats = {
|
|
16
|
+
"B11:B14": "#,##0", # whole dollars
|
|
17
|
+
"B6:B7": "0.0%", # rates, one decimal
|
|
18
|
+
"B8": '"$"#,##0', # currency with a literal sign
|
|
19
|
+
"C2:C13": "yyyy-mm-dd", # real dates, ISO order
|
|
20
|
+
"D2:D13": '"$"#,##0;[Red]-"$"#,##0', # negatives in red
|
|
21
|
+
}
|
|
22
|
+
for rng, code in formats.items():
|
|
23
|
+
block = ws[rng]
|
|
24
|
+
rows = block if isinstance(block, tuple) else ((block,),) # a single cell is not a tuple
|
|
25
|
+
for row in rows:
|
|
26
|
+
for cell in row:
|
|
27
|
+
cell.number_format = code
|
|
28
|
+
wb.save(sys.argv[2])
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## The codes worth knowing
|
|
32
|
+
|
|
33
|
+
| Purpose | Code | Notes |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| Thousands, no decimals | `#,##0` | The default for money in a model |
|
|
36
|
+
| Thousands, two decimals | `#,##0.00` | Prices, unit costs |
|
|
37
|
+
| Percent, one decimal | `0.0%` | Analytical percentages — rates, margins, growth |
|
|
38
|
+
| Percent, no decimal | `0%` | Dashboard and KPI tiles only |
|
|
39
|
+
| Percent, two decimals | `0.00%` | When differences of a tenth of a point matter |
|
|
40
|
+
| Currency | `"$"#,##0` | A literal sign keeps the unit visible in every cell |
|
|
41
|
+
| Negative in red | `#,##0;[Red]-#,##0` | Check that the reader wants colour, not a `( )` convention |
|
|
42
|
+
| Date | `yyyy-mm-dd` | Sortable, unambiguous; store a real date, not text |
|
|
43
|
+
| Text passthrough | `@` | For codes and account numbers with leading zeros |
|
|
44
|
+
|
|
45
|
+
Do not use `0,0%` or `#.##0`. They are not locale-independent and render
|
|
46
|
+
differently on an engine that reads `,` as a decimal separator.
|
|
47
|
+
|
|
48
|
+
## Signs, units, and scale
|
|
49
|
+
|
|
50
|
+
- State the unit once, in the header or title (`Revenue (USD)`), and keep the
|
|
51
|
+
stored value in that unit. A column that stores thousands but is headed
|
|
52
|
+
"USD" is a defect waiting to be discovered.
|
|
53
|
+
- If the presentation needs thousands (`$K`) while the data is in units,
|
|
54
|
+
format does not divide — either store thousands and say so, or divide with a
|
|
55
|
+
formula in a helper column. Never scale twice.
|
|
56
|
+
- Percentages: store `0.064`, never `6.4`. A stored `6.4` formatted `0.0%`
|
|
57
|
+
reads `640.0%`.
|
|
58
|
+
|
|
59
|
+
## Widths and `###`
|
|
60
|
+
|
|
61
|
+
`###` means the column is narrower than the formatted number. Widen that
|
|
62
|
+
column (`ws.column_dimensions["B"].width = 14`) or shrink the font for the block.
|
|
63
|
+
Never shorten the number, switch to text, or reduce decimals just to fit — and do
|
|
64
|
+
not autofit every column in the sheet to fix one.
|
|
65
|
+
|
|
66
|
+
## Dates
|
|
67
|
+
|
|
68
|
+
Write a real date (`datetime.date(2026, 1, 31)`) and set `yyyy-mm-dd`. Storing
|
|
69
|
+
an ISO string sorts alphabetically and calculates as text: `EDATE`, `SUMIFS` on
|
|
70
|
+
dates, and `YEAR()` all fail silently or with `#VALUE!`. A date typed as a number
|
|
71
|
+
of days since 1899-12-30 is a serial — fine for formulas, unreadable for people,
|
|
72
|
+
so format it.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Sparklines and in-cell bars
|
|
2
|
+
|
|
3
|
+
openpyxl writes no sparkline object (and neither does the helper CLI), so a
|
|
4
|
+
"sparkline" here is one of two things: a formula that draws a bar inside the
|
|
5
|
+
cell, or a tiny native chart. Pick by what the user needs to read.
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
import sys
|
|
9
|
+
from openpyxl import load_workbook
|
|
10
|
+
from openpyxl.styles import Alignment, Font
|
|
11
|
+
|
|
12
|
+
wb = load_workbook(sys.argv[1])
|
|
13
|
+
ws = wb["Trend"]
|
|
14
|
+
|
|
15
|
+
for col in range(2, 14): # B..M
|
|
16
|
+
letter = ws.cell(1, col).column_letter
|
|
17
|
+
cell = ws.cell(4, col, f'=IF({letter}3="","",REPT("█",MAX(1,ROUND({letter}3/MAX($B$3:$M$3)*7,0))))')
|
|
18
|
+
cell.font = Font(size=9, color="FF2E7D32")
|
|
19
|
+
cell.alignment = Alignment(horizontal="left", shrink_to_fit=True)
|
|
20
|
+
ws.row_dimensions[4].height = 14
|
|
21
|
+
wb.save(sys.argv[2])
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `REPT` needs a repeat count that fits the column. A 9-character column shows
|
|
25
|
+
about 7 blocks at 9pt; anything longer spills into the neighbouring cell and
|
|
26
|
+
the bars look like one continuous smear. Scale to the column width, not to 22.
|
|
27
|
+
- Keep the count formula-driven (`value / MAX(values) * width`), so a changed
|
|
28
|
+
number moves the bar.
|
|
29
|
+
- The block character is text. Sorting the column sorts blocks, and a reader who
|
|
30
|
+
copies the cell gets `████`, not a number — never put these in the column the
|
|
31
|
+
numbers should be read from.
|
|
32
|
+
- Guard blanks with `IF(cell="","",…)`, otherwise a blank reads as zero and every
|
|
33
|
+
missing month draws a minimum bar.
|
|
34
|
+
- A native in-cell chart is not the same as a chart object: if the user needs a
|
|
35
|
+
hover tooltip, axis, or legend, build a real chart with `recipes/charts.md`
|
|
36
|
+
instead of stretching a formula.
|
|
37
|
+
|
|
38
|
+
## When a real chart is the right answer
|
|
39
|
+
|
|
40
|
+
A sparkline is context for one number, in a dense table. If the sheet has space
|
|
41
|
+
and the point is the trend itself, a small `LineChart` (height 4, width 9, no
|
|
42
|
+
legend, no gridlines) reads better and stays editable. Two or three word-sized
|
|
43
|
+
charts beat a wall of block characters.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Chart choice and audit
|
|
2
|
+
|
|
3
|
+
A chart earns its place when it makes a comparison, a trend, a distribution, or a
|
|
4
|
+
relationship easier to see than a table would. If the reader only needs the
|
|
5
|
+
figures, a compact table or a KPI tile is better — and cheaper to check.
|
|
6
|
+
|
|
7
|
+
| Question | Default | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Compare and rank categories | Column or bar, sorted by value | Horizontal bar for long labels |
|
|
10
|
+
| Change over time | Line, chronological left to right | Area only when the volume under the line means something |
|
|
11
|
+
| Distribution of values | Histogram (formula bins + bar) | Box-and-whisker when median and spread matter and the engine supports it |
|
|
12
|
+
| Relationship between two numbers | Scatter | Never a line chart over unordered pairs |
|
|
13
|
+
| Share of a whole | Sorted bar, or a table | Pie/doughnut only for two or three slices, rough share |
|
|
14
|
+
| Exact values | Table | A chart cannot carry precision |
|
|
15
|
+
| One metric with context | KPI tile plus a small line | Sparkline-style bars only if the sheet is dense |
|
|
16
|
+
|
|
17
|
+
## Honesty
|
|
18
|
+
|
|
19
|
+
- Series must read from cells, not from typed arrays, and derived values must be
|
|
20
|
+
formulas. A chart of pasted numbers drifts the moment the table updates.
|
|
21
|
+
- Include zero on bar, column, and area axes. Narrowing a line or scatter axis is
|
|
22
|
+
acceptable when the limits are stated; a truncated bar axis turns a 5% change
|
|
23
|
+
into a dramatic cliff.
|
|
24
|
+
- No 3-D, no shadows, no gradients. They occlude data and date the workbook.
|
|
25
|
+
- One period, one baseline, one unit across comparable charts. Disclose omitted
|
|
26
|
+
periods and missing values; do not let a blank read as zero.
|
|
27
|
+
- Sort categories deliberately (by value, or by the natural order of time), and
|
|
28
|
+
keep the same order across charts that will be compared.
|
|
29
|
+
|
|
30
|
+
## Formatting rules that catch reviewers' eyes
|
|
31
|
+
|
|
32
|
+
- Title states subject and unit: `Profit by category ($m)`, `Monthly revenue
|
|
33
|
+
(USD)`. No placeholder titles, no legend standing in for a title.
|
|
34
|
+
- Units in the title or on the axis: `($K)`, `($M)`, `(USD thousands)`. Never
|
|
35
|
+
`($000)`.
|
|
36
|
+
- Axis number formats are set on the chart. Source cell formats do not carry over,
|
|
37
|
+
and a `0.0%` column can still produce `0.06, 0.08` ticks.
|
|
38
|
+
- Few series: direct labels. More series: legend above the plot area, consistent
|
|
39
|
+
colours per series across the workbook.
|
|
40
|
+
- Single series: no legend, one colour. A reference or target line is neutral or
|
|
41
|
+
dashed so it does not read as another data series.
|
|
42
|
+
- Selective data labels only — the last point, the maximum, the one the user asked
|
|
43
|
+
about. Ten labels on a twelve-point line is a table with extra steps.
|
|
44
|
+
- Line strokes are set explicitly; a fill alone may not colour an exported line.
|
|
45
|
+
|
|
46
|
+
## Placement
|
|
47
|
+
|
|
48
|
+
Charts sit next to the data they describe, aligned to a column edge, over empty
|
|
49
|
+
cells, and never over the data, the controls, or a note. Size them to their
|
|
50
|
+
content; a chart stretched across the page with two bars in it looks unfinished.
|
|
51
|
+
|
|
52
|
+
## Verifying a chart
|
|
53
|
+
|
|
54
|
+
1. Read the object back: type, anchor, series count, category source.
|
|
55
|
+
2. Render and look at the image: are there categories, is anything clipped, is the
|
|
56
|
+
legend empty, do the bars reach the values in the table?
|
|
57
|
+
3. Compare the visual against the sheet's numbers at one or two points.
|
|
58
|
+
4. Re-open in the app the user will use if the colours matter — an authoring
|
|
59
|
+
preview is not proof that a filled series exports as a visible line.
|
|
60
|
+
|
|
61
|
+
If the chart cannot be delivered as asked (the engine has no box plot, the data
|
|
62
|
+
cannot be rearranged), say so and use the closest clear alternative. Never claim a
|
|
63
|
+
requirement was met by a chart that does not show it.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Financial models
|
|
2
|
+
|
|
3
|
+
Applies to forecasts, budgets, cash-flow plans, and valuation work in any
|
|
4
|
+
industry.
|
|
5
|
+
|
|
6
|
+
- Periods run left to right with the scale in the header (Actual, Forecast,
|
|
7
|
+
Budget). Do not mix a monthly column with a quarterly total in the same row
|
|
8
|
+
without a labelled total column at the edge.
|
|
9
|
+
- Drivers first, results second: volume × price, headcount × cost, days × rate.
|
|
10
|
+
A revenue row that jumps straight to a number cannot be reviewed.
|
|
11
|
+
- Units are stated once and kept: thousands vs millions in the same block is the
|
|
12
|
+
classic reconciliation failure. Put the unit in the title, not in a footnote.
|
|
13
|
+
- Three statements or none: if the workbook includes a balance sheet and a cash
|
|
14
|
+
flow, the balance sheet must balance and closing cash must equal the cash-flow
|
|
15
|
+
ending balance. Add those as checks, not as comments.
|
|
16
|
+
- Working capital moves: receivables from revenue × DSO, payables from cost × DPO,
|
|
17
|
+
inventory from COGS × days. Hard-coded changes in working capital break when the
|
|
18
|
+
drivers move.
|
|
19
|
+
- Scenarios: one selector, one set of case inputs per driver, and an explicit
|
|
20
|
+
`Case Selected:` on each output. A workbook with two switch cells reports two
|
|
21
|
+
answers.
|
|
22
|
+
- Never hard-code a total that already exists as a sum, and never sum a column that
|
|
23
|
+
already contains a total (double counting is silent).
|
|
24
|
+
- Sensitivity: one or two variables, closed-form or a small grid with the base case
|
|
25
|
+
marked. A native What-If Data Table is a different object with its own limits —
|
|
26
|
+
only build one when the user asks for it and the engine supports it.
|
|
27
|
+
|
|
28
|
+
## Checks a finance reader looks for first
|
|
29
|
+
|
|
30
|
+
| Check | Expected |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Balance sheet balances | Assets − Liabilities − Equity = 0 |
|
|
33
|
+
| Cash ties | Closing cash on the balance sheet = cash-flow ending balance |
|
|
34
|
+
| Sum of segments | Segment revenue = consolidated revenue |
|
|
35
|
+
| Period total | Sum of monthly columns = annual total column |
|
|
36
|
+
| Case consistency | Every tab shows the same selected case |
|
|
37
|
+
| No hard-coded totals | Total cells are formulas |
|
|
38
|
+
|
|
39
|
+
Put them on a check tab, terminal and read-only, and make a failing check visually
|
|
40
|
+
obvious without painting passing checks green.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Healthcare operations
|
|
2
|
+
|
|
3
|
+
Workbooks here usually track volume, capacity, cost, and quality — not patients.
|
|
4
|
+
Treat patient-level data as sensitive: do not paste identifiers into a workbook
|
|
5
|
+
unless the user asks for it, do not copy rows from files you were shown into new
|
|
6
|
+
sheets, and prefer aggregates.
|
|
7
|
+
|
|
8
|
+
- Name the denominator in every rate: per patient day, per discharge, per 1,000
|
|
9
|
+
members, per available bed. A percentage without its base is not a metric.
|
|
10
|
+
- Volume and capacity are different columns. Utilization is
|
|
11
|
+
`used ÷ available`, and both sides need the same period and unit (bed-days, not
|
|
12
|
+
beds).
|
|
13
|
+
- Payer mix, service line, and site of care are separate dimensions. One table with
|
|
14
|
+
a column per dimension beats four tables that must be read together.
|
|
15
|
+
- Quality and safety metrics keep their own definitions; do not average a rate
|
|
16
|
+
across sites without stating whether it is volume-weighted.
|
|
17
|
+
- Claims and remittance data arrive with gaps. Show missing as blank or `n.a.`,
|
|
18
|
+
never as zero, and state the coverage period.
|
|
19
|
+
- Do not invent clinical thresholds, targets, or compliance claims. Use the
|
|
20
|
+
targets the source file provides, and cite the sheet and cell.
|
|
21
|
+
- Money and counts follow the finance conventions: units stated once, totals as
|
|
22
|
+
formulas, checks that detail rows reconcile to the summary.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Marketing and advertising
|
|
2
|
+
|
|
3
|
+
Campaign work is a funnel plus a spend table, and both are easy to make look
|
|
4
|
+
better than they are.
|
|
5
|
+
|
|
6
|
+
- One row per campaign, channel, or creative — with that grain named in the header.
|
|
7
|
+
Mixing a channel total into a campaign table double counts.
|
|
8
|
+
- The funnel reads spend → impressions → clicks → conversions → revenue, in that
|
|
9
|
+
order, with rates derived by formula: `CTR = clicks / impressions`,
|
|
10
|
+
`CVR = conversions / clicks`, `CPA = spend / conversions`,
|
|
11
|
+
`ROAS = revenue / spend`.
|
|
12
|
+
- Never compute a ratio from cells that are not the same period and the same
|
|
13
|
+
population. A monthly CTR built from a quarterly spend and a weekly click count
|
|
14
|
+
is a number nobody can defend.
|
|
15
|
+
- Attribution is a claim: say which model the numbers use (last click, platform
|
|
16
|
+
reported, blended) and keep it constant across the table. Do not add platform
|
|
17
|
+
conversions together and call it incremental revenue.
|
|
18
|
+
- Missing spend or reach for a period is blank, not zero — a zero-spend month
|
|
19
|
+
shows an infinite CPA and a fake collapse in the trend.
|
|
20
|
+
- Benchmarks and targets belong in a labelled row or column with their source, not
|
|
21
|
+
in a note the reader has to find.
|
|
22
|
+
|
|
23
|
+
## Charts for marketing
|
|
24
|
+
|
|
25
|
+
Spend and return on the same chart only when both are in the same unit; otherwise
|
|
26
|
+
two aligned charts. Sort channel bars by spend or by return — not alphabetically —
|
|
27
|
+
and keep the same order across charts. A conversion trend belongs on a line chart
|
|
28
|
+
with the campaign launch dates marked, not on a pie.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Scientific and research data
|
|
2
|
+
|
|
3
|
+
The spreadsheet is usually a working copy of measurements, not the record of
|
|
4
|
+
truth. Keep it that way: never edit raw measurements in place, and never let a
|
|
5
|
+
formatted view replace the values behind it.
|
|
6
|
+
|
|
7
|
+
- Raw data on its own sheet, untouched, in columns whose headers carry the unit
|
|
8
|
+
(`time (s)`, `temp (C)`, `conc (mg/L)`). Derived columns live on a build sheet
|
|
9
|
+
and reference the raw cells.
|
|
10
|
+
- One row per observation, one column per variable. Do not encode a variable in a
|
|
11
|
+
colour, a note, or a header font.
|
|
12
|
+
- Replicates are separate rows with a replicate id and a group id; the mean and
|
|
13
|
+
standard deviation are formulas over those rows, never typed.
|
|
14
|
+
- Keep the precision the instrument gives you and let the format hide extra
|
|
15
|
+
decimals. Rounding stored values destroys the ability to recompute a mean.
|
|
16
|
+
- Uncertainty, detection limits, and excluded points are stated in labelled cells.
|
|
17
|
+
An excluded point stays in the data with a reason column — deleting it hides the
|
|
18
|
+
decision.
|
|
19
|
+
- Smoothing, binning, and unit conversion are formulas with visible inputs, or they
|
|
20
|
+
do not exist. A trend line drawn over noisy points is not an analysis.
|
|
21
|
+
- Distribution, trend, and relationship: choose the chart by the question, and
|
|
22
|
+
check that the axis ranges and bins are stated (`references/charts.md`).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Formula patterns
|
|
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.
|
|
5
|
+
|
|
6
|
+
## Anchoring
|
|
7
|
+
|
|
8
|
+
| Reference | Moves when filled | Use for |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| `C8` | both ways | A grid where every cell looks at its own row and column |
|
|
11
|
+
| `C$4` | down only | A header row of periods |
|
|
12
|
+
| `$A8` | right only | A column of item labels |
|
|
13
|
+
| `$B$3` | never | One rate, a case selector, a fixed constant |
|
|
14
|
+
|
|
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.
|
|
19
|
+
|
|
20
|
+
## Aggregation
|
|
21
|
+
|
|
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.
|
|
35
|
+
|
|
36
|
+
## Dates and periods
|
|
37
|
+
|
|
38
|
+
- Use the date the source gives; `TODAY()` only when the workbook should track
|
|
39
|
+
today, and label it when it does.
|
|
40
|
+
- 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.
|
|
48
|
+
|
|
49
|
+
## Missing data
|
|
50
|
+
|
|
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.
|
|
60
|
+
|
|
61
|
+
## Things not to write
|
|
62
|
+
|
|
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.
|
|
71
|
+
|
|
72
|
+
## Circular references
|
|
73
|
+
|
|
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.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Style guidelines
|
|
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.
|
|
6
|
+
|
|
7
|
+
## Page furniture
|
|
8
|
+
|
|
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.
|
|
11
|
+
- 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.
|
|
14
|
+
- 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.
|
|
17
|
+
|
|
18
|
+
## Structure
|
|
19
|
+
|
|
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.
|
|
31
|
+
|
|
32
|
+
## Numbers, inputs, calcs
|
|
33
|
+
|
|
34
|
+
- 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.
|
|
43
|
+
- Technical helper rows above a model are italic and grouped/collapsed.
|
|
44
|
+
|
|
45
|
+
## Conditional formatting as a cue
|
|
46
|
+
|
|
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.
|
|
53
|
+
|
|
54
|
+
## Typography
|
|
55
|
+
|
|
56
|
+
- 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.
|
|
63
|
+
|
|
64
|
+
## Tab colours
|
|
65
|
+
|
|
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.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Workbook structure
|
|
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.
|
|
7
|
+
|
|
8
|
+
| Role | Holds | Feeds |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| Input / Sources | Pasted exports, system extracts, unchanged source tables | Builds |
|
|
11
|
+
| Assumptions | Rates, drivers, the case selector, global inputs | Builds |
|
|
12
|
+
| Build | The visible calculation steps between inputs and outputs | Outputs |
|
|
13
|
+
| Output / Summary | Consolidated results, the numbers a reader came for | Nothing downstream |
|
|
14
|
+
| Check / Audit | Diagnostics that compare what should reconcile | Nothing — terminal and read-only |
|
|
15
|
+
| Cover / ReadMe | A short front page, or an explanation of method and joins | Nothing |
|
|
16
|
+
|
|
17
|
+
Rules that keep a workbook readable a year later:
|
|
18
|
+
|
|
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.
|
|
33
|
+
|
|
34
|
+
## Physical order
|
|
35
|
+
|
|
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.
|
|
40
|
+
|
|
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.
|
|
44
|
+
|
|
45
|
+
## Names
|
|
46
|
+
|
|
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.
|
|
51
|
+
|
|
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.
|
|
54
|
+
|
|
55
|
+
## The case selector
|
|
56
|
+
|
|
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.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Google Sheets
|
|
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.
|
|
6
|
+
|
|
7
|
+
## What to do instead
|
|
8
|
+
|
|
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.
|
|
19
|
+
|
|
20
|
+
## When writing formulas for a file that will go back to Sheets
|
|
21
|
+
|
|
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`.
|
|
31
|
+
|
|
32
|
+
## Links
|
|
33
|
+
|
|
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.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Answer questions about an existing workbook
|
|
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.
|
|
5
|
+
|
|
6
|
+
## Procedure
|
|
7
|
+
|
|
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.
|
|
20
|
+
|
|
21
|
+
## Judgement calls
|
|
22
|
+
|
|
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.
|
|
31
|
+
- If the workbook has a case selector, check it. The answer depends on it.
|
|
32
|
+
|
|
33
|
+
## Output shape
|
|
34
|
+
|
|
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.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Resolve an `office-annotations` region to cells
|
|
2
|
+
|
|
3
|
+
The user drags a box on the rendered workbook and types a requirement. The
|
|
4
|
+
payload for spreadsheets is:
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"target": "book.xlsx",
|
|
9
|
+
"fileName": "book.xlsx",
|
|
10
|
+
"text": "",
|
|
11
|
+
"requirement": "make this column currency",
|
|
12
|
+
"region": { "left": 0.42, "top": 0.51, "width": 0.18, "height": 0.30 },
|
|
13
|
+
"imageName": "book-page-1.png",
|
|
14
|
+
"unmapped": true
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
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.
|
|
21
|
+
|
|
22
|
+
## Procedure
|
|
23
|
+
|
|
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.
|
|
39
|
+
|
|
40
|
+
## What not to do
|
|
41
|
+
|
|
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.
|