目录
一、源码查看
1.1. 入口
查看源码入口可知,传入一个自定义函数数组,它会自动注册到全局和仓库,且含有<n>和<f>属性,并且自定义函数设置在创建工作簿的配置中
// 入口:src/core.js 56行
luckysheet.create = function (setting) {
// 66 行:通用继承,得到新的对象,并继承传入对象的所有可枚举属性
let extendsetting = common_extend(defaultSetting, setting);
// 160 行
functionlist(extendsetting.customFunctions);
}
// 函数详解:src/function/functionlist.js (中文为自己的注释)
const functionlist = function(customFunctions){ // 参数表示传入的自定义函数列表
let _locale = locale(); // 拿到国际化的语言文本对象
// internationalization,get function list
let functionListOrigin = [...getLocalizedFunctionList(_locale.functionlist)]; // 拿到原有的函数列表
// add new property f
for (let i = 0; i < functionListOrigin.length; i++) {
let func = functionListOrigin[i];
func.f = functionImplementation[func.n];
}
// 如果传入了自定义函数数组
if (customFunctions) {
functionListOrigin.push(...customFunctions);
}
// 将函数数组写到数据仓库
Store.functionlist = functionListOrigin;
// get n property
const luckysheet_function = {};
for (let i = 0; i < functionListOrigin.length; i++) {
let func = functionListOrigin[i];
luckysheet_function[func.n] = func;
}
window.luckysheet_function = luckysheet_function; //Mount window for eval() calculation formula
Store.luckysheet_function = luckysheet_function;
}
1.2. 自定义公式可能的参数
在文件src/controllers/insertFormula.js中搜索luckysheet_function、functionlist等内容,可在30行、71行、211行等地方,知道自定义公式可能这样定义
interface customFunctions {
n: string;
p: Array<{
detail: string;
repeat: 'y' | 'n';
name: string;
}>;
d: string;
a: string;
t: string;
}
另外一个文件的源码
// src/global/formula.js 1060 行
//"n": "AVERAGE",
//"t": "1",
//"d": "返回数据集的算术平均值,对文本忽略不计。",
//"a": "返回数据集的算术平均值",
//"p": [{ "name": "数值1", "example": "A2:A100", "detail": "计算平均值时用到的第一个数值或范围。", "require": "m", "repeat": "n", "type": "rangenumber" },
// { "name": "数值2", "example": "B2:B100", "detail": "计算平均值时用到的其他数值或范围。", "require": "o", "repeat": "y", "type": "rangenumber" }
//]
根据上述源码以及页面实际显示的情况,可以完成自定义公式参数的类型定义。
二、TypeScript定义
export type ICustomFunction = {
/**函数名 */
n: string;
/**函数返回类型 */
t: any;
/**函数参数个数 */
m: [number, number];
/**每个参数的描述 */
p: Array<ICustomFunctionArgumentDescription>;
/**
* 公式执行的函数
*
* `this` 指向与函数同级的自定义对象
*/
f: Function;
/**
* 摘要
*
* 进行公式参数编辑时显示的摘要提示
*/
d: string;
/**
* 描述
*
* 输入 "=公式名"的时候显示的提示
*/
a: string;
};
export type ICustomFunctionArgumentDescription = {
/**参数使用示例 */
example: string;
require: /**必填 */"m" | /**选填 */ "o";
/**
* 是否重复
*
* 重复意味着剩余参数都是如此
*/
repeat: /**否 */"n" | /**是 */ "y";
/**参数类型 */
type: TCellFormat_t | 0;
/**参数名 */
name: string;
/**参数文字说明 */
detail: string;
};
三、插入到表格
3.1. 创建表格
import customFunctions from './customFunctions';
const options = {
container: 'luckysheet',
title: '标题',
lang: 'zh',
gridKey: '35as4d#-a6s54we3f1we5f4f3asd5f4d3',
myFolderUrl: `myFolderUrl`,
loadUrl: `server/luckysheet/api/load`,
allowUpdate: true,
updateUrl: `ws/url`,
customFunctions: [
...customFunctions,
],
};
luckysheet.create(options);
3.2. 公式定义
// 自定义公式
const customFunctions: Array<ICustomFunction> = [
TOJSON,
];
/**
* 自定义公式参数 - 选区类型[区域模式]
*/
export type CustomFunctionArgumentRangeTable = {
/**单元格连续的列 */
coll: Exclude<number, 1>;
/**单元格的数据 */
data: Array<Array<ICell>>;
/**单元格连续的行 */
rowl: Exclude<number, 1>;
/**单元格所属表格的名称 */
sheetName: string;
/**单元格开始位置 */
startCell: string;
};
export const TOJSON: ICustomFunction = {
n: "TOJSON",
t: 0,
m: [1, 1],
a: "将指定区域的内容转为JSON字符串",
d: "转换区域表格为JSON",
p: [
{
example: "\"Sheet2!B2:H11\"",
require: "m",
repeat: "n",
type: 0,
name: "表格区域",
detail: "将选区转为JSON",
},
],
f: function() {
//必要参数个数错误检测
if(arguments.length < this.m[0]) {
return '参数不足';
}
if(arguments.length > this.m[1]) {
return '参数过多';
}
const [_range] = (arguments as unknown) as [ CustomFunctionArgumentRangeTable ];
if(_range.coll === 1 || _range.rowl === 1) {
return "选区异常";
}
// const data_prev = transpose(_range.data);
const jsonObject = [];
for(let row = 1; row < _range.data.length; row++) {
const rowJsonObject: {[key: string]: string} = {};
// 如果这一行都是空的,就要结束了
if(_range.data[row].every(col => !col || !col.m)) break;
for(let col = 0; col < _range.data[row].length; col++) {
const key = _range.data[0][col] ? _range.data[0][col].m : '';
const value = _range.data[row][col] ? _range.data[row][col].m : '';
rowJsonObject[key] = value;
}
jsonObject.push(rowJsonObject);
}
return JSON.stringify(jsonObject);
}
}
四、使用效果


