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.
- package/assets/skills/excel-live-control/SKILL.md +119 -152
- package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
- package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
- package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
- package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
- package/assets/skills/excel-live-control/references/office-automation.md +127 -153
- package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
- package/assets/skills/excel-live-control/style_guidelines.md +56 -64
- package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
- package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
- package/assets/skills/office-documents/SKILL.md +24 -60
- package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
- package/assets/skills/office-documents/ooxml/comments.md +8 -8
- package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
- package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
- package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
- package/assets/skills/office-documents/references/docx-structure.md +11 -13
- package/assets/skills/office-documents/references/template-elicitation.md +11 -13
- package/assets/skills/office-documents/references/writing-quality.md +20 -20
- package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
- package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
- package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
- package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
- package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
- package/assets/skills/office-documents/tasks/create_edit.md +14 -16
- package/assets/skills/office-documents/tasks/equations.md +17 -28
- package/assets/skills/office-documents/tasks/fields_update.md +14 -16
- package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
- package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
- package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
- package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
- package/assets/skills/office-documents/tasks/images_figures.md +15 -25
- package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
- package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
- package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
- package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
- package/assets/skills/office-documents/tasks/read_review.md +9 -20
- package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
- package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
- package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
- package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
- package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
- package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
- package/assets/skills/office-documents/tasks/verify_render.md +11 -23
- package/assets/skills/office-documents/tasks/watermarks_background.md +11 -15
- package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
- package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
- package/assets/skills/office-pdf/SKILL.md +36 -51
- package/assets/skills/office-pdf/references/form-fields.md +20 -20
- package/assets/skills/office-pdf/references/geometry.md +10 -10
- package/assets/skills/office-pdf/references/layout-quality.md +13 -13
- package/assets/skills/office-pdf/references/limits.md +12 -56
- package/assets/skills/office-pdf/tasks/annotations.md +5 -5
- package/assets/skills/office-pdf/tasks/create.md +6 -9
- package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
- package/assets/skills/office-pdf/tasks/forms.md +15 -15
- package/assets/skills/office-pdf/tasks/read.md +9 -9
- package/assets/skills/office-pdf/tasks/redact.md +18 -18
- package/assets/skills/office-pdf/tasks/stamp.md +10 -10
- package/assets/skills/office-presentations/SKILL.md +71 -91
- package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
- package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
- package/assets/skills/office-presentations/recipes/README.md +24 -35
- package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
- package/assets/skills/office-presentations/recipes/connectors.md +11 -12
- package/assets/skills/office-presentations/recipes/images.md +11 -12
- package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
- package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
- package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
- package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
- package/assets/skills/office-presentations/recipes/tables.md +14 -14
- package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
- package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
- package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
- package/assets/skills/office-presentations/references/finalization.md +10 -12
- package/assets/skills/office-presentations/references/native-bullets.md +14 -18
- package/assets/skills/office-presentations/references/native-evidence.md +18 -32
- package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
- package/assets/skills/office-presentations/references/templates.md +31 -60
- package/assets/skills/office-presentations/routing/google_slides.md +4 -4
- package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
- package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
- package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
- package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
- package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
- package/assets/skills/office-presentations/tasks/template-following.md +23 -28
- package/assets/skills/office-spreadsheets/SKILL.md +32 -39
- package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
- package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
- package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
- package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
- package/assets/skills/office-spreadsheets/references/charts.md +15 -34
- package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
- package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
- package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
- package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
- package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
- package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
- package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
- package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
- package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
- package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
- package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
- package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
- package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
- package/assets/skills/shared/annotation-recipes.md +98 -120
- package/assets/skills/shared/common-workflow.md +70 -80
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,53 +1,52 @@
|
|
|
1
1
|
# Marketing and advertising
|
|
2
2
|
|
|
3
|
-
Campaign, funnel, lead, CRM and ad-performance data.
|
|
4
|
-
|
|
3
|
+
Campaign, funnel, lead, CRM and ad-performance data. Failures here are grain, denominator or
|
|
4
|
+
freshness — rarely arithmetic.
|
|
5
5
|
|
|
6
6
|
## Know what the export is
|
|
7
7
|
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **Channel setup
|
|
12
|
-
|
|
13
|
-
- **Grain
|
|
8
|
+
- **Freshness**: an export pulled Tuesday and analysed Friday is Tuesday's data. Record the
|
|
9
|
+
extract date and as-of date in the input area; do not read a Friday-vs-Tuesday difference as
|
|
10
|
+
performance.
|
|
11
|
+
- **Channel setup**: a campaign may span an ad platform, a CRM and a billing system. Name the
|
|
12
|
+
source of each figure before combining them.
|
|
13
|
+
- **Grain**: daily rows are not campaign rows. Impressions are not sessions; clicks are not
|
|
14
14
|
leads; leads are not qualified leads; a pipeline total is not revenue.
|
|
15
|
-
- **Denominators
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
- **Denominators**: CTR uses impressions; CVR uses sessions or clicks per the platform's
|
|
16
|
+
definition; CPA uses conversions attributed that period. Put the platform's definition in
|
|
17
|
+
the label — vendors' "conversion rate" differ.
|
|
18
18
|
|
|
19
19
|
## Layout
|
|
20
20
|
|
|
21
21
|
- Name tabs by content and period: `Leads_Q1_2025`, `Pipeline Analysis`, `ROI Dashboard`.
|
|
22
|
-
- Keep the raw import intact on its own sheet; clean in derived columns or a prepared
|
|
23
|
-
|
|
24
|
-
renamed source) so the exclusion is visible.
|
|
22
|
+
- Keep the raw import intact on its own sheet; clean in derived columns or a prepared area,
|
|
23
|
+
and record exclusions and mappings (non-target region, test account, renamed source).
|
|
25
24
|
- One typed time-series date column with one format. Add an ISO helper column only when a
|
|
26
|
-
downstream import needs it,
|
|
25
|
+
downstream import needs it, labelled as such.
|
|
27
26
|
- Targets and traffic lights only when the source supplies a target and a direction. No
|
|
28
|
-
invented targets, no green/amber/red on
|
|
29
|
-
- Every dashboard figure traces back to a cell in the prepared data
|
|
30
|
-
|
|
27
|
+
invented targets, no green/amber/red on goals nobody set.
|
|
28
|
+
- Every dashboard figure traces back to a cell in the prepared data; otherwise it does not go
|
|
29
|
+
on the dashboard.
|
|
31
30
|
|
|
32
31
|
## Metrics
|
|
33
32
|
|
|
34
|
-
- Define abbreviations where
|
|
35
|
-
|
|
36
|
-
- Keep the comparison basis visible: week over week, month over month, or
|
|
37
|
-
|
|
38
|
-
- Attribution:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- Charts only when they make a trend,
|
|
42
|
-
|
|
33
|
+
- Define abbreviations where used (CPC, CPM, CPA, ROAS, MQL) — a legend on the analysis sheet,
|
|
34
|
+
not a glossary tab nobody opens.
|
|
35
|
+
- Keep the comparison basis visible: week over week, month over month, or same period last
|
|
36
|
+
year. Mixing bases in one chart is the most common misleading dashboard.
|
|
37
|
+
- Attribution: state the model (last click, first click, linear, platform-reported) and keep
|
|
38
|
+
it consistent within a table. Platform- and analytics-reported conversions never reconcile
|
|
39
|
+
exactly; report both.
|
|
40
|
+
- Charts only when they make a trend, comparison or funnel clearer than a table. Six
|
|
41
|
+
categories is a table with extra steps.
|
|
43
42
|
|
|
44
43
|
## Doing it live
|
|
45
44
|
|
|
46
|
-
- Read first: `info` (
|
|
45
|
+
- Read first: `info` (sheets, used ranges, whether the user is mid-edit), then
|
|
47
46
|
`read_range --formulas` across the block you will extend.
|
|
48
|
-
- Append new periods as rows below the
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
- Verify with `read_range --formulas
|
|
53
|
-
|
|
47
|
+
- Append new periods as rows below the table and extend the table, conditional formatting and
|
|
48
|
+
chart source with them. No second table beside the first.
|
|
49
|
+
- For a refresh flag (stale extract, missing platform), use amber input fill plus a note in
|
|
50
|
+
the cell beside it, not an unexplained colour.
|
|
51
|
+
- Verify with `read_range --formulas`; a misaligned denominator surfaces as a rate off by a
|
|
52
|
+
factor of ten.
|
|
@@ -1,53 +1,51 @@
|
|
|
1
1
|
# Scientific research data
|
|
2
2
|
|
|
3
|
-
The spreadsheet is often the only record of an experiment. Treat
|
|
4
|
-
irreplaceable: a cleaned value that overwrote a raw measurement is data loss, and a live
|
|
5
|
-
|
|
3
|
+
The spreadsheet is often the only record of an experiment. Treat observations as
|
|
4
|
+
irreplaceable: a cleaned value that overwrote a raw measurement is data loss, and a live edit
|
|
5
|
+
is one keystroke away.
|
|
6
6
|
|
|
7
7
|
## Keep the raw table raw
|
|
8
8
|
|
|
9
|
-
- One flat table: one row per observation, one variable per column, one unit per column.
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
`
|
|
13
|
-
- Record the cleaning:
|
|
14
|
-
|
|
15
|
-
- Missing observations stay visibly missing (blank or `n.a
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
- One flat table: one row per observation, one variable per column, one unit per column. No
|
|
10
|
+
merged cells, no multi-row headers, no calculation rows inside the data block.
|
|
11
|
+
- Never overwrite a measurement. Transformations go in separate columns (headed `log10(x)`,
|
|
12
|
+
`normalised`) or a separate processed block or sheet.
|
|
13
|
+
- Record the cleaning: rows excluded and why, values imputed, units converted — in a protocol
|
|
14
|
+
note on or beside the sheet.
|
|
15
|
+
- Missing observations stay visibly missing (blank or `n.a.`, per the table's convention);
|
|
16
|
+
never zero-fill silently. Label randomised and simulated values as such — they are not
|
|
17
|
+
observations.
|
|
18
18
|
|
|
19
19
|
## Presentation tables are a different object
|
|
20
20
|
|
|
21
|
-
When the sheet
|
|
21
|
+
When the sheet reports the data rather than holding it:
|
|
22
22
|
|
|
23
|
-
- One type of data per column
|
|
24
|
-
the cell.
|
|
23
|
+
- One type of data per column; units in the header (`Concentration (mg/L)`), never in the cell.
|
|
25
24
|
- Never encode meaning only in colour or bold — add a labelled value column (`Flag:
|
|
26
|
-
excluded`, `Status: control`). A
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
- No merged cells in a table you expect anyone to sort or filter.
|
|
25
|
+
excluded`, `Status: control`). A monochrome printout must still carry the meaning.
|
|
26
|
+
- Notes belong in a notes column, not in cell comments a co-author will never see.
|
|
27
|
+
- No merged cells in a table anyone will sort or filter.
|
|
30
28
|
|
|
31
29
|
## Analysis
|
|
32
30
|
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
- Show the
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
- Distinguish measurement, derived value, flag and assumption
|
|
40
|
-
|
|
41
|
-
- If the design
|
|
42
|
-
|
|
31
|
+
- A transparent formula beats a clever one; someone must defend the number in review six
|
|
32
|
+
months from now.
|
|
33
|
+
- Show the steps: intermediate columns are the evidence; one formula makes the result
|
|
34
|
+
unfalsifiable.
|
|
35
|
+
- Circular references and iterative calculation are off-limits unless the user asks and
|
|
36
|
+
documents it. A simulation's random seed and method are part of the result.
|
|
37
|
+
- Distinguish measurement, derived value, flag and assumption by label, not by font colour
|
|
38
|
+
alone.
|
|
39
|
+
- If the design changes (exclusion added, normalisation changed), say so in the reply. A
|
|
40
|
+
quiet denominator change rewrites the conclusion.
|
|
43
41
|
|
|
44
42
|
## Doing it live
|
|
45
43
|
|
|
46
44
|
- Before touching anything: `info`, then `read_range --formulas --display` on the block.
|
|
47
|
-
Raw data and report blocks
|
|
48
|
-
- Append observations as
|
|
49
|
-
|
|
50
|
-
- Verify with `read_range --formulas`; the `errors` array catches the `#DIV/0!` and
|
|
51
|
-
|
|
52
|
-
- Never delete rows from the middle of a data table; a delete shifts every downstream
|
|
53
|
-
|
|
45
|
+
Raw data and report blocks usually sit on different sheets; confirm which is which.
|
|
46
|
+
- Append observations as bottom rows, extend any table object to cover them, leave the header
|
|
47
|
+
row untouched.
|
|
48
|
+
- Verify with `read_range --formulas`; the `errors` array catches the `#DIV/0!` and `#VALUE!`
|
|
49
|
+
that appear when text lands in a numeric column.
|
|
50
|
+
- Never delete rows from the middle of a data table; a delete shifts every downstream formula
|
|
51
|
+
and chart range.
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
# The COM object model behind a live edit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
boundaries, and every object you hold is a proxy that re-reads state when you ask it.
|
|
6
|
-
That explains most of the rules below.
|
|
3
|
+
The target is an out-of-process COM server that owns a window. Each property read or write
|
|
4
|
+
is a remote call; each object is a proxy that re-reads state. That explains most rules here.
|
|
7
5
|
|
|
8
6
|
`container_tools/live_excel.py` wraps the common cases. Read this when the CLI has no verb
|
|
9
|
-
for
|
|
10
|
-
are extending the tool.
|
|
7
|
+
for the task, a failure is unexplained, or you extend the tool.
|
|
11
8
|
|
|
12
9
|
## Reaching the running instance
|
|
13
10
|
|
|
@@ -15,36 +12,33 @@ are extending the tool.
|
|
|
15
12
|
$app = [Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application')
|
|
16
13
|
```
|
|
17
14
|
|
|
18
|
-
-
|
|
19
|
-
Excel.Application` creates a new
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
- WPS
|
|
25
|
-
|
|
26
|
-
`
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
it stays invisible until something shows it, and it leaks until `Application.Quit()`.
|
|
15
|
+
- The only supported way to find a running instance. `New-Object -ComObject
|
|
16
|
+
Excel.Application` creates a new invisible one; never use it for user work.
|
|
17
|
+
- Only in Windows PowerShell 5.1 (`powershell.exe`); PowerShell 7 (`pwsh`) removed it,
|
|
18
|
+
which is why the tool shells out to `powershell.exe`.
|
|
19
|
+
- Nothing running raises `0x800401E3 (MK_E_UNAVAILABLE)`. Ask the user to open the
|
|
20
|
+
workbook; launch nothing.
|
|
21
|
+
- WPS registers `Ket.Application` and `Excel.Application`, so attaching does not prove
|
|
22
|
+
Microsoft Excel. `Application.Name`/`Version` are useless here (WPS reports `Microsoft
|
|
23
|
+
Excel` / `12.0`). Infer the product from `Application.Path`.
|
|
24
|
+
- The running-object table is per user session and outlives the creating process. A hidden
|
|
25
|
+
self-test instance stays attachable, invisible until shown, and leaks until
|
|
26
|
+
`Application.Quit()`.
|
|
31
27
|
|
|
32
28
|
## Addressing
|
|
33
29
|
|
|
34
30
|
`Application` → `Workbooks` → `Workbook` → `Sheets` → `Worksheet` → `Range`.
|
|
35
31
|
|
|
36
32
|
- Collections are **1-based**: `$book.Sheets.Item(1)`. `Item(0)` throws.
|
|
37
|
-
- `$sheet.Cells` is the whole sheet; `$sheet.UsedRange` is the rectangle
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- A1 strings: `A1`, `B4:D9`, `$B$14`, `Sheet1!A1:C9`, `'Build Detail'!E14` (quote
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
spelling.
|
|
47
|
-
- Multi-area ranges (`A1:A5,C1:C5`) exist; the tool refuses them for writes because a
|
|
33
|
+
- `$sheet.Cells` is the whole sheet; `$sheet.UsedRange` is the rectangle holding content or
|
|
34
|
+
formatting. Clearing the last cell does not shrink it: a read hint, never an edit
|
|
35
|
+
boundary.
|
|
36
|
+
- A1 strings: `A1`, `B4:D9`, `$B$14`, `Sheet1!A1:C9`, `'Build Detail'!E14` (quote names
|
|
37
|
+
with spaces). `$r.Address(0,0)` gives `A1:C3`; report the absolute form the user can
|
|
38
|
+
paste into the Name Box.
|
|
39
|
+
- Sheet-name matching is case-insensitive in .NET but exact for COM:
|
|
40
|
+
`$book.Sheets.Item('Build')` throws on `build`. Use `Worksheet.Name` for spelling.
|
|
41
|
+
- Multi-area ranges (`A1:A5,C1:C5`) exist; the tool refuses them for writes because one
|
|
48
42
|
rectangular `Value2` assignment cannot fill them.
|
|
49
43
|
|
|
50
44
|
## Cells: what you write and what comes back
|
|
@@ -52,156 +46,136 @@ $app = [Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application')
|
|
|
52
46
|
| Property | Use it for | Reads back |
|
|
53
47
|
| --- | --- | --- |
|
|
54
48
|
| `Range.Value2` | every value: numbers, text, dates (as serials), booleans, arrays | typed scalars / `Object[,]` |
|
|
55
|
-
| `Range.Formula` | formulas in A1 notation; also
|
|
49
|
+
| `Range.Formula` | formulas in A1 notation; also how to read them back | `String`, e.g. `=SUM(B2:B9)` |
|
|
56
50
|
| `Range.FormulaR1C1` | fills where you think in offsets | `String` |
|
|
57
|
-
| `Range.Text` | the
|
|
58
|
-
|
|
59
|
-
- **`Value2`
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
you are writing.
|
|
67
|
-
- A multi-cell read returns a 2-D `Object[,]` with **1-based** indices. A single cell
|
|
51
|
+
| `Range.Text` | the displayed string, after number format | per-cell only |
|
|
52
|
+
|
|
53
|
+
- **`Value2` preserves type and ignores locale.** A `Double` stays a number, a `String`
|
|
54
|
+
stays text — unless the app parses it as a date, currency, or `=1+1`. `"2026-01-31"`
|
|
55
|
+
written through `Value2` produced serial `46053` in a date-formatted cell. For literal
|
|
56
|
+
text, store the serial/number and set a number format, or prefix the apostrophe. Never
|
|
57
|
+
rely on the parse.
|
|
58
|
+
- **`$null` empties a cell**, the supported way to clear one value inside a written block.
|
|
59
|
+
- A multi-cell read returns a 2-D `Object[,]` with **1-based** indices; a single cell
|
|
68
60
|
returns a scalar, so code that always indexes `[1,1]` fails on one-cell ranges.
|
|
69
|
-
- **Errors
|
|
70
|
-
`-
|
|
71
|
-
`-
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
- Formulas are text. There is no calculation on write; the value updates when the
|
|
84
|
-
application recalculates, which is why `recalc` exists.
|
|
61
|
+
- **Errors are integers.** `#DIV/0!` is Int32 SCODE `-2146826281`; `#VALUE!` `-2146826273`,
|
|
62
|
+
`#REF!` `-2146826265`, `#NAME?` `-2146826259`, `#NUM!` `-2146826252`, `#N/A`
|
|
63
|
+
`-2146826246`. WPS returns `False` from `WorksheetFunction.IsError` and throws on
|
|
64
|
+
`SpecialCells(16)`, so test "is this an Int32?", then read `Range.Text`,
|
|
65
|
+
`Range.Formula`, `Range.Address(0,0)` for that cell alone.
|
|
66
|
+
- `Range.Text` is per-cell; on a multi-cell range WPS returns `DBNull`, so the tool reads
|
|
67
|
+
cell by cell (hence the `--display` cap).
|
|
68
|
+
- **One formula assigned to a range fills with relative adjustment**: `A1:A3` = `=B1`
|
|
69
|
+
gives `=B1`, `=B2`, `=B3`. Cheap for a column, and how unintended formulas appear on
|
|
70
|
+
multi-cell targets.
|
|
71
|
+
- Dates are serials (`days since 1899-12-30`, 1900 system). `DateSerial(y,m,d)` gives the
|
|
72
|
+
number; `NumberFormat` gives the look.
|
|
73
|
+
- Formulas are text. Nothing calculates on write; values update on recalc, which is why
|
|
74
|
+
`recalc` exists.
|
|
85
75
|
|
|
86
76
|
## Number formats
|
|
87
77
|
|
|
88
|
-
`Range.NumberFormat` takes
|
|
89
|
-
`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
- Format is display only
|
|
95
|
-
|
|
96
|
-
- One format per column
|
|
97
|
-
|
|
98
|
-
-
|
|
99
|
-
|
|
100
|
-
- `###`
|
|
101
|
-
|
|
102
|
-
`EntireColumn.AutoFit()`, and check the result with `--display`.
|
|
78
|
+
`Range.NumberFormat` takes codes, not locales: `#,##0`, `#,##0.00`, `0.0%`, `"$"#,##0.00`,
|
|
79
|
+
`mmm-yy`, `d-mmm`, `@`. Use invariant ASCII; the dot is always the decimal point inside a
|
|
80
|
+
code, whatever `Application.DecimalSeparator` says. WPS returns empty
|
|
81
|
+
`DecimalSeparator`/`ThousandsSeparator`: never read locale from the app or build codes from
|
|
82
|
+
locale data.
|
|
83
|
+
|
|
84
|
+
- Format is display only; values keep full precision. Never round data to make it read
|
|
85
|
+
right.
|
|
86
|
+
- One format per column; mixing `#,##0` and `#,##0.00` down a column is the commonest
|
|
87
|
+
visual defect.
|
|
88
|
+
- Precision belongs in the code: `0.0%` for analytical tables, `0%` for dashboards,
|
|
89
|
+
`0.00%` when differences are small.
|
|
90
|
+
- `###` means too narrow, not wrong. Widen with `ColumnWidth` (default ~8.43) or
|
|
91
|
+
`EntireColumn.AutoFit()`, then check with `--display`.
|
|
103
92
|
|
|
104
93
|
## Colour is BGR
|
|
105
94
|
|
|
106
|
-
`Interior.Color` and `Font.Color` are OLE
|
|
107
|
-
spec in this repo is `#RRGGBB`. Convert explicitly:
|
|
95
|
+
`Interior.Color` and `Font.Color` are OLE longs `0xBBGGRR`; specs are `#RRGGBB`:
|
|
108
96
|
|
|
109
97
|
```
|
|
110
98
|
ole = red + green * 256 + blue * 65536 # #RRGGBB -> BGR long
|
|
111
99
|
```
|
|
112
100
|
|
|
113
|
-
`#C00000` becomes `192`;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
existing colours rather than inventing one.
|
|
101
|
+
`#C00000` becomes `192`; pure blue fill is `16711680`. `ColorIndex = -4142` removes a fill
|
|
102
|
+
(`Interior.Color` then reads `16777215`). Theme colours and tints are not addressable;
|
|
103
|
+
reuse existing workbook colours.
|
|
117
104
|
|
|
118
105
|
## Font, borders, alignment, layout
|
|
119
106
|
|
|
120
107
|
- `Range.Font`: `Name`, `Size`, `Bold`, `Italic`, `Color`, `Underline`, `Strikethrough`.
|
|
121
|
-
One family
|
|
122
|
-
|
|
123
|
-
- `Range.Borders.Item(index)`: 7 left, 8 top, 9 bottom, 10 right; `LineStyle` (1
|
|
124
|
-
`Weight` (2 thin), `Color`. `BorderAround(1, 2)` draws a thin outline in one
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
- Whole-sheet `AutoFit` and `Select`/`Activate`
|
|
134
|
-
|
|
135
|
-
user who is looking at the window.
|
|
108
|
+
One family per sheet: Helvetica Neue → Helvetica → Arial → Aptos, whichever the workbook
|
|
109
|
+
uses.
|
|
110
|
+
- `Range.Borders.Item(index)`: 7 left, 8 top, 9 bottom, 10 right; `LineStyle` (1
|
|
111
|
+
continuous), `Weight` (2 thin), `Color`. `BorderAround(1, 2)` draws a thin outline in one
|
|
112
|
+
call.
|
|
113
|
+
- `HorizontalAlignment` takes `xlHAlign*` (`-4131` left, `-4108` center, `-4152` right);
|
|
114
|
+
`VerticalAlignment` takes `xlVAlign*` (`-4160` top, `-4108` center, `-4104` bottom). The
|
|
115
|
+
tool maps readable names.
|
|
116
|
+
- Also: `Merge()`, `UnMerge()`, `WrapText`, `IndentLevel`, `EntireColumn.ColumnWidth`,
|
|
117
|
+
`Tab.Color`, `Rows.Hidden`.
|
|
118
|
+
- `FreezePanes` lives on `Window` and did not stick on a hidden WPS instance. No freeze
|
|
119
|
+
verb: tell the user, or do it visibly.
|
|
120
|
+
- Whole-sheet `AutoFit` and `Select`/`Activate` change the user's view, can take seconds,
|
|
121
|
+
and `ScreenUpdating` does not hide the flicker.
|
|
136
122
|
|
|
137
123
|
## Objects beside the cells
|
|
138
124
|
|
|
139
|
-
- **Tables**: `$sheet.ListObjects.Add(1, $range, [Type]::Missing, $has_headers)
|
|
140
|
-
|
|
141
|
-
`
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
rather than adding a second one over the same cells.
|
|
125
|
+
- **Tables**: `$sheet.ListObjects.Add(1, $range, [Type]::Missing, $has_headers)`.
|
|
126
|
+
PowerShell cannot reproduce VBA's empty argument positions, so pass `[Type]::Missing` for
|
|
127
|
+
`Destination`. Tables get localized default names (`表1`); name them. `has_headers = 0`
|
|
128
|
+
makes the app generate a header row above the data, shifting values down and making the
|
|
129
|
+
table one row taller than the range. Extend with `ListObject.Resize`, never a second
|
|
130
|
+
table.
|
|
146
131
|
- **Charts**: `$sheet.ChartObjects().Add(left, top, width, height)` → `.Chart` →
|
|
147
|
-
`.SetSourceData($range)` + `.ChartType
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
- **
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- **Conditional formats**: `Range.FormatConditions`. Appending a condition to a range
|
|
161
|
-
that already has one edits the *existing* set; a "fix" here can silently change rules
|
|
162
|
-
the user depends on. Read first, and keep the range bounded.
|
|
163
|
-
- **Validation**: `Range.Validation` — same rule. Read the existing rule before writing a
|
|
164
|
-
new one.
|
|
132
|
+
`.SetSourceData($range)` + `.ChartType`; `HasTitle`/`ChartTitle.Text` set the title.
|
|
133
|
+
Types: column 51, stacked column 52, bar 57, stacked bar 58, line 4, line with markers
|
|
134
|
+
65, area 1, stacked area 76, pie 5, doughnut -4120, scatter -4169, scatter with lines 74.
|
|
135
|
+
A chart over an empty range renders blank; check the source cells.
|
|
136
|
+
- **Shapes**: `Shapes.AddShape(...)`, `AddTextbox`, `AddPicture`. They float over cells, sit
|
|
137
|
+
outside the used range, and need `TopLeftCell` anchoring to move with data.
|
|
138
|
+
- **Pivots**: `PivotTables`, `PivotFields`. Read and report; never rebuild through COM
|
|
139
|
+
unless asked — a failed attempt loses the layout.
|
|
140
|
+
- **Names**: `$workbook.Names`, `Range.Name`. Deleting their cells breaks names (`#REF!`),
|
|
141
|
+
so a rename or row delete is a contract change.
|
|
142
|
+
- **Conditional formats**: `Range.FormatConditions`. Appending to a range with an existing
|
|
143
|
+
condition edits that set; read first, keep the range bounded.
|
|
144
|
+
- **Validation**: `Range.Validation`; read the existing rule before writing.
|
|
165
145
|
|
|
166
146
|
## Calculation and freshness
|
|
167
147
|
|
|
168
|
-
- `Application.Calculation`: `-4105` automatic, `-4135` manual.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
- `CalculateFull` recalculates dependencies, not just the active sheet.
|
|
172
|
-
rebuilds the
|
|
173
|
-
slow on
|
|
174
|
-
-
|
|
175
|
-
|
|
176
|
-
succeed.
|
|
148
|
+
- `Application.Calculation`: `-4105` automatic, `-4135` manual. Manual mode shows stale
|
|
149
|
+
numbers after an edit; `recalc` runs `CalculateFull` on every open workbook and reports
|
|
150
|
+
the mode.
|
|
151
|
+
- `CalculateFull` recalculates dependencies, not just the active sheet.
|
|
152
|
+
`CalculateFullRebuild` rebuilds the tree; use it only when a value looks impossible — it
|
|
153
|
+
is slow on large models.
|
|
154
|
+
- Iteration (`Application.Iteration`) is off by default. Circular references that "worked"
|
|
155
|
+
mean it was on; do not enable it to make an edit succeed.
|
|
177
156
|
|
|
178
157
|
## Latency, failures, retries
|
|
179
158
|
|
|
180
|
-
- Every property access is an RPC.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
-
|
|
187
|
-
- `
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- **Nothing is transactional.** A call that fails halfway leaves the cells it already
|
|
197
|
-
wrote. The retry protocol is: `read_range` the block, compare with intent, write only
|
|
198
|
-
what is missing or wrong. Replaying the same batch is how a live document gets
|
|
199
|
-
duplicated rows.
|
|
159
|
+
- Every property access is an RPC. `info` plus three reads took 1.2–1.5 s here; formatting
|
|
160
|
+
100 cells one at a time can take tens of seconds. **Batch**: one `write_range` per block,
|
|
161
|
+
one `style_range` per range, one `set_formula` per column. Never loop per cell.
|
|
162
|
+
- Default timeout is 180 s. Raising it is fine for a big paste; below 1 s fails on a busy
|
|
163
|
+
app.
|
|
164
|
+
- Failures you meet:
|
|
165
|
+
- `0x800401E3` — nothing running. Ask the user to open the workbook.
|
|
166
|
+
- `0x8001010A` (RPC_E_SERVERCALL_RETRYLATER) — app busy (dialog, recalculation, dragged
|
|
167
|
+
window). Read again; if it persists, tell the user a dialog is blocking it.
|
|
168
|
+
- "Object required" / stale proxy — usually the workbook was closed. Re-attach by name;
|
|
169
|
+
never reuse the old object.
|
|
170
|
+
- An Excel method raising "does not contain a method named …" in WPS: the WPS model is a
|
|
171
|
+
subset. Fall back to a simpler route (formatting via `Value2`/`NumberFormat`).
|
|
172
|
+
- **Nothing is transactional.** A half-failing call leaves written cells. Retry:
|
|
173
|
+
`read_range` the block, compare with intent, write only what is missing or wrong.
|
|
174
|
+
Replaying a batch duplicates rows.
|
|
200
175
|
|
|
201
176
|
## The one rule that outranks the rest
|
|
202
177
|
|
|
203
|
-
A live edit mutates a document the user is looking at
|
|
204
|
-
**Read and diff before writing.** `read_range` the target with `--formulas`; note
|
|
205
|
-
`
|
|
206
|
-
|
|
207
|
-
work is more important than finishing the task.
|
|
178
|
+
A live edit mutates a document the user is looking at, possibly with unsaved changes.
|
|
179
|
+
**Read and diff before writing.** `read_range` the target with `--formulas`; note
|
|
180
|
+
`saved: false` from `info`; then make the smallest write that satisfies the request. If the
|
|
181
|
+
diff shows unexpected values, stop and ask — unsaved user work outranks finishing the task.
|