目前,我正在共享运行时加载项项目中从 CustomFunction.Invocation 更改为 StreamingInvocation,因为我将不得不使用 Web 套接字。我有一个用例需要使用自定义函数的地址属性作为数据对象中的键以供进一步使用,我发现它不能与 StreamingInvocation 一起使用。我尝试使用 onChanged 和 onCalculated 事件实现解决方法,但效果不佳。所以,我不确定是否有一些解决方法可以用来在其内部获取自定义函数的地址属性。
编辑:添加代码和更多细节
export class TestExcelService {
private static instance: TestExcelService;
private dataEventEmtter?: EventEmitter;
// prevent direct construction call with new keyword.
// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {
this.registerOnCalculated();
}
public static getInstance(): TestExcelService {
if (!TestExcelService.instance) {
TestExcelService.instance = new TestExcelService();
}
return TestExcelService.instance;
}
public setDataEventEmtter(eventEmitter: EventEmitter): void {
this.dataEventEmtter = eventEmitter;
}
public getDataEventEmtter(): EventEmitter | undefined {
return this.dataEventEmtter;
}
private async registerOnCalculated(): Promise<void> {
await Excel.run(async (context: Excel.RequestContext) => {
context.workbook.worksheets.getActiveWorksheet().onCalculated.add(
async (arg: Excel.WorksheetCalculatedEventArgs): Promise<void> => {
const formulaAddresses: ICellAddress[] = await this.filterMyFormulaAddress(arg);
if (this.dataEventEmtter && formulaAddresses.length > 0) {
this.dataEventEmtter.emit('onExcelCalculated', formulaAddresses);
}
},
);
});
}
private async filterMyFormulaAddress(arg: Excel.WorksheetCalculatedEventArgs): Promise<ICellAddress[]> {
// filter only some formulas
return [];
}
}
export class TestDataService {
private eventEmitter: EventEmitter = new EventEmitter();
private static instance: TestDataService;
private dataQueue = [];
// prevent direct construction call with new keyword.
// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {
this.eventEmitter.addListener('onExcelCalculated', this.excelCalculatedHandler.bind(this));
}
public static getInstance(): TestDataService {
if (!TestDataService.instance) {
TestDataService.instance = new TestDataService();
}
return TestDataService.instance;
}
public addDataToQueue(data): void {
const duplicatedIndex: number = this.dataQueue.findIndex(
(queueData) => data.formulaId === queueData.formulaId,
);
if (duplicatedIndex < 0) {
this.dataQueue.push(data);
}
}
public getEventEmitter(): EventEmitter {
return this.eventEmitter;
}
private async excelCalculatedHandler(formulaAddresses: ICellAddress[]): Promise<void> {
if (Array.isArray(this.dataQueue) && this.dataQueue.length > 0) {
// check that data queue is not empty and map formula addresses from onCalculated event to the data queue
}
}
}
我不能发布完整的代码,所以我将不得不删除和修改代码的某些部分。
一般的想法是我将必须使用它们各自的公式地址映射的数据对象添加到 DataService 中的数据队列中,并且在触发 onCalculated 事件后,我应该能够获得计算和过滤地址的列表。
根据我的测试,公式地址的顺序应该与数据队列的顺序相匹配。起初,当我一次执行一个公式或同时重新计算少量公式时,这种解决方法似乎工作正常,但是当公式数量开始增长并且我尝试重新计算所有公式时,公式的顺序地址和数据队列不会像我预期的那样匹配。