简介
wps加载项自定义函数是指在表格的加载项中注册js函数,可以在表格公式中的调用js函数。
调用方式目前只支持同步式调用, 暂不支持异步调用, 敬请期待。wps 自从12.1.0.20540
版本开始支持加载项自定义函数。
快速入门
创建带有自定义函数的加载项
使用wpsjs create 加载项名字命令来创建表格加载项,并在加载项目录中使用wpsjs debug命令来启动加载项。
创建出的加载项中都有functions.js文件(根据不同的框架放在不同的位置),可以在此文件中添加新的自定义函数。 创建出的加载项中都带有manifest.xml文件,包含自定义函数的命名空间和加载项的元数据。
使用自定义函数
调用自定义函数的语法为命名空间.函数名(参数列表)
- 安装加载项后(需要重启wps)打开et表格
- 点击单元格编辑栏左边的函数图标,打开“插入函数”对话框
- 切换到“用户定义”函数 即可看到所有自定义函数的信息
加载项文件
加载项自定义函数功能依赖于加载项中的以下文件:
manifest.xml
manifest.xml的对自定义函数的主要作用是定义functions.json的uri以及命名空间。如果直接使用wps.AddCustomFunction来注册自定义函数和元数据,那么不需要functions.json和manifest.xml。 manifest.xml需要放在加载项打包目录的根目录,与ribbon.xml文件在同一目录。 确保用wpsjs debug启动加载项后,可以通过http://127.0.0.1:3893/manifest.xml
(3893要改为你的wpsjs服务端口号)访问manifest.xml manifest.xml文件格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<JsPlugin>
<ApiVersion>1.0.0</ApiVersion>
<Name>HelloEt</Name>
<Dwscription>addon Description</Dwscription>
<Functions>
<Uri>/functions.json</Uri>
<Namespace>HelloEt</Namespace>
</Functions>
</JsPlugin>
functions.json
functions.json是描述加载项自定义函数的元数据的文件。如果直接使用wps.AddCustomFunction来注册自定义函数和元数据,那么不需要functions.json。 一般不需要手写functions.json,wpsjs中的vite插件能扫描functions.js并自动生成functions.json。
wps会根据manifest.xml中的Functions.Uri加载functions.json文件。这个例子中,functions.json与manifest.xml在同一文件夹,wps会从http://127.0.0.1:3893/functions.json
加载functions.json文件
字段定义
functions.json的字段定义如下:
字段 | 类型 | 定义 |
---|---|---|
functions | object[] | 自定义函数集合 |
functions[].name | string | 函数名 |
functions[].description | string | 函数帮助信息 |
functions[].result.type | string | 返回值类型 |
functions[].parameters[].name | string | 参数名 |
functions[].parameters[].description | string | 参数帮助信息 |
functions[].parameters[].type | string | 参数类型 |
例子
functions.json例子如下:
{
"functions": [
{
"name": "custom_function",
"parameters": [
{
"name": "arg0",
"description": "支持字符串参数",
"type": "string"
},
{
"name": "arg1",
"description": "支持数值参数",
"type": "number"
},
{
"name": "arg2",
"description": "支持bool参数",
"type": "boolean"
},
{
"name": "arg3",
"description": "",
"type": "any"
},
{
"name": "arg4",
"description": "",
"type": "any"
}
],
"description": "这是一个加载项自定义函数1",
"result": {
"type": "number"
}
}
]
}
functions.js
functions.js文件是一个普通的js文件,要保证主页面加载后这个文件能够被加载。 functions.js可以放在任意位置,可以使用任意文件名,可以使用typescript,只要确保其能够被index.html正确加载,确保其中的wps.AddCustomFunction()可以正常被调用即可。 在有manifest.xml的情况下,wps.AddCustomFunction中的命名空间应该与manifest.xml中的命名空间匹配。
jsdoc
wpsjs能够解析functions.js代码,扫描其中的每一个函数,以及函数的jsdoc注释。来生成functions.json jsdoc注释是以/**
开头的,与普通注释不同
@customfunction
这个注释用来区分自定义函数和其他函数。只有带有@customfunction的函数会被注册为自定义函数
@param
这个注释用来定义参数类型,以及提取参数描述信息 如果要添加普通参数,可以添加注释:@param {string} arg0
- 支持字符串参数 如果要添加可选参数,可以添加注释:@param {string} [arg0]
- 支持字符串参数 如果函数参数声明上带有typescript类型标记,那么wpsjs会优先使用typescript类型标记
@returns
这个注释用来标记返回值类型。 如果函数声明上带有返回值typescript类型标记,那么wpsjs会优先使用typescript类型标记
函数描述
注释中的其他文本会被作为函数描述
函数注册
当使用wpsjs的vite插件来生成functions.json时,vite插件也会自动插入注册api函数的代码。如果不适用vite插件,那么需要手动注册函数
if (wps.AddCustomFunction !== undefined) { // 兼容旧版wps
wps.AddCustomFunction("HelloEt", "custom_function", custom_function)
}
例子
// 如果需要使用vite来自动生成functions.json, 那么需要这些文档注释来描述元数据.
// 如果手动编写functions.json或者直接使用wps.AddCustomFunction来注册自定义函数,那么不需要写jsdoc
/**
* 这是一个加载项自定义函数
* @customfunction
* @param {string} arg0 - 支持字符串参数
* @param {number} arg1 - 支持数值参数
* @param {boolean} arg2 - 支持bool参数
* @returns {number} - 可以设置返回值类型
*/
function custom_function(arg0, arg1, arg2, arg3, arg4) {
let argAndType = (arg) => `${arg}: ${typeof arg}`
let argAndTypeList = [arg0, arg1, arg2, arg3, arg4].map(argAndType)
let message = `这是一个加载项自定义函数HelloEtTextVue(${argAndTypeList.join(', ')})`
console.log(message)
return message
}
// 如果使用vite来自动生成functions.json, 那么旧不需要手动注册函数.
if (wps.AddCustomFunction !== undefined) { // 兼容旧版wps
wps.AddCustomFunction("HelloEt", "custom_function", custom_function)
}
参数类型
目前能接受的参数类型有:
参数类型 | 对应的typescript类型 | 备注 |
---|---|---|
number | number | |
number[][] | number[][] | |
string | string | |
string[][] | string[][] | |
boolean | boolean | |
boolean[][] | boolean[][] | |
any | number|string|boolean | 数据会被转换为基础类型 |
any[][] | (number|string|boolean)[][] | 数据会被转换为基础类型的矩阵 |
object | object | 可以用来传递Range对象 |
自定义函数支持使用可选类型 只需要在类型后面加上?
,或者在jsdoc注释中使用标注可选参数即可
加载项迁移方式
关于如何在旧加载项中添加自定义函数。
最简单的方法是创建一个新的加载项,然后对照新加载项的文件来修改旧加载项。
方法1:用jsapi直接注册函数
wps.AddCustomFunction能够直接注册自定义函数的函数对象以及其元数据。 AddCustomFunction函数 在js代码中直接调用wps.AddCustomFunction,即可注册自定义函数
AddCustomFunction参数 | 类型 | 作用 |
---|---|---|
namesapce | string | 函数命名空间 |
name | string | 函数名 |
func | function | js函数 |
meta | object|undefined | 函数元数据 |
函数元数据
wps.AddCustomFunction的meta参数中的函数元数据类型是js对象类型,其字段是:
字段 | 类型 | 定义 |
---|---|---|
description | string | 函数帮助信息 |
result.type | string | 返回值类型 |
parameters[].name | string | 参数名 |
parameters[].description | string | 参数帮助信息 |
parameters[].type | string | 参数类型 |
例子
if (wps.AddCustomFunction !== undefined) { // 兼容旧版wps
wps.AddCustomFunction("HelloEt", "functionname", function(arg0) {
console.log(`call(${arg0}: ${typeof arg0})`)
return arg0
}, {
description: "",
result: { type: "number[][]" },
parameters: [
{ name: "arg0", type: "number[][]", description: "" },
]
})
}
方法2:手动编辑functions.json
wps加载项加载过程中,会尝试加载加载项的manifest.xml文件,并根据其内容加载functions.json,然后从functinos.json中加载函数元数据
需要编写:
- manifest.xml
- functions.json
- functions.js 中调用wps.AddCustomFunction来注册函数
方法3:借助vite插件
这种方法不再需要开发者手写functions.json,而是利用jsdoc注释以及typescript类型标记来生成functions.json
需要编写:
- manifest.xml
- functions.json
- functions.js 中使用jsdoc注释来描述函数的元数据
- vite.config.js 中需要添加vite插件来扫描functions.js,生成functions.json
wpsjs依赖库
要利用wpsjs来扫描functions.js,就需要安装wpsjs依赖包。安装命令是npm i wpsjs --save-dev wpsjs信息会添加到package.json中的devDependencies里面。 如果要把wpsjs下载到本地目录,那么将package.json中的wpsjs信息改为 “wpsjs”: “file:path/to/npm_wps_jsapi_cli”,然后在加载项目录里面运行npm install
package.json构建脚本
将package.json中的scripts中的所有命令都改成vite命令。这样能让wpsjs命令自动使用vite来启动和打包加载项。
"scripts": {
"dev": "vite --port 3893",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
vite打包配置
修改vite.config.js,添加插件。 如果你的加载还没有使用vite,那么可以用wpsjs create创建新的无框架加载项或者react加载项,参考新加载项的vite.config.js 如果你使用webpack来打包加载项,那你可以从wpsjs/vite_plugins中导入所需函数,用webpack插件来调用wpsjs/vite_plugins中的函数。
- 从wpsjs中导入需要的vite插件
import { functionsScanner, copyFile } from "wpsjs/vite_plugins"
- 把manifest.xml复制到打包目录内 在vite配置中的plugins中添加以下代码:
copyFile({
src: 'manifest.xml',
dest: 'manifest.xml',
}),
- 扫描funcitons.js,生成functions.json 在vite配置中的plugins中添加以下代码:
functionsScanner({
inputJsPath: 'src/components/js/functions.js',
outputJsonPath: 'functions.json',
namespace: 'HelloEt',
}),
functionsScanner插件配置的namespace字段应该与manifest.xml中的Namespace相同。
例子
vite.config.js文件例子(vue):
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { functionsScanner, copyFile } from "wpsjs/vite_plugins"
// https://vitejs.dev/config/
export default defineConfig({
base: './',
plugins: [
copyFile({
src: 'manifest.xml',
dest: 'manifest.xml',
}),
functionsScanner({
inputJsPath: 'src/components/js/functions.js',
outputJsonPath: 'functions.json',
namespace: 'HelloEt',
}),
vue()
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
host: '0.0.0.0'
}
})
常见问题
- wps不支持manifest.xml和functions.json文件的热重载。 如果修改了manifest.xml或者functions.json文件,需要重启wps才能生效。
- wps的加载项热重载时可能导致执行到wps.AddCustomFunction时, js函数无法正确从浏览器传递到主进程。如果遇到这种情况, 请尝试重启wps或者再触发一次加载项了重载。
- wps加载项的自定义函数暂不支持异步调用, 敬请期待。
- 如果启动加载项时报错
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '... node_modules\wpsjs\vite_plugins'
, 说明wpsjs的版本过低, 请升级wpsjs到最新版本。 - 如果wps中自定义函数没有成功注册, 请检查:
- 加载项调试器中的wps.AddCustomFunction是否为undefined, 如果是undefined, 说明您的wps版本过低, 请升级wps到不低于
12.1.0.20540
版本。 - 用curl或者浏览器访问
http://127.0.0.1:3893/manifest.xml
(3893要改为你的wpsjs服务端口号), 来检查manifest.xml是否能够正常访问。 - 用curl或者浏览器访问
http://127.0.0.1:3893/functions.json
(3893要改为你的wpsjs服务端口号, functions.json文件的uri改为你在 manifest.xml中设置的uri), 来检查functions.json是否能够正常访问。 - manifest.xml与vite.config.js中设置的命名空间是否一致。
- 如果手动调用wps.AddCustomFunction来注册函数, 并使用manifest.xml, 两者的自定义函数命名空间是否一致。