如何通过 Angular 使用 Office JS 中的 addHandlerAsync

How to use addHandlerAsync from Office JS with Angular

我正在使用 Angular 创建一个 Excel 加载项,并为各种单元格创建了绑定。我有一个显示这些绑定单元格内数据的表单,我希望在单元格中的数据发生变化时更新表单。在 OfficeJS 库中,它引用使用:

addHandlerAsync(Office.EventType.BindingDataChanged, <handler method>)

https://dev.office.com/reference/add-ins/shared/binding.addhandlerasync

但是,当我尝试在 Angular 组件或服务内的 TS 中执行此操作时,处理程序在触发时无法从组件或服务调用任何方法。它只能在处理程序中使用 运行 Office JS 方法。我该怎么做才能从处理程序中触发组件或服务方法?

用例的一个示例是,如果您想在每次电子表格中的任何单元格绑定发生更改时触发加载项中的某些内容,例如在加载项中显示某些内容。这似乎是一个可以支持的通用操作。并且文档在 JS 中显示了类似的内容:

function addHandler() {
Office.select("bindings#MyBinding").addHandlerAsync(
    Office.EventType.BindingDataChanged, dataChanged);
}
function dataChanged(eventArgs) {
    write('Bound data changed in binding: ' + eventArgs.binding.id);
}
// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message; 
}

但是,当我尝试做类似的事情时:

 createHandlerOnA1(): Promise<IOfficeResult> {
        return new Promise((resolve, reject) => {
            this.workbook.bindings.getByIdAsync(this.bindingName, (result: Office.AsyncResult) => {
                if(result.status === Office.AsyncResultStatus.Failed) {
                    reject({
                        error: 'failed to get binding by id'
                    });
                } else {
                    result.value.addHandlerAsync(Office.EventType.BindingDataChanged, this.changeEvent, (handlerResult: Office.AsyncResult) => {
                        if(handlerResult.status === Office.AsyncResultStatus.Failed) {
                            reject({
                                error: 'failed to set a handler'
                            });
                        } else {
                            // Successful 
                            resolve({
                                success: 'successfully set handler'
                            });
                        }
                    })
                }
            })
        })
    }

  addHandler() {
    this.createHandlerOnA1()
    .then((result: any) => {
      this.feedback = result.success;
    }, (result: IOfficeResult) => {
      this.feedback = result.error;
    });
  }

  changeFeedback() {
    this.feedback = 'hello'
  }

  // Excel methods
  changeEvent(eventArgs: any) {
      Excel.run(async (context) => {
            const data = [
                ["Hello World"]
            ];
      const range = context.workbook.getSelectedRange()
      range.values = data;
      await context.sync();
    });
    // Handler cannot run this
    // this.changeFeedback(); 
  }

函数 changeFeedback() 不能 运行 来自 changeEvent(eventArgs: any) 处理程序。我在这里做了一个示例 repo 来演示这个问题:

https://github.com/brandonkoch6/addHandlerAsyncError

我试图更改对处理程序的引用,以便它通过这样做来维护 'this' 的绑定:

addHandlerAsync(Office.EventType.BindingDataChanged, (eventArgs:any) => this.changeEvent(eventArgs))

addHandlerAsync(Office.EventType.BindingDataChanged, this.changeEvent.bind(this))

那些并不能解决问题。所以,我有点不知所措。

如有任何帮助,我们将不胜感激。我认为这与处理程序为运行时'this'的上下文对象有关。有一个 [options] 参数作为添加处理程序的一部分,但我似乎无法在文档中找到所有可用的选项:

https://dev.office.com/docs/add-ins/develop/asynchronous-programming-in-office-add-ins#passing-optional-parameters-to-asynchronous-methods

问题是因为代码 运行 在 angular 区域之外。

您需要将代码置于 运行 区域内。检查 my code, and this article 以了解其工作原理。

import { NgZone } from '@angular/core';

// ...

constructor(private zone: NgZone) { }

myFunction() {
  this.zone.run(() => {
    // the code
  });
}

P.S。我创建了一个问题 here。有时间我会尽快更新文档。