资讯动态

Univer Sheets 公式集成插件 @univerjs/sheets-formula 深度解析:安装、注册与计算流程

发布时间:2026/9/14 14:46:23 来源:尧图企业网站定制
Univer Sheets 公式集成插件 univerjs/sheets-formula 深度解析安装、注册与计算流程【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univerUniver 的全栈架构把「公式引擎」与「表格业务」拆分为两个独立的包univerjs/engine-formula负责公式的解析、依赖树构建与计算而本文主角univerjs/sheets-formula负责把公式引擎接入 Univer Sheets提供公式数据服务、依赖处理与工作表感知的计算调度。读完本文你将掌握该插件的安装注册方式、初始化计算模式配置、内置命令与 Facade API 用法以及本地/远程两种插件形态的源码级工作原理。包概览与定位univerjs/sheets-formula位于仓库 packages/sheets-formula其核心定位在包内 README 中一句话概括连接公式引擎与 Univer Sheets包括公式数据服务formula data services、依赖处理dependency handling与面向工作表的计算sheet-aware calculation。其包级能力对照如下与 README 中 Package Overview 表一致项值包名univerjs/sheets-formulaUMD 全局变量UniverSheetsFormulaCSS无纯逻辑层不输出样式Locales有提供计算进度等 UI 文案Facade 入口有univerjs/sheets-formula/facade从 package.json 可以看到它的直接依赖集中在三个核心包上univerjs/core插件与 DI 基础设施、univerjs/engine-formula公式引擎、univerjs/sheets表格核心同时依赖univerjs/docs与univerjs/rpc后者正是远程插件实现 RPC 通道的基础。exports字段暴露了./locale/*语言包与./facadeFacade 扩展两个子路径这解释了 README 中 locale 与 Facade 的用法来源。安装与版本一致性按 README 的安装方式使用你熟悉的包管理器即可pnpm add univerjs/sheets-formula # 或 npm install univerjs/sheets-formulaREADME 特别强调一条集成铁律所有univerjs/*包必须保持同一版本。这一点在 package.json 的依赖声明中有迹可循——它通过workspace:*引用univerjs/core、univerjs/engine-formula、univerjs/sheets等同仓库包多包之间通过内部协议Mutation、Service、DI token深度耦合版本漂移极易引发兼容问题。当前仓库中该包版本为1.0.0-beta.2。插件注册与 Locale 合并README 给出的最小使用示例import EnUS from univerjs/sheets-formula/locale/en-US; import { UniverSheetsFormulaPlugin } from univerjs/sheets-formula; univer.registerPlugin(UniverSheetsFormulaPlugin); // 当此包贡献 UI 文案时把 EnUS 合并进你的 Univer locale 映射两点说明Locale 是可选但推荐的该包本身是纯逻辑插件但在公式计算耗时超过阈值时会展示进度文案如 Analyzing formulas...、Calculating array formulas...这些文案来自 src/locale 下的语言包。仓库当前维护了 20 种语言包括 en-US、zh-CN、zh-TW、zh-HK、ja-JP、ko-KR、de-DE、fr-FR、ru-RU 等包名与语言一一对应如univerjs/sheets-formula/locale/zh-CN。插件名称与类型从 plugin.ts 源码可见UniverSheetsFormulaPlugin的pluginName为SHEET_FORMULA_PLUGIN_NAMESHEET_FORMULA_PLUGINtype为UniverInstanceType.UNIVER_SHEET即它只服务于工作表类型实例。README 的导出插件类清单为两个UniverSheetsFormulaPlugin标准插件完整接入公式引擎与表格业务UniverRemoteSheetsFormulaPlugin远程RPC形态注册RemoteRegisterFunctionService到 RPC 通道供主线程侧代理自定义函数注册。集成顺序必须先注册引擎与表格README 的 Integration Notes 给出关键约束Register this package withuniverjs/engine-formulaanduniverjs/sheetsbefore adding formula UI packages.这句话包含两层意思依赖前置UniverSheetsFormulaPlugin通过装饰器DependentOn(UniverFormulaEnginePlugin, UniverSheetsPlugin)声明依赖plugin.ts而UniverRemoteSheetsFormulaPlugin仅依赖DependentOn(UniverFormulaEnginePlugin)plugin.ts。注册顺序上必须先注册univerjs/engine-formula的UniverFormulaEnginePlugin与univerjs/sheets的UniverSheetsPlugin。UI 包后置诸如公式编辑栏、函数插入面板等 UI 能力属于univerjs/sheets-formula-ui等更上层包它们依赖本包提供的数据与计算能力因此本包应在 UI 包之前注册。一个典型的注册顺序示例univer.registerPlugin(UniverSheetsFormulaEnginePlugin); // univerjs/engine-formula univer.registerPlugin(UniverSheetsPlugin); // univerjs/sheets univer.registerPlugin(UniverSheetsFormulaPlugin); // univerjs/sheets-formula // 之后才注册公式相关 UI 包源码级原理插件的生命周期与依赖装配理解本包最有价值的是看它在插件生命周期各阶段做了什么plugin.ts构造阶段将用户配置与defaultPluginBaseConfig合并后通过IConfigService.setConfig(PLUGIN_CONFIG_KEY_BASE, rest, { merge: true })写入配置服务配置键为sheets-formula.base.config见 config/config.ts。onStarting注册 12 个控制器/服务依赖Dependency[]其中包括FormulaController、FormulaRefRangeService、ArrayFormulaCellInterceptorController、ImageFormulaCellInterceptorController、TriggerCalculationController、UpdateFormulaController、ActiveDirtyController、DefinedNameController、UpdateDefinedNameController、SuperTableController、FormulaAutoFillController、UnitQualifierRenameController、SheetFormulaCalculationResultApplyController。若配置了notExecuteFormula还会额外注入IRemoteRegisterFunctionService的 RPC 代理。若配置了description会调用IDescriptionService.registerDescriptions注册函数描述。onReadytouchDependencies主动实例化计算链路相关控制器在 Node 环境isNodeEnv()额外初始化TriggerCalculationController因为无渲染环境无法等待渲染完成。onRendered实例化DefinedNameController、SuperTableController浏览器环境在此阶段才初始化TriggerCalculationController——等待渲染完成后再启动公式计算。这一套「延迟 touch 分阶段初始化」的设计确保公式计算不会阻塞首屏渲染也体现了该包在univerjs/engine-formula与univerjs/sheets之间的桥接职责。初始化计算模式配置IUniverSheetsFormulaBaseConfig提供四个可选配置项config/config.ts配置项类型说明notExecuteFormulaboolean为true时本端不执行公式计算改为通过 RPC 委托远程计算器执行自定义函数需同步到远端descriptionIFunctionInfo[]注册到描述服务的函数元信息供公式 UI 展示参数说明等functionArray[CtorBaseFunction, IFunctionNames]自定义函数的构造器与名称映射initialFormulaComputingCalculationMode初始化时的计算模式默认WHEN_EMPTY其中CalculationMode枚举的三种语义在源码注释中定义得十分清晰enum CalculationMode { FORCED, // 强制计算所有公式 WHEN_EMPTY, // 部分计算仅计算没有 v 值的公式单元格 NO_CALCULATION // 不计算任何公式 }这三种模式的实际调度逻辑位于 trigger-calculation.controller.ts 的_initialExecuteFormula与_getDirtyDataByCalculationModeNO_CALCULATION直接跳过初始计算 MutationWHEN_EMPTY会从FormulaDataModel.getFormulaDirtyRanges()取得需要重算的脏区间仅对这些区间发起SetTriggerFormulaCalculationStartMutationFORCED会以forceCalculation: true构建脏数据dirtyRanges为空让引擎全量重算。通过 Facade 动态修改计算模式除了注册插件时传配置还可通过 Facade API 在运行时修改univerAPI.getFormula().setInitialFormulaComputing(0)参数即CalculationMode枚举值。需要留意的是f-formula.ts 中的实现会在Starting生命周期之后调用时打印 warning——该配置只影响下次Univer Sheet 构建时的初始化数据计算当前已构建的实例不会立即重算。内置命令插入函数与快速求和FormulaControllerformula.controller.ts在构造时向ICommandService注册两个命令InsertFunctionCommand命令 id 为formula.command.insert-functioninsert-function.command.ts。其核心逻辑值得展开参数list中的每个IInsertFunction包含range函数作用范围、primary主单元格行列、formula公式字符串对每个函数项在主单元格写入{ f: formula, si: formulaId }其中si是generateRandomId(6)生成的共享公式 ID范围内其余单元格仅写入{ si: formulaId }形成「主单元格定义公式、其余单元格共享引用」的数组公式结构对listOfRangeHasNumber范围内已有数值的情形只写主单元格公式避免覆盖既有数据最终统一通过SetRangeValuesCommand落盘保证命令可撤销、可进入历史栈。QuickSumCommand命令 id 为sheets-formula.command.quick-sumquick-sum.command.ts模拟 Excel 的自动求和Alt体验取当前选区SheetsSelectionsService.getCurrentLastSelection()定位第一个非空单元格通过alignToMergedCellsBorders处理合并单元格边界expandToContinuousRange向四周扩展到连续数据区域在数据区域右侧最后一列与下方最后一行对每个空单元格生成SUM(起始行:当前行-1)或SUM(起始列:当前列-1)公式通过sequenceExecuteAsync依次执行SetRangeValuesCommand与SetSelectionsOperation把选区更新到公式区域。两个命令均有对应单测commands/tests下的insert-function.command.spec.ts与quick-sum.command.spec.ts可作行为参考。Facade API注册自定义函数本包通过 Facade 扩展把自定义函数能力暴露给用户入口为univerjs/sheets-formula/facadefacade/index.ts 聚合了 f-formula、f-enum、f-workbook、f-range 四个扩展。其机制是FFormula.extend(FFormulaSheetsMixin)并声明模块合并让univerAPI.getFormula()直接获得以下能力registerFunction同步函数const formulaEngine univerAPI.getFormula(); // 注册一个问候函数 formulaEngine.registerFunction( HELLO, (name) Hello, ${name}!, A simple greeting function ); // 在单元格中调用 const fWorkbook univerAPI.getActiveWorkbook(); const fWorksheet fWorkbook.getSheetByName(Sheet1); const cellA1 fWorksheet.getRange(A1); cellA1.setValue(World); const cellA2 fWorksheet.getRange(A2); cellA2.setValue({ f: HELLO(A1) });Facade 的registerFunction支持三种重载仅名称实现、带字符串描述、带{ locales, description }对象以提供多语言函数描述。注册成功后内部调用IRegisterFunctionService.registerFunction并触发一次防抖 10ms 的强制公式重算SetTriggerFormulaCalculationStartMutationwithforceCalculation: true保证新函数立即生效返回的IDisposable可在销毁时注销函数。registerAsyncFunction异步函数异步自定义函数适用于请求后端数据等场景formulaEngine.registerAsyncFunction( RANDOM_DELAYED, async () { await new Promise(resolve setTimeout(resolve, 500)); return Math.random(); }, Mock a random number generation function ); fWorksheet.getRange(A1).setValue({ f: RANDOM_DELAYED() });源码实现与同步版一致区别仅在于调用registerAsyncFunction走异步注册通道f-formula.ts。在单元格写入公式Facade 用例中反复出现cell.setValue({ f: ... })这是 Univer 标准公式写入方式——单元格数据的f字段即公式字符串计算引擎异步求值后回填v值。若需在计算结束后读取结果可订阅formulaEngine.calculationEnd(...)其中functionsExecutedState 3FormulaExecutedStateType.SUCCESS表示计算成功。远程插件notExecuteFormula 与 RPC 代理UniverRemoteSheetsFormulaPlugin是远程形态的实现其机制值得单独说明plugin.tsonStarting中向注入器添加RemoteRegisterFunctionService并通过IRPCChannelService.registerChannel以通道名sheets-formula.remote-register-function.service暴露给远端而UniverSheetsFormulaPlugin在notExecuteFormula: true时会用toModule(...)创建一个指向该 RPC 通道的代理注入IRemoteRegisterFunctionService——本地不再执行计算而是把自定义函数注册请求转发给远程计算进程。从 remote-register-function.service.ts 可以看到该服务提供了registerFunctions、registerAsyncFunctions、unregisterFunctions三个方法但注册方法出于安全考虑直接抛错注释明确Remote custom function registration is disabled because function deserialization over RPC is unsafe.即禁止通过 RPC 反序列化执行任意代码仅unregisterFunctions可正常注销。这说明该远程通道当前主要用于公式计算结果的回传自定义函数的跨进程注册被刻意限制——这是重要的安全边界集成远程计算方案时务必留意。计算进度与通知本包还负责把引擎的计算进度翻译成可感知的 UI 状态。TriggerCalculationController通过监听SetFormulaCalculationNotificationMutation按FormulaExecuteStageType的不同阶段START、CURRENTLY_CALCULATING、START_DEPENDENCY_ARRAY_FORMULA、CURRENTLY_CALCULATING_ARRAY_FORMULA维护一个BehaviorSubjectICalculationProgressprogress$对外暴露{ done, count, label }计算总时长超过1 秒才显示进度条内部用 1000ms 定时器控制标签文案来自 locale 包即前文所述sheets-formula.progress.*analyzing / calculating / array-analysis / array-calculation / done并行多次计算只维护一条进度最后一次完成后才关闭进度。同时该控制器在每次计算前会从IConfigService读取ENGINE_FORMULA_CYCLE_REFERENCE_COUNT循环引用最大迭代次数与ENGINE_FORMULA_RETURN_DEPENDENCY_TREE是否返回依赖树等引擎级配置注入 Mutation 参数并把隐藏行过滤信息FormulaDataModel.getHiddenRowsFiltered()传入引擎保证「隐藏行不参与计算」的表格语义。总结univerjs/sheets-formula是 Univer Sheets 公式能力的「业务层胶水」向上承接univerjs/engine-formula的计算能力与univerjs/sheets的表格数据模型向下为公式 UI 包提供数据服务与命令支撑。掌握它的安装顺序引擎 → 表格 → 本包 → UI 包、初始化计算模式WHEN_EMPTY/FORCED/NO_CALCULATION、内置命令插入函数、快速求和以及 Facade 自定义函数 API即可在 Univer 应用中快速搭建具备完整公式能力的电子表格场景如需远程计算架构则要理解notExecuteFormula与 RPC 代理背后的安全边界。进一步深入可阅读 plugin.ts、trigger-calculation.controller.ts 以及 controllers/tests下的集成测试如sheet-formula-trigger.integration.spec.ts它们展示了完整的计算触发链路与验证方式。【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价