OfficeJs - 使用流式调用时获取自定义函数的地址属性

问题描述

目前,我正致力于在共享运行时加载项项目中从 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
    }
  }
}

我不能发布完整的代码,所以我必须删除和修改代码的某些部分。

总的想法是我将必须用它们各自的公式地址映射到数据服务中的数据队列的数据对象添加,并且在触发 onCalculated 事件后,我应该能够获得计算和过滤地址的列表。

根据我的测试,公式地址的顺序应该与数据队列的顺序匹配。起初,当我一次执行一个公式或同时重新计算少量公式时,此解决方法似乎工作正常,但是当公式数量开始增加并且我尝试重新计算所有公式时,公式的顺序地址和数据队列将不会如我预期的那样匹配。

解决方法

流媒体功能很特别。如果任何一组流函数使用相同的表达式,则它们共享相同的根(即上下文)。范围在工作簿中很好。在另一个工作簿中,上下文会有所不同。所以没有为流功能提供地址信息。如您所见, onCalculated 事件将记录所有计算出的地址。但是,对于地址的特殊请求,它需要额外的逻辑,例如保持公式地址的顺序以匹配您的案例中的数据队列。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...