@svgrid/enterprise 3.0.0 → 3.0.2
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/README.md +95 -95
- package/dist/ExpressionEditorHarness.svelte.d.ts +2 -2
- package/dist/SvAdvancedFilter.svelte.d.ts +2 -2
- package/dist/SvAlertRuleEditor.svelte.d.ts +2 -2
- package/dist/SvAlertsManager.svelte.d.ts +3 -3
- package/dist/SvAlertsPanel.svelte.d.ts +1 -1
- package/dist/SvAuthGate.svelte +115 -115
- package/dist/SvAuthGate.svelte.d.ts +1 -1
- package/dist/SvBoard.svelte.d.ts +1 -1
- package/dist/SvExportMenu.svelte +553 -553
- package/dist/SvExportMenu.svelte.d.ts +2 -2
- package/dist/SvExpressionEditor.svelte.d.ts +2 -2
- package/dist/SvFileInput.svelte +113 -113
- package/dist/SvFormulaBar.svelte +606 -0
- package/dist/SvFormulaBar.svelte.d.ts +62 -0
- package/dist/SvGridAlerts.svelte.d.ts +2 -2
- package/dist/SvGridBoard.svelte +2358 -2358
- package/dist/SvGridBulkEditDrawer.svelte.d.ts +1 -1
- package/dist/SvGridEditPanel.svelte +1157 -1157
- package/dist/SvGridEditPanel.svelte.d.ts +3 -3
- package/dist/SvGridMasterDetail.svelte +116 -116
- package/dist/SvGridMasterDetail.svelte.d.ts +1 -1
- package/dist/SvGridScheduler.svelte +5358 -5358
- package/dist/SvImportDialog.svelte +1020 -1020
- package/dist/SvImportDialog.svelte.d.ts +2 -2
- package/dist/SvLookupInput.svelte +180 -180
- package/dist/SvLookupInput.svelte.d.ts +1 -1
- package/dist/SvPivotDesigner.svelte +2041 -1990
- package/dist/SvPivotDesigner.svelte.d.ts +2 -2
- package/dist/SvRecordDetail.svelte.d.ts +1 -1
- package/dist/SvRibbonIcon.svelte +46 -0
- package/dist/SvRibbonIcon.svelte.d.ts +17 -0
- package/dist/SvSchedule.svelte.d.ts +1 -1
- package/dist/SvSchemaChart.svelte +236 -234
- package/dist/SvSchemaChart.svelte.d.ts +2 -2
- package/dist/SvSchemaDashboard.svelte +130 -130
- package/dist/SvSchemaDashboard.svelte.d.ts +3 -3
- package/dist/SvSheet.svelte +4114 -0
- package/dist/SvSheet.svelte.d.ts +142 -0
- package/dist/SvSheetComment.svelte +98 -0
- package/dist/SvSheetComment.svelte.d.ts +22 -0
- package/dist/SvSheetConditionalFormat.svelte +162 -0
- package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
- package/dist/SvSheetDataValidation.svelte +249 -0
- package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
- package/dist/SvSheetFilterMenu.svelte +217 -0
- package/dist/SvSheetFilterMenu.svelte.d.ts +17 -0
- package/dist/SvSheetFindReplace.svelte +132 -0
- package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
- package/dist/SvSheetFormatCells.svelte +421 -0
- package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
- package/dist/SvSheetGoalSeek.svelte +144 -0
- package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
- package/dist/SvSheetInsertFunction.svelte +147 -0
- package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
- package/dist/SvSheetListPicker.svelte +89 -0
- package/dist/SvSheetListPicker.svelte.d.ts +16 -0
- package/dist/SvSheetManageRules.svelte +185 -0
- package/dist/SvSheetManageRules.svelte.d.ts +16 -0
- package/dist/SvSheetNameManager.svelte +225 -0
- package/dist/SvSheetNameManager.svelte.d.ts +11 -0
- package/dist/SvSheetPasteSpecial.svelte +105 -0
- package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
- package/dist/SvSheetRemoveDuplicates.svelte +149 -0
- package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
- package/dist/SvSheetRibbon.svelte +1201 -0
- package/dist/SvSheetRibbon.svelte.d.ts +34 -0
- package/dist/SvSheetSizeDialog.svelte +58 -0
- package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
- package/dist/SvSheetTabs.svelte +441 -0
- package/dist/SvSheetTabs.svelte.d.ts +36 -0
- package/dist/SvSheetTabs.test-harness.svelte.d.ts +17 -0
- package/dist/SvSheetTabs.test-harness.svelte.js +22 -0
- package/dist/SvSheetTextToColumns.svelte +172 -0
- package/dist/SvSheetTextToColumns.svelte.d.ts +13 -0
- package/dist/SvSheetValidationAlert.svelte +83 -0
- package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -1
- package/dist/advanced-filter-enable.js +3 -3
- package/dist/alerts/alert-engine-attach.d.ts +2 -2
- package/dist/alerts/alert-engine-attach.js +3 -3
- package/dist/alerts/alert-engine.d.ts +1 -1
- package/dist/alerts/alert-engine.js +2 -2
- package/dist/alerts/alert-formats.d.ts +1 -1
- package/dist/alerts/alert-formats.js +1 -1
- package/dist/alerts/alert-observer.d.ts +3 -3
- package/dist/alerts/alert-observer.js +1 -1
- package/dist/alerts/alert-storage.d.ts +1 -1
- package/dist/alerts/alert-store.svelte.d.ts +1 -1
- package/dist/alerts/alert-types.d.ts +2 -2
- package/dist/alerts.js +2 -2
- package/dist/board.js +2 -2
- package/dist/cdn/svgrid-enterprise.svelte-external.js +19046 -5428
- package/dist/designer/assets/GridMenus-BlsvL_aU.js +8 -0
- package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
- package/dist/designer/assets/SvChartMenu-D9hEeHar.js +1 -0
- package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
- package/dist/designer/assets/SvDateRangeInput-C0iCCZ8o.css +1 -0
- package/dist/designer/assets/SvDateTimePicker-DARvKUL2.js +1 -0
- package/dist/designer/assets/SvDateTimePicker-DPv09DIT.css +1 -0
- package/dist/designer/assets/{preload-helper-CG0n22O7.js → SvGrid.helpers-BgT-gnCo.js} +1 -1
- package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +4 -0
- package/dist/designer/assets/SvGridChart-B8j1SSy3.js +3 -0
- package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
- package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
- package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +1 -0
- package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
- package/dist/designer/assets/SvGridChartPanel-pT6ITc2P.js +4 -0
- package/dist/designer/assets/SvGridChartView-7msfnWZT.css +1 -0
- package/dist/designer/assets/SvGridChartView-bg281UA1.js +1 -0
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +1 -0
- package/dist/designer/assets/SvGridDropdown-CcidB3rm.css +1 -0
- package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
- package/dist/designer/assets/SvListBox-BXfyqy4a.css +1 -0
- package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
- package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
- package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
- package/dist/designer/assets/SvTabs-UFCMTHXS.js +1 -0
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +1 -0
- package/dist/designer/assets/chart-cIPUsbM5.js +1 -0
- package/dist/designer/assets/chart-export-B6bkQ3X8.js +11 -0
- package/dist/designer/assets/chart-export-pdf-BbA28-gt.js +11 -0
- package/dist/designer/assets/chart-panel-messages-DtTxpBUU.js +1 -0
- package/dist/designer/assets/chart-summary-Czu_5epb.js +1 -0
- package/dist/designer/assets/chart-trend-D5I5VEe8.js +1 -0
- package/dist/designer/assets/chart-validate-BMqM-qkF.js +1 -0
- package/dist/designer/assets/column-resize-BYDzR1Ve.js +1 -0
- package/dist/designer/assets/date-format-B8JbEtIG.js +1 -0
- package/dist/designer/assets/date-format-DKS-z0xS.css +1 -0
- package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
- package/dist/designer/assets/export-format-D-eP4b2l.js +6 -0
- package/dist/designer/assets/focus-trap-CAreAhlU.js +1 -0
- package/dist/designer/assets/index-CMFgAoVV.css +1 -0
- package/dist/designer/assets/{index-zUBix-JQ.js → index-DwU7CAMm.js} +2985 -141
- package/dist/designer/assets/list-option-BP_dWS66.js +1 -0
- package/dist/designer/assets/preload-helper-HclGiUj8.js +1 -0
- package/dist/designer/assets/row-resize-DLktcqUK.js +1 -0
- package/dist/designer/assets/src-CITpcm6b.js +1 -0
- package/dist/designer/assets/src-EdI3Xqds.js +58 -0
- package/dist/designer/index.html +32 -23
- package/dist/export-conditional.d.ts +1 -1
- package/dist/export-pdf.d.ts +89 -0
- package/dist/export-pdf.js +130 -0
- package/dist/export-print.js +19 -19
- package/dist/export-xls.d.ts +2 -2
- package/dist/export.d.ts +2 -2
- package/dist/export.js +23 -16
- package/dist/expressions/builder-tree.d.ts +2 -2
- package/dist/expressions/builder-tree.js +1 -1
- package/dist/expressions/compile.d.ts +1 -1
- package/dist/import.js +1 -1
- package/dist/index.d.ts +116 -53
- package/dist/index.js +117 -50
- package/dist/install.d.ts +4 -4
- package/dist/install.js +16 -11
- package/dist/license.d.ts +3 -2
- package/dist/license.js +9 -4
- package/dist/node/studio.js +187 -116
- package/dist/pivot-chart.d.ts +26 -2
- package/dist/pivot-chart.js +25 -69
- package/dist/pivot-designer.d.ts +1 -1
- package/dist/pivot-enable.js +3 -3
- package/dist/print.d.ts +1 -1
- package/dist/print.js +4 -4
- package/dist/scheduler-config.d.ts +5 -5
- package/dist/scheduler-freebusy.d.ts +1 -1
- package/dist/scheduler-freebusy.js +1 -1
- package/dist/scheduler.js +2 -2
- package/dist/schema-designer.d.ts +1 -1
- package/dist/schema-designer.js +2 -2
- package/dist/selection-bar.js +2 -2
- package/dist/sheet/address.d.ts +43 -0
- package/dist/sheet/address.js +81 -0
- package/dist/sheet/ast.d.ts +94 -0
- package/dist/sheet/ast.js +56 -0
- package/dist/sheet/auto-filter.d.ts +66 -0
- package/dist/sheet/auto-filter.js +147 -0
- package/dist/sheet/autocomplete.d.ts +42 -0
- package/dist/sheet/autocomplete.js +162 -0
- package/dist/sheet/coerce.d.ts +31 -0
- package/dist/sheet/coerce.js +122 -0
- package/dist/sheet/commands.d.ts +89 -0
- package/dist/sheet/commands.js +230 -0
- package/dist/sheet/comments.d.ts +29 -0
- package/dist/sheet/comments.js +73 -0
- package/dist/sheet/conditional-formats.d.ts +144 -0
- package/dist/sheet/conditional-formats.js +316 -0
- package/dist/sheet/deps.d.ts +60 -0
- package/dist/sheet/deps.js +199 -0
- package/dist/sheet/document.d.ts +150 -0
- package/dist/sheet/document.js +264 -0
- package/dist/sheet/edit-keys.d.ts +14 -0
- package/dist/sheet/edit-keys.js +40 -0
- package/dist/sheet/entry.d.ts +31 -0
- package/dist/sheet/entry.js +76 -0
- package/dist/sheet/evaluate.d.ts +61 -0
- package/dist/sheet/evaluate.js +337 -0
- package/dist/sheet/find-replace.d.ts +62 -0
- package/dist/sheet/find-replace.js +152 -0
- package/dist/sheet/format-store.d.ts +99 -0
- package/dist/sheet/format-store.js +233 -0
- package/dist/sheet/freeze.d.ts +54 -0
- package/dist/sheet/freeze.js +58 -0
- package/dist/sheet/function-catalog.d.ts +10 -0
- package/dist/sheet/function-catalog.js +94 -0
- package/dist/sheet/functions.d.ts +28 -0
- package/dist/sheet/functions.js +362 -0
- package/dist/sheet/goal-seek.d.ts +73 -0
- package/dist/sheet/goal-seek.js +153 -0
- package/dist/sheet/index.d.ts +53 -0
- package/dist/sheet/index.js +53 -0
- package/dist/sheet/merges.d.ts +71 -0
- package/dist/sheet/merges.js +137 -0
- package/dist/sheet/names.d.ts +31 -0
- package/dist/sheet/names.js +87 -0
- package/dist/sheet/navigate.d.ts +52 -0
- package/dist/sheet/navigate.js +135 -0
- package/dist/sheet/number-format.d.ts +63 -0
- package/dist/sheet/number-format.js +508 -0
- package/dist/sheet/palette.d.ts +19 -0
- package/dist/sheet/palette.js +84 -0
- package/dist/sheet/parse.d.ts +13 -0
- package/dist/sheet/parse.js +108 -0
- package/dist/sheet/paste-special.d.ts +164 -0
- package/dist/sheet/paste-special.js +592 -0
- package/dist/sheet/protection.d.ts +21 -0
- package/dist/sheet/protection.js +48 -0
- package/dist/sheet/rects.d.ts +45 -0
- package/dist/sheet/rects.js +112 -0
- package/dist/sheet/refs.d.ts +82 -0
- package/dist/sheet/refs.js +266 -0
- package/dist/sheet/ribbon-icons.d.ts +31 -0
- package/dist/sheet/ribbon-icons.js +350 -0
- package/dist/sheet/ribbon.d.ts +173 -0
- package/dist/sheet/ribbon.js +753 -0
- package/dist/sheet/shortcuts.d.ts +164 -0
- package/dist/sheet/shortcuts.js +623 -0
- package/dist/sheet/structure.d.ts +87 -0
- package/dist/sheet/structure.js +166 -0
- package/dist/sheet/tables.d.ts +70 -0
- package/dist/sheet/tables.js +147 -0
- package/dist/sheet/tokenize.d.ts +54 -0
- package/dist/sheet/tokenize.js +304 -0
- package/dist/sheet/transforms.d.ts +76 -0
- package/dist/sheet/transforms.js +154 -0
- package/dist/sheet/validation.d.ts +92 -0
- package/dist/sheet/validation.js +241 -0
- package/dist/sheet/workbook.d.ts +72 -0
- package/dist/sheet/workbook.js +409 -0
- package/dist/sheet-enable.d.ts +6 -0
- package/dist/sheet-enable.js +46 -0
- package/dist/sources/aggregate.d.ts +1 -1
- package/dist/sources/auth-supabase.js +1 -1
- package/dist/sources/dashboard.d.ts +2 -2
- package/dist/sources/dashboard.js +1 -1
- package/dist/sources/index.d.ts +13 -13
- package/dist/sources/index.js +13 -13
- package/dist/sources/realtime-supabase.js +1 -1
- package/dist/sources/relation-lookup.d.ts +1 -1
- package/dist/sources/relation-lookup.js +1 -1
- package/dist/sources/rest-adapters.d.ts +1 -1
- package/dist/sources/rest-adapters.js +1 -1
- package/dist/sources/rest.d.ts +2 -2
- package/dist/sources/rest.js +3 -3
- package/dist/sources/supabase.d.ts +2 -2
- package/dist/sources/supabase.js +3 -3
- package/dist/sources/with-entity-rules.d.ts +1 -1
- package/dist/sources/with-entity-rules.js +1 -1
- package/dist/sources/with-relation-labels.d.ts +1 -1
- package/dist/studio/emit-project.js +2161 -2127
- package/dist/studio/emit-schema.js +369 -369
- package/dist/studio/index.d.ts +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio/introspect-db.js +45 -45
- package/dist/studio/project.d.ts +10 -0
- package/dist/studio/samples/crm.js +6 -6
- package/dist/studio/samples/fleet.js +7 -7
- package/dist/studio/samples/insurance.js +9 -9
- package/dist/studio/samples/inventory.js +12 -12
- package/dist/studio/samples/projects.js +5 -5
- package/dist/studio/samples/support.js +8 -8
- package/dist/studio/scaffold-app.js +104 -104
- package/dist/studio/scaffold.js +151 -151
- package/dist/studio/ui-components.d.ts +7 -0
- package/dist/studio/ui-components.generated.js +63 -1
- package/dist/studio/ui-components.js +35 -0
- package/dist/sveltekit/in-memory.d.ts +3 -3
- package/dist/sveltekit/in-memory.js +4 -4
- package/dist/sveltekit/index.d.ts +6 -6
- package/dist/sveltekit/index.js +5 -5
- package/dist/sveltekit/query-plan.d.ts +1 -1
- package/dist/sveltekit/sql-source.d.ts +4 -4
- package/dist/sveltekit/sql-source.js +4 -4
- package/dist/sveltekit/sql.d.ts +1 -1
- package/dist/sveltekit/transport.d.ts +2 -2
- package/dist/sveltekit/transport.js +1 -1
- package/dist/upgrade-prompt.js +25 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -4
- package/dist/designer/assets/GridMenus-Cgilexpk.js +0 -8
- package/dist/designer/assets/SvDateRangeInput-BV5OXYQ2.css +0 -1
- package/dist/designer/assets/SvDateRangeInput-CVn-yqrQ.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-BdioTrJQ.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-CY8TK4BT.css +0 -1
- package/dist/designer/assets/SvField-BF-9TJSd.css +0 -1
- package/dist/designer/assets/SvField-BsqiA5me.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-dLY7_kk9.js +0 -2
- package/dist/designer/assets/SvGridChart-BEDNTdc5.js +0 -2
- package/dist/designer/assets/SvGridChart-Vu4Nvjiv.css +0 -1
- package/dist/designer/assets/SvGridChartPanel-x3lzSxuf.js +0 -10
- package/dist/designer/assets/SvGridChartView-CAKhPELi.js +0 -1
- package/dist/designer/assets/SvGridChartView-DX9HfkBR.css +0 -1
- package/dist/designer/assets/SvGridDropdown-CAYG7Y-O.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Crwb2P3Q.css +0 -1
- package/dist/designer/assets/SvListBox-CVYQcLX9.js +0 -1
- package/dist/designer/assets/SvListBox-DgN8kvjt.css +0 -1
- package/dist/designer/assets/chart-DHEgt4lN.js +0 -1
- package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
- package/dist/designer/assets/date-format-4DJvNtG2.js +0 -1
- package/dist/designer/assets/date-format-Dzy4mTGh.css +0 -1
- package/dist/designer/assets/easing-zaypKrr0.js +0 -3
- package/dist/designer/assets/export-format-DwjuTfrQ.js +0 -6
- package/dist/designer/assets/index-Cp7fDJ3b.css +0 -1
- package/dist/designer/assets/js-scroller.svelte-Bhxqb3-c.js +0 -110
- package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
- package/dist/designer/assets/src-B7DNcoQK.css +0 -1
- package/dist/designer/assets/src-BoYyigAC.js +0 -2896
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -3875
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -21
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -1938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -205
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -18
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -264
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -697
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -4938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -495
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -190
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -8
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -138
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What Insert Function shows for each function: its group, the argument
|
|
3
|
+
* list, and one line on what it does. The engine's table (`FUNCTIONS`) is
|
|
4
|
+
* the source of truth for which names exist; a name missing here is listed
|
|
5
|
+
* with a bare `NAME(...)` and no description rather than left out, so a
|
|
6
|
+
* custom function registered through `withCustomFunctions` appears too.
|
|
7
|
+
*/
|
|
8
|
+
import { FUNCTIONS } from './functions.js';
|
|
9
|
+
import { SIGNATURES } from './autocomplete.js';
|
|
10
|
+
const CATALOG = {
|
|
11
|
+
SUM: { group: 'Math', description: 'Adds all the numbers in a range of cells.', signature: 'SUM(number1, [number2], ...)' },
|
|
12
|
+
ABS: { group: 'Math', description: 'Returns the absolute value of a number, a number without its sign.', signature: 'ABS(number)' },
|
|
13
|
+
INT: { group: 'Math', description: 'Rounds a number down to the nearest integer.', signature: 'INT(number)' },
|
|
14
|
+
MOD: { group: 'Math', description: 'Returns the remainder after a number is divided by a divisor.', signature: 'MOD(number, divisor)' },
|
|
15
|
+
POWER: { group: 'Math', description: 'Returns the result of a number raised to a power.', signature: 'POWER(number, power)' },
|
|
16
|
+
SQRT: { group: 'Math', description: 'Returns the square root of a number.', signature: 'SQRT(number)' },
|
|
17
|
+
ROUND: { group: 'Math', description: 'Rounds a number to a specified number of digits.' },
|
|
18
|
+
ROUNDUP: { group: 'Math', description: 'Rounds a number up, away from zero.', signature: 'ROUNDUP(number, digits)' },
|
|
19
|
+
ROUNDDOWN: { group: 'Math', description: 'Rounds a number down, toward zero.', signature: 'ROUNDDOWN(number, digits)' },
|
|
20
|
+
SUMIF: { group: 'Math', description: 'Adds the cells specified by a given condition or criteria.' },
|
|
21
|
+
SUMIFS: { group: 'Math', description: 'Adds the cells specified by a given set of conditions or criteria.' },
|
|
22
|
+
AVERAGE: { group: 'Statistical', description: 'Returns the average (arithmetic mean) of its arguments.', signature: 'AVERAGE(number1, [number2], ...)' },
|
|
23
|
+
AVG: { group: 'Statistical', description: 'The same as AVERAGE.', signature: 'AVG(number1, [number2], ...)' },
|
|
24
|
+
MIN: { group: 'Statistical', description: 'Returns the smallest number in a set of values.', signature: 'MIN(number1, [number2], ...)' },
|
|
25
|
+
MAX: { group: 'Statistical', description: 'Returns the largest value in a set of values.', signature: 'MAX(number1, [number2], ...)' },
|
|
26
|
+
COUNT: { group: 'Statistical', description: 'Counts the number of cells in a range that contain numbers.', signature: 'COUNT(value1, [value2], ...)' },
|
|
27
|
+
COUNTA: { group: 'Statistical', description: 'Counts the number of cells in a range that are not empty.', signature: 'COUNTA(value1, [value2], ...)' },
|
|
28
|
+
COUNTBLANK: { group: 'Statistical', description: 'Counts the number of empty cells in a range.', signature: 'COUNTBLANK(range)' },
|
|
29
|
+
MEDIAN: { group: 'Statistical', description: 'Returns the median, the number in the middle of a set of numbers.', signature: 'MEDIAN(number1, [number2], ...)' },
|
|
30
|
+
STDEV: { group: 'Statistical', description: 'Estimates standard deviation based on a sample.', signature: 'STDEV(number1, [number2], ...)' },
|
|
31
|
+
RANK: { group: 'Statistical', description: 'Returns the rank of a number in a list of numbers.', signature: 'RANK(number, ref, [order])' },
|
|
32
|
+
COUNTIF: { group: 'Statistical', description: 'Counts the number of cells within a range that meet the given condition.' },
|
|
33
|
+
COUNTIFS: { group: 'Statistical', description: 'Counts the number of cells specified by a given set of conditions.' },
|
|
34
|
+
AVERAGEIF: { group: 'Statistical', description: 'Finds the average of the cells specified by a given condition.' },
|
|
35
|
+
IF: { group: 'Logical', description: 'Checks whether a condition is met, and returns one value if TRUE and another if FALSE.' },
|
|
36
|
+
IFS: { group: 'Logical', description: 'Checks whether one or more conditions are met and returns a value corresponding to the first TRUE condition.' },
|
|
37
|
+
IFERROR: { group: 'Logical', description: 'Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula.' },
|
|
38
|
+
IFNA: { group: 'Logical', description: 'Returns the value you specify if the expression resolves to #N/A, otherwise returns the result of the expression.', signature: 'IFNA(value, fallback)' },
|
|
39
|
+
SWITCH: { group: 'Logical', description: 'Evaluates an expression against a list of values and returns the result corresponding to the first matching value.' },
|
|
40
|
+
AND: { group: 'Logical', description: 'Checks whether all arguments are TRUE, and returns TRUE if all arguments are TRUE.', signature: 'AND(logical1, [logical2], ...)' },
|
|
41
|
+
OR: { group: 'Logical', description: 'Checks whether any of the arguments are TRUE, and returns TRUE or FALSE.', signature: 'OR(logical1, [logical2], ...)' },
|
|
42
|
+
NOT: { group: 'Logical', description: 'Changes FALSE to TRUE, or TRUE to FALSE.', signature: 'NOT(logical)' },
|
|
43
|
+
XOR: { group: 'Logical', description: 'Returns a logical exclusive OR of all arguments.', signature: 'XOR(logical1, [logical2], ...)' },
|
|
44
|
+
ISNUMBER: { group: 'Information', description: 'Checks whether a value is a number, and returns TRUE or FALSE.', signature: 'ISNUMBER(value)' },
|
|
45
|
+
ISTEXT: { group: 'Information', description: 'Checks whether a value is text, and returns TRUE or FALSE.', signature: 'ISTEXT(value)' },
|
|
46
|
+
ISLOGICAL: { group: 'Information', description: 'Checks whether a value is a logical value (TRUE or FALSE), and returns TRUE or FALSE.', signature: 'ISLOGICAL(value)' },
|
|
47
|
+
ISBLANK: { group: 'Information', description: 'Checks whether a reference is to an empty cell, and returns TRUE or FALSE.', signature: 'ISBLANK(value)' },
|
|
48
|
+
LEN: { group: 'Text', description: 'Returns the number of characters in a text string.', signature: 'LEN(text)' },
|
|
49
|
+
LEFT: { group: 'Text', description: 'Returns the specified number of characters from the start of a text string.', signature: 'LEFT(text, [count])' },
|
|
50
|
+
RIGHT: { group: 'Text', description: 'Returns the specified number of characters from the end of a text string.', signature: 'RIGHT(text, [count])' },
|
|
51
|
+
MID: { group: 'Text', description: 'Returns the characters from the middle of a text string, given a starting position and length.' },
|
|
52
|
+
UPPER: { group: 'Text', description: 'Converts a text string to all uppercase letters.', signature: 'UPPER(text)' },
|
|
53
|
+
LOWER: { group: 'Text', description: 'Converts all letters in a text string to lowercase.', signature: 'LOWER(text)' },
|
|
54
|
+
TRIM: { group: 'Text', description: 'Removes all spaces from a text string except for single spaces between words.', signature: 'TRIM(text)' },
|
|
55
|
+
CONCAT: { group: 'Text', description: 'Concatenates a list or range of text strings.', signature: 'CONCAT(text1, [text2], ...)' },
|
|
56
|
+
CONCATENATE: { group: 'Text', description: 'Joins several text strings into one text string.', signature: 'CONCATENATE(text1, [text2], ...)' },
|
|
57
|
+
TEXTJOIN: { group: 'Text', description: 'Concatenates a list or range of text strings using a delimiter.' },
|
|
58
|
+
SUBSTITUTE: { group: 'Text', description: 'Replaces existing text with new text in a text string.' },
|
|
59
|
+
FIND: { group: 'Text', description: 'Returns the starting position of one text string within another; case-sensitive.', signature: 'FIND(find, within, [start])' },
|
|
60
|
+
SEARCH: { group: 'Text', description: 'Returns the position of one text string within another; not case-sensitive.', signature: 'SEARCH(find, within, [start])' },
|
|
61
|
+
TEXT: { group: 'Text', description: 'Converts a value to text in a specific number format.' },
|
|
62
|
+
TODAY: { group: 'Date & Time', description: "Returns the current date formatted as a date.", signature: 'TODAY()' },
|
|
63
|
+
NOW: { group: 'Date & Time', description: 'Returns the current date and time formatted as a date and time.', signature: 'NOW()' },
|
|
64
|
+
YEAR: { group: 'Date & Time', description: 'Returns the year of a date, an integer in the range 1900 - 9999.', signature: 'YEAR(date)' },
|
|
65
|
+
MONTH: { group: 'Date & Time', description: 'Returns the month, a number from 1 (January) to 12 (December).', signature: 'MONTH(date)' },
|
|
66
|
+
DAY: { group: 'Date & Time', description: 'Returns the day of the month, a number from 1 to 31.', signature: 'DAY(date)' },
|
|
67
|
+
DATE: { group: 'Date & Time', description: 'Returns the date for a given year, month and day.' },
|
|
68
|
+
EOMONTH: { group: 'Date & Time', description: 'Returns the last day of the month before or after a specified number of months.' },
|
|
69
|
+
DAYS: { group: 'Date & Time', description: 'Returns the number of days between two dates.', signature: 'DAYS(end_date, start_date)' },
|
|
70
|
+
DATEDIF: { group: 'Date & Time', description: 'Calculates the number of days, months or years between two dates.', signature: 'DATEDIF(start_date, end_date, unit)' },
|
|
71
|
+
VLOOKUP: { group: 'Lookup & Reference', description: 'Looks for a value in the leftmost column of a table, and returns a value in the same row from a column you specify.' },
|
|
72
|
+
HLOOKUP: { group: 'Lookup & Reference', description: 'Looks for a value in the top row of a table, and returns a value in the same column from a row you specify.' },
|
|
73
|
+
XLOOKUP: { group: 'Lookup & Reference', description: 'Searches a range for a match and returns the corresponding item from a second range.' },
|
|
74
|
+
INDEX: { group: 'Lookup & Reference', description: 'Returns a value from a range at the intersection of a given row and column.' },
|
|
75
|
+
MATCH: { group: 'Lookup & Reference', description: 'Returns the relative position of an item in a range that matches a specified value.' },
|
|
76
|
+
};
|
|
77
|
+
/** The IF family is dispatched by the evaluator, not the function table. */
|
|
78
|
+
const EVALUATOR_FUNCTIONS = ['IF', 'IFS', 'IFERROR', 'IFNA', 'SWITCH'];
|
|
79
|
+
export const FUNCTION_GROUPS = [
|
|
80
|
+
'Math', 'Statistical', 'Logical', 'Information', 'Text', 'Date & Time', 'Lookup & Reference', 'Other',
|
|
81
|
+
];
|
|
82
|
+
/** Every function the engine knows, described, alphabetical. */
|
|
83
|
+
export function functionCatalog() {
|
|
84
|
+
const names = new Set([...Object.keys(FUNCTIONS), ...EVALUATOR_FUNCTIONS]);
|
|
85
|
+
return [...names].sort().map((name) => {
|
|
86
|
+
const entry = CATALOG[name];
|
|
87
|
+
return {
|
|
88
|
+
name,
|
|
89
|
+
group: entry?.group ?? 'Other',
|
|
90
|
+
signature: entry?.signature ?? SIGNATURES[name] ?? `${name}(...)`,
|
|
91
|
+
description: entry?.description ?? '',
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The function table.
|
|
3
|
+
*
|
|
4
|
+
* Each entry receives its arguments already evaluated, in two shapes:
|
|
5
|
+
* - `flat` every argument flattened into one list, ranges expanded. What
|
|
6
|
+
* SUM and COUNT want.
|
|
7
|
+
* - `args` one list per argument, so a function can tell `SUM(A1:A3, 5)`
|
|
8
|
+
* from `SUM(A1:A3)` and `SUMIF` can line a range up against a
|
|
9
|
+
* parallel one.
|
|
10
|
+
* - `grids` the 2-D shape of any range argument, kept for VLOOKUP / INDEX /
|
|
11
|
+
* MATCH, which lose meaning once flattened.
|
|
12
|
+
*
|
|
13
|
+
* Functions that must NOT evaluate every argument (IF, IFERROR, AND, OR with
|
|
14
|
+
* short-circuit semantics) are handled in the evaluator instead, because by the
|
|
15
|
+
* time a table entry runs, evaluation has already happened.
|
|
16
|
+
*/
|
|
17
|
+
import { isError, type CellValue } from './ast.js';
|
|
18
|
+
export type FnArgs = {
|
|
19
|
+
flat: ReadonlyArray<CellValue>;
|
|
20
|
+
args: ReadonlyArray<ReadonlyArray<CellValue>>;
|
|
21
|
+
grids: ReadonlyArray<ReadonlyArray<ReadonlyArray<CellValue>> | null>;
|
|
22
|
+
};
|
|
23
|
+
export type SheetFunction = (a: FnArgs) => CellValue;
|
|
24
|
+
export declare const FUNCTIONS: Record<string, SheetFunction>;
|
|
25
|
+
/** Merge caller-supplied functions over the built-ins. Keys are uppercased so
|
|
26
|
+
* a consumer can register `myFn` and write `=MYFN()`. */
|
|
27
|
+
export declare function withCustomFunctions(custom: Record<string, SheetFunction> | undefined): Record<string, SheetFunction>;
|
|
28
|
+
export { isError };
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The function table.
|
|
3
|
+
*
|
|
4
|
+
* Each entry receives its arguments already evaluated, in two shapes:
|
|
5
|
+
* - `flat` every argument flattened into one list, ranges expanded. What
|
|
6
|
+
* SUM and COUNT want.
|
|
7
|
+
* - `args` one list per argument, so a function can tell `SUM(A1:A3, 5)`
|
|
8
|
+
* from `SUM(A1:A3)` and `SUMIF` can line a range up against a
|
|
9
|
+
* parallel one.
|
|
10
|
+
* - `grids` the 2-D shape of any range argument, kept for VLOOKUP / INDEX /
|
|
11
|
+
* MATCH, which lose meaning once flattened.
|
|
12
|
+
*
|
|
13
|
+
* Functions that must NOT evaluate every argument (IF, IFERROR, AND, OR with
|
|
14
|
+
* short-circuit semantics) are handled in the evaluator instead, because by the
|
|
15
|
+
* time a table entry runs, evaluation has already happened.
|
|
16
|
+
*/
|
|
17
|
+
import { FormulaError, isError, err } from './ast.js';
|
|
18
|
+
import { toNumber, toBool, toText, looseEquals, compare, numericOnly, isBlank, matchesCriterion, } from './coerce.js';
|
|
19
|
+
const first = (a) => a.flat[0] ?? '';
|
|
20
|
+
const nth = (a, i) => a.args[i]?.[0] ?? '';
|
|
21
|
+
function sum(values) {
|
|
22
|
+
return numericOnly(values).reduce((x, y) => x + y, 0);
|
|
23
|
+
}
|
|
24
|
+
function average(values) {
|
|
25
|
+
const ns = numericOnly(values);
|
|
26
|
+
if (ns.length === 0)
|
|
27
|
+
return err('#DIV/0!');
|
|
28
|
+
return ns.reduce((x, y) => x + y, 0) / ns.length;
|
|
29
|
+
}
|
|
30
|
+
function roundTo(value, digits) {
|
|
31
|
+
const f = Math.pow(10, digits);
|
|
32
|
+
// Scale, round, unscale. The epsilon nudge keeps 1.005 -> 1.01 rather than
|
|
33
|
+
// 1.00, which is the binary-float surprise users report as a bug.
|
|
34
|
+
return Math.round((value * f) * (1 + Number.EPSILON)) / f;
|
|
35
|
+
}
|
|
36
|
+
function toDate(v) {
|
|
37
|
+
if (typeof v === 'number') {
|
|
38
|
+
// Excel serial: day 1 is 1900-01-01, with the famous phantom leap day.
|
|
39
|
+
return new Date(Date.UTC(1899, 11, 30) + v * 86400000);
|
|
40
|
+
}
|
|
41
|
+
const d = new Date(toText(v));
|
|
42
|
+
if (Number.isNaN(d.getTime()))
|
|
43
|
+
throw new FormulaError('#VALUE!');
|
|
44
|
+
return d;
|
|
45
|
+
}
|
|
46
|
+
const iso = (d) => d.toISOString().slice(0, 10);
|
|
47
|
+
/** Sum / count / average over a criterion range, optionally summing a parallel
|
|
48
|
+
* range. The three IF functions differ only in what they do with the hits. */
|
|
49
|
+
function criteriaHits(range, criterion) {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (let i = 0; i < range.length; i += 1) {
|
|
52
|
+
if (matchesCriterion(range[i], criterion))
|
|
53
|
+
out.push(i);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/** SUMIFS / COUNTIFS: every (range, criterion) pair must match at an index. */
|
|
58
|
+
function multiCriteriaHits(pairs) {
|
|
59
|
+
const firstPair = pairs[0];
|
|
60
|
+
if (!firstPair)
|
|
61
|
+
return [];
|
|
62
|
+
const out = [];
|
|
63
|
+
for (let i = 0; i < firstPair[0].length; i += 1) {
|
|
64
|
+
if (pairs.every(([range, crit]) => matchesCriterion(range[i] ?? '', crit)))
|
|
65
|
+
out.push(i);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
export const FUNCTIONS = {
|
|
70
|
+
// ---- Math and aggregation -------------------------------------------
|
|
71
|
+
SUM: (a) => sum(a.flat),
|
|
72
|
+
AVERAGE: (a) => average(a.flat),
|
|
73
|
+
AVG: (a) => average(a.flat),
|
|
74
|
+
MIN: (a) => { const n = numericOnly(a.flat); return n.length ? Math.min(...n) : 0; },
|
|
75
|
+
MAX: (a) => { const n = numericOnly(a.flat); return n.length ? Math.max(...n) : 0; },
|
|
76
|
+
COUNT: (a) => a.flat.filter((v) => typeof v === 'number').length,
|
|
77
|
+
COUNTA: (a) => a.flat.filter((v) => !isBlank(v)).length,
|
|
78
|
+
COUNTBLANK: (a) => a.flat.filter((v) => isBlank(v)).length,
|
|
79
|
+
ABS: (a) => Math.abs(toNumber(first(a))),
|
|
80
|
+
INT: (a) => Math.floor(toNumber(first(a))),
|
|
81
|
+
MOD: (a) => {
|
|
82
|
+
const d = toNumber(nth(a, 1));
|
|
83
|
+
if (d === 0)
|
|
84
|
+
return err('#DIV/0!');
|
|
85
|
+
// Excel's MOD follows the sign of the divisor, unlike JavaScript's %.
|
|
86
|
+
const n = toNumber(nth(a, 0));
|
|
87
|
+
return n - d * Math.floor(n / d);
|
|
88
|
+
},
|
|
89
|
+
POWER: (a) => Math.pow(toNumber(nth(a, 0)), toNumber(nth(a, 1))),
|
|
90
|
+
SQRT: (a) => {
|
|
91
|
+
const n = toNumber(first(a));
|
|
92
|
+
return n < 0 ? err('#NUM!') : Math.sqrt(n);
|
|
93
|
+
},
|
|
94
|
+
ROUND: (a) => roundTo(toNumber(nth(a, 0)), Math.round(toNumber(nth(a, 1) || 0))),
|
|
95
|
+
ROUNDUP: (a) => {
|
|
96
|
+
const d = Math.round(toNumber(nth(a, 1) || 0));
|
|
97
|
+
const f = Math.pow(10, d);
|
|
98
|
+
const v = toNumber(nth(a, 0));
|
|
99
|
+
return (v < 0 ? -Math.ceil(-v * f) : Math.ceil(v * f)) / f;
|
|
100
|
+
},
|
|
101
|
+
ROUNDDOWN: (a) => {
|
|
102
|
+
const d = Math.round(toNumber(nth(a, 1) || 0));
|
|
103
|
+
const f = Math.pow(10, d);
|
|
104
|
+
const v = toNumber(nth(a, 0));
|
|
105
|
+
return (v < 0 ? -Math.floor(-v * f) : Math.floor(v * f)) / f;
|
|
106
|
+
},
|
|
107
|
+
MEDIAN: (a) => {
|
|
108
|
+
const n = numericOnly(a.flat).sort((x, y) => x - y);
|
|
109
|
+
if (!n.length)
|
|
110
|
+
return err('#NUM!');
|
|
111
|
+
const mid = Math.floor(n.length / 2);
|
|
112
|
+
return n.length % 2 ? n[mid] : (n[mid - 1] + n[mid]) / 2;
|
|
113
|
+
},
|
|
114
|
+
STDEV: (a) => {
|
|
115
|
+
const n = numericOnly(a.flat);
|
|
116
|
+
if (n.length < 2)
|
|
117
|
+
return err('#DIV/0!');
|
|
118
|
+
const mean = n.reduce((x, y) => x + y, 0) / n.length;
|
|
119
|
+
const variance = n.reduce((acc, v) => acc + (v - mean) ** 2, 0) / (n.length - 1);
|
|
120
|
+
return Math.sqrt(variance);
|
|
121
|
+
},
|
|
122
|
+
RANK: (a) => {
|
|
123
|
+
const value = toNumber(nth(a, 0));
|
|
124
|
+
const pool = numericOnly(a.args[1] ?? []);
|
|
125
|
+
const ascending = a.args[2] !== undefined && toBool(nth(a, 2));
|
|
126
|
+
const sorted = pool.slice().sort((x, y) => (ascending ? x - y : y - x));
|
|
127
|
+
const at = sorted.indexOf(value);
|
|
128
|
+
return at < 0 ? err('#N/A') : at + 1;
|
|
129
|
+
},
|
|
130
|
+
// ---- Conditional aggregation ----------------------------------------
|
|
131
|
+
SUMIF: (a) => {
|
|
132
|
+
const range = a.args[0] ?? [];
|
|
133
|
+
const hits = criteriaHits(range, nth(a, 1));
|
|
134
|
+
// The optional third argument is the range actually summed.
|
|
135
|
+
const target = a.args[2] ?? range;
|
|
136
|
+
return sum(hits.map((i) => target[i] ?? ''));
|
|
137
|
+
},
|
|
138
|
+
COUNTIF: (a) => criteriaHits(a.args[0] ?? [], nth(a, 1)).length,
|
|
139
|
+
AVERAGEIF: (a) => {
|
|
140
|
+
const range = a.args[0] ?? [];
|
|
141
|
+
const hits = criteriaHits(range, nth(a, 1));
|
|
142
|
+
const target = a.args[2] ?? range;
|
|
143
|
+
return average(hits.map((i) => target[i] ?? ''));
|
|
144
|
+
},
|
|
145
|
+
SUMIFS: (a) => {
|
|
146
|
+
const target = a.args[0] ?? [];
|
|
147
|
+
const pairs = [];
|
|
148
|
+
for (let i = 1; i + 1 < a.args.length + 1; i += 2) {
|
|
149
|
+
const range = a.args[i];
|
|
150
|
+
if (!range)
|
|
151
|
+
break;
|
|
152
|
+
pairs.push([range, a.args[i + 1]?.[0] ?? '']);
|
|
153
|
+
}
|
|
154
|
+
return sum(multiCriteriaHits(pairs).map((i) => target[i] ?? ''));
|
|
155
|
+
},
|
|
156
|
+
COUNTIFS: (a) => {
|
|
157
|
+
const pairs = [];
|
|
158
|
+
for (let i = 0; i < a.args.length; i += 2) {
|
|
159
|
+
const range = a.args[i];
|
|
160
|
+
if (!range)
|
|
161
|
+
break;
|
|
162
|
+
pairs.push([range, a.args[i + 1]?.[0] ?? '']);
|
|
163
|
+
}
|
|
164
|
+
return multiCriteriaHits(pairs).length;
|
|
165
|
+
},
|
|
166
|
+
// ---- Logical ---------------------------------------------------------
|
|
167
|
+
NOT: (a) => !toBool(first(a)),
|
|
168
|
+
AND: (a) => a.flat.every((v) => toBool(v)),
|
|
169
|
+
OR: (a) => a.flat.some((v) => toBool(v)),
|
|
170
|
+
XOR: (a) => a.flat.filter((v) => toBool(v)).length % 2 === 1,
|
|
171
|
+
// ---- Information -----------------------------------------------------
|
|
172
|
+
// What a value IS, not what it can be coerced to: "12" typed as text is
|
|
173
|
+
// text here, the way Excel answers, and a blank is neither.
|
|
174
|
+
ISNUMBER: (a) => typeof first(a) === 'number',
|
|
175
|
+
ISTEXT: (a) => typeof first(a) === 'string' && first(a) !== '',
|
|
176
|
+
ISLOGICAL: (a) => typeof first(a) === 'boolean',
|
|
177
|
+
ISBLANK: (a) => first(a) === '',
|
|
178
|
+
// ---- Text ------------------------------------------------------------
|
|
179
|
+
LEN: (a) => toText(first(a)).length,
|
|
180
|
+
LEFT: (a) => toText(nth(a, 0)).slice(0, Math.max(0, Math.round(toNumber(a.args[1] ? nth(a, 1) : 1)))),
|
|
181
|
+
RIGHT: (a) => {
|
|
182
|
+
const s = toText(nth(a, 0));
|
|
183
|
+
const n = Math.max(0, Math.round(toNumber(a.args[1] ? nth(a, 1) : 1)));
|
|
184
|
+
return n >= s.length ? s : s.slice(s.length - n);
|
|
185
|
+
},
|
|
186
|
+
MID: (a) => {
|
|
187
|
+
const s = toText(nth(a, 0));
|
|
188
|
+
const start = Math.round(toNumber(nth(a, 1)));
|
|
189
|
+
if (start < 1)
|
|
190
|
+
return err('#VALUE!');
|
|
191
|
+
return s.slice(start - 1, start - 1 + Math.max(0, Math.round(toNumber(nth(a, 2)))));
|
|
192
|
+
},
|
|
193
|
+
UPPER: (a) => toText(first(a)).toUpperCase(),
|
|
194
|
+
LOWER: (a) => toText(first(a)).toLowerCase(),
|
|
195
|
+
TRIM: (a) => toText(first(a)).trim().replace(/\s+/g, ' '),
|
|
196
|
+
CONCAT: (a) => a.flat.map((v) => toText(v)).join(''),
|
|
197
|
+
CONCATENATE: (a) => a.flat.map((v) => toText(v)).join(''),
|
|
198
|
+
TEXTJOIN: (a) => {
|
|
199
|
+
const sep = toText(nth(a, 0));
|
|
200
|
+
const skipEmpty = toBool(nth(a, 1));
|
|
201
|
+
const rest = a.args.slice(2).flat();
|
|
202
|
+
return rest.filter((v) => !skipEmpty || !isBlank(v)).map((v) => toText(v)).join(sep);
|
|
203
|
+
},
|
|
204
|
+
SUBSTITUTE: (a) => {
|
|
205
|
+
const s = toText(nth(a, 0));
|
|
206
|
+
const find = toText(nth(a, 1));
|
|
207
|
+
const replace = toText(nth(a, 2));
|
|
208
|
+
if (find === '')
|
|
209
|
+
return s;
|
|
210
|
+
return s.split(find).join(replace);
|
|
211
|
+
},
|
|
212
|
+
FIND: (a) => {
|
|
213
|
+
// Case sensitive, 1-based, #VALUE! when absent. SEARCH is its
|
|
214
|
+
// case-insensitive twin.
|
|
215
|
+
const at = toText(nth(a, 1)).indexOf(toText(nth(a, 0)));
|
|
216
|
+
return at < 0 ? err('#VALUE!') : at + 1;
|
|
217
|
+
},
|
|
218
|
+
SEARCH: (a) => {
|
|
219
|
+
const at = toText(nth(a, 1)).toLowerCase().indexOf(toText(nth(a, 0)).toLowerCase());
|
|
220
|
+
return at < 0 ? err('#VALUE!') : at + 1;
|
|
221
|
+
},
|
|
222
|
+
TEXT: (a) => {
|
|
223
|
+
// Minimal: the full Excel format grammar arrives with per-cell number
|
|
224
|
+
// formats. Until then this covers the common fixed-decimal case.
|
|
225
|
+
const v = toNumber(nth(a, 0));
|
|
226
|
+
const pattern = toText(nth(a, 1));
|
|
227
|
+
const decimals = /\.(0+)/.exec(pattern)?.[1]?.length ?? 0;
|
|
228
|
+
const body = v.toFixed(decimals);
|
|
229
|
+
if (pattern.includes(',')) {
|
|
230
|
+
const [int = '', frac] = body.split('.');
|
|
231
|
+
const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
232
|
+
return frac ? `${grouped}.${frac}` : grouped;
|
|
233
|
+
}
|
|
234
|
+
return body;
|
|
235
|
+
},
|
|
236
|
+
// ---- Date ------------------------------------------------------------
|
|
237
|
+
TODAY: () => iso(new Date()),
|
|
238
|
+
NOW: () => new Date().toISOString().slice(0, 19).replace('T', ' '),
|
|
239
|
+
YEAR: (a) => toDate(first(a)).getUTCFullYear(),
|
|
240
|
+
MONTH: (a) => toDate(first(a)).getUTCMonth() + 1,
|
|
241
|
+
DAY: (a) => toDate(first(a)).getUTCDate(),
|
|
242
|
+
DATE: (a) => iso(new Date(Date.UTC(Math.round(toNumber(nth(a, 0))), Math.round(toNumber(nth(a, 1))) - 1, Math.round(toNumber(nth(a, 2)))))),
|
|
243
|
+
EOMONTH: (a) => {
|
|
244
|
+
const d = toDate(nth(a, 0));
|
|
245
|
+
const months = Math.round(toNumber(nth(a, 1)));
|
|
246
|
+
// Day 0 of the following month is the last day of the target month.
|
|
247
|
+
return iso(new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + months + 1, 0)));
|
|
248
|
+
},
|
|
249
|
+
// DAYS(end, start): whole days, negative when the end comes first.
|
|
250
|
+
DAYS: (a) => Math.round((toDate(nth(a, 0)).getTime() - toDate(nth(a, 1)).getTime()) / 86400000),
|
|
251
|
+
// DATEDIF(start, end, unit): Excel's "d", "m" and "y", completed units
|
|
252
|
+
// only, and #NUM! when the start comes after the end, as Excel gives.
|
|
253
|
+
DATEDIF: (a) => {
|
|
254
|
+
const start = toDate(nth(a, 0));
|
|
255
|
+
const end = toDate(nth(a, 1));
|
|
256
|
+
if (end.getTime() < start.getTime())
|
|
257
|
+
return err('#NUM!');
|
|
258
|
+
const unit = toText(nth(a, 2)).toUpperCase();
|
|
259
|
+
if (unit === 'D')
|
|
260
|
+
return Math.floor((end.getTime() - start.getTime()) / 86400000);
|
|
261
|
+
let months = (end.getUTCFullYear() - start.getUTCFullYear()) * 12 + (end.getUTCMonth() - start.getUTCMonth());
|
|
262
|
+
if (end.getUTCDate() < start.getUTCDate())
|
|
263
|
+
months -= 1;
|
|
264
|
+
if (unit === 'M')
|
|
265
|
+
return months;
|
|
266
|
+
if (unit === 'Y')
|
|
267
|
+
return Math.floor(months / 12);
|
|
268
|
+
return err('#NUM!');
|
|
269
|
+
},
|
|
270
|
+
// ---- Lookup ----------------------------------------------------------
|
|
271
|
+
VLOOKUP: (a) => {
|
|
272
|
+
const needle = nth(a, 0);
|
|
273
|
+
const grid = a.grids[1];
|
|
274
|
+
if (!grid)
|
|
275
|
+
return err('#REF!');
|
|
276
|
+
const col = Math.round(toNumber(nth(a, 2)));
|
|
277
|
+
if (col < 1)
|
|
278
|
+
return err('#VALUE!');
|
|
279
|
+
for (const row of grid) {
|
|
280
|
+
if (row[0] !== undefined && looseEquals(row[0], needle)) {
|
|
281
|
+
const cell = row[col - 1];
|
|
282
|
+
return cell === undefined ? err('#REF!') : cell;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return err('#N/A');
|
|
286
|
+
},
|
|
287
|
+
HLOOKUP: (a) => {
|
|
288
|
+
const needle = nth(a, 0);
|
|
289
|
+
const grid = a.grids[1];
|
|
290
|
+
if (!grid)
|
|
291
|
+
return err('#REF!');
|
|
292
|
+
const rowIndex = Math.round(toNumber(nth(a, 2)));
|
|
293
|
+
if (rowIndex < 1)
|
|
294
|
+
return err('#VALUE!');
|
|
295
|
+
const header = grid[0] ?? [];
|
|
296
|
+
for (let c = 0; c < header.length; c += 1) {
|
|
297
|
+
if (looseEquals(header[c], needle)) {
|
|
298
|
+
const cell = grid[rowIndex - 1]?.[c];
|
|
299
|
+
return cell === undefined ? err('#REF!') : cell;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return err('#N/A');
|
|
303
|
+
},
|
|
304
|
+
MATCH: (a) => {
|
|
305
|
+
const needle = nth(a, 0);
|
|
306
|
+
const pool = a.args[1] ?? [];
|
|
307
|
+
const mode = a.args[2] ? Math.round(toNumber(nth(a, 2))) : 1;
|
|
308
|
+
if (mode === 0) {
|
|
309
|
+
const at = pool.findIndex((v) => looseEquals(v, needle));
|
|
310
|
+
return at < 0 ? err('#N/A') : at + 1;
|
|
311
|
+
}
|
|
312
|
+
// Ordered search: the last value not past the needle.
|
|
313
|
+
let best = -1;
|
|
314
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
315
|
+
const cmp = compare(pool[i], needle);
|
|
316
|
+
if (mode === 1 ? cmp <= 0 : cmp >= 0)
|
|
317
|
+
best = i;
|
|
318
|
+
}
|
|
319
|
+
return best < 0 ? err('#N/A') : best + 1;
|
|
320
|
+
},
|
|
321
|
+
INDEX: (a) => {
|
|
322
|
+
const grid = a.grids[0];
|
|
323
|
+
if (!grid) {
|
|
324
|
+
const at = Math.round(toNumber(nth(a, 1)));
|
|
325
|
+
const v = (a.args[0] ?? [])[at - 1];
|
|
326
|
+
return v === undefined ? err('#REF!') : v;
|
|
327
|
+
}
|
|
328
|
+
const given = Math.round(toNumber(nth(a, 1)));
|
|
329
|
+
// With one number, a one-column range indexes by row and a one-row range
|
|
330
|
+
// by column, as Excel does: =INDEX(B4:D4, 2) is the second scenario
|
|
331
|
+
// heading, not #REF!.
|
|
332
|
+
const oneRow = grid.length === 1 && !a.args[2];
|
|
333
|
+
const rowIndex = oneRow ? 1 : given;
|
|
334
|
+
const colIndex = oneRow ? given : a.args[2] ? Math.round(toNumber(nth(a, 2))) : 1;
|
|
335
|
+
const row = grid[rowIndex - 1];
|
|
336
|
+
if (!row)
|
|
337
|
+
return err('#REF!');
|
|
338
|
+
const cell = row[colIndex - 1];
|
|
339
|
+
return cell === undefined ? err('#REF!') : cell;
|
|
340
|
+
},
|
|
341
|
+
XLOOKUP: (a) => {
|
|
342
|
+
const needle = nth(a, 0);
|
|
343
|
+
const haystack = a.args[1] ?? [];
|
|
344
|
+
const results = a.args[2] ?? [];
|
|
345
|
+
const at = haystack.findIndex((v) => looseEquals(v, needle));
|
|
346
|
+
if (at < 0)
|
|
347
|
+
return a.args[3] ? nth(a, 3) : err('#N/A');
|
|
348
|
+
const cell = results[at];
|
|
349
|
+
return cell === undefined ? err('#REF!') : cell;
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
/** Merge caller-supplied functions over the built-ins. Keys are uppercased so
|
|
353
|
+
* a consumer can register `myFn` and write `=MYFN()`. */
|
|
354
|
+
export function withCustomFunctions(custom) {
|
|
355
|
+
if (!custom)
|
|
356
|
+
return FUNCTIONS;
|
|
357
|
+
const out = { ...FUNCTIONS };
|
|
358
|
+
for (const [name, fn] of Object.entries(custom))
|
|
359
|
+
out[name.toUpperCase()] = fn;
|
|
360
|
+
return out;
|
|
361
|
+
}
|
|
362
|
+
export { isError };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal Seek: find the input value that makes a formula cell hit a target.
|
|
3
|
+
*
|
|
4
|
+
* "What interest rate makes the monthly payment 1500?" You know the answer
|
|
5
|
+
* you want and one cell you are willing to change; the solver finds it.
|
|
6
|
+
*
|
|
7
|
+
* The method is secant with a bisection fallback, not Newton. Newton needs a
|
|
8
|
+
* derivative, and the function here is "recalculate a spreadsheet", which has
|
|
9
|
+
* no analytic one. Secant approximates the slope from two evaluations, which
|
|
10
|
+
* is the same information a numerical derivative would cost anyway.
|
|
11
|
+
*
|
|
12
|
+
* Bisection is the fallback because secant is fast but not safe: it can step
|
|
13
|
+
* to infinity on a flat stretch or oscillate on a kink. When a bracket is
|
|
14
|
+
* known - two inputs whose results straddle the target - bisection cannot
|
|
15
|
+
* fail, only be slow. Trying secant first and falling back keeps the common
|
|
16
|
+
* case quick and the awkward case terminating.
|
|
17
|
+
*/
|
|
18
|
+
export type GoalSeekOptions = {
|
|
19
|
+
/** Stop once the result is this close to the target. */
|
|
20
|
+
tolerance?: number;
|
|
21
|
+
/** Give up after this many recalculations. */
|
|
22
|
+
maxIterations?: number;
|
|
23
|
+
/** Where to start looking. Defaults to the input cell's current value. */
|
|
24
|
+
initialGuess?: number;
|
|
25
|
+
/** Keep the answer inside these bounds. A rate solver wants [0, 1]. */
|
|
26
|
+
min?: number;
|
|
27
|
+
max?: number;
|
|
28
|
+
};
|
|
29
|
+
export type GoalSeekResult = {
|
|
30
|
+
/** Whether the target was reached within tolerance. */
|
|
31
|
+
converged: boolean;
|
|
32
|
+
/** The input value found. Present even when it did not converge, so a
|
|
33
|
+
* caller can show the closest attempt rather than nothing. */
|
|
34
|
+
value: number;
|
|
35
|
+
/** What the formula produced at that input. */
|
|
36
|
+
result: number;
|
|
37
|
+
iterations: number;
|
|
38
|
+
/** Why it stopped, when it did not converge. */
|
|
39
|
+
reason?: 'maxIterations' | 'notNumeric' | 'flat' | 'outOfBounds';
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Solve `evaluate(input) = target` for `input`.
|
|
43
|
+
*
|
|
44
|
+
* `evaluate` sets the input cell, recalculates, and returns the formula
|
|
45
|
+
* cell's value. It is called many times, so it should be the workbook's own
|
|
46
|
+
* recalculation rather than anything that touches the DOM.
|
|
47
|
+
*
|
|
48
|
+
* The caller owns the input cell: this never writes. It reports the value it
|
|
49
|
+
* found and lets the caller decide whether to keep it, which is what makes
|
|
50
|
+
* Excel's "Goal Seek found a solution / OK or Cancel" dialog possible.
|
|
51
|
+
*/
|
|
52
|
+
export declare function goalSeek(evaluate: (input: number) => unknown, target: number, start: number, options?: GoalSeekOptions): GoalSeekResult;
|
|
53
|
+
/** What `goalSeekCell` needs of a workbook. */
|
|
54
|
+
export type GoalSeekSheet = {
|
|
55
|
+
getRaw(sheet: string, row: number, col: number): string;
|
|
56
|
+
setRaw(sheet: string, row: number, col: number, text: string): void;
|
|
57
|
+
getValue(sheet: string, row: number, col: number): unknown;
|
|
58
|
+
};
|
|
59
|
+
export type CellAddress = {
|
|
60
|
+
sheet: string;
|
|
61
|
+
row: number;
|
|
62
|
+
col: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Goal Seek over a workbook: change `input` until `formula` reads `target`.
|
|
66
|
+
*
|
|
67
|
+
* The input cell is RESTORED before returning, whatever the outcome. The
|
|
68
|
+
* solver writes to it dozens of times while searching, and leaving the last
|
|
69
|
+
* probe behind would be worse than not running: Excel shows you the answer
|
|
70
|
+
* and asks before keeping it, which it cannot do if the sheet has already
|
|
71
|
+
* moved. Apply `result.value` yourself once the user says yes.
|
|
72
|
+
*/
|
|
73
|
+
export declare function goalSeekCell(book: GoalSeekSheet, formula: CellAddress, input: CellAddress, target: number, options?: GoalSeekOptions): GoalSeekResult;
|