Office JS:插件在多个 Excel 实例中执行时出现问题

Office JS: Problems when Addin is executed in multiple Excel instances

我在多个 Excel 实例中执行 office 插件时遇到问题。当两者同时执行时,一个停止 运行。

我做了 2 个快速 ScriptLab 示例,您可以在其中重现一些问题(我粘贴了它们)。一个包含一个 UDF 函数,只需在 ScriptLab 中注册它。另一个是产生我的一个问题的样本。

首先注册 UDF,然后再使用第二部分,创建 2 个工作簿,每个工作簿有 100 个工作sheet,其中包含以下函数(取决于 Snippent 名称,在我的例子中是 "Blank snippet (1)",如果您的名字不同,请在此处和函数 "findAllOrNullObject") 的插件代码中调整公式名称。

=SCRIPTLAB.BLANKSNIPPET1.ADD(1;2)

最快的方法是: 使用该函数创建十个 sheet 并将这十个作品 sheet 复制十次到工作簿的末尾。完成后,再次使用不同的名称保存工作簿。然后,打开两个工作簿并单击 "Run"(在两个 sheet 中)。比在 运行 或打开一个应用程序时单击另一个应用程序。在控制台上,您会看到一个计数器,指示 sheet 插件实际在哪个上工作。您应该期望在这两种情况下都出现 "INDEX: 100",但是当您单击另一个应用程序或启动一个应用程序时,一个实例会停止,并且不会达到 100。如果您不会直接遇到问题,请重试,它肯定会出现。

UDF 代码:

/**
 * Adds two numbers.
 * @customfunction
 * @param first First number
 * @param second Second number
 * @returns The sum of the two numbers.
 */
/* global clearInterval, console, setInterval */

function add(first: number, second: number): number {
  return first + second;
}

插件代码:

$("#run").click(() => tryCatch(run));

async function run() {
  this.refreshWorkbook();
}

async function refreshWorkbook() {
  let sheets: Excel.WorksheetCollection;

  Excel.run(async (context) => {
    sheets = context.workbook.worksheets;
    sheets.load("items/name");
    await sheets.context.sync();
    if (sheets.items.length >= 1) {
      for (let sheetIndex = 0; sheetIndex < sheets.items.length; sheetIndex++) {
        console.log("INDEX : " + sheetIndex);
        const sheet = sheets.items[sheetIndex];
        await this.getInfo(sheet.name).then((information) => {
          // some stuff
        });
      }
    }
  });
}

async function getInfo(worksheetName: string): Promise<string> {
  return new Promise<string>((resolve, reject) => {
    Excel.run(async (context) => {
      const sheet: Excel.Worksheet = context.workbook.worksheets.getItem(worksheetName);
      sheet.load("name");
      await context.sync();
      const usedRange = sheet.getUsedRangeOrNullObject();
      if (usedRange) {
        const functionCells = sheet.findAllOrNullObject("=SCRIPTLAB.SCRIPTLAB.BLANKSNIPPET1.ADD(", {
          matchCase: false,
          completeMatch: false
        });
        functionCells.load("areaCount");
        await context.sync();
        if (functionCells) {
          resolve("A");
        } else {
          reject("X");
        }
      }
    });
  });
}

/** Default helper for invoking an action and handling errors. */
async function tryCatch(callback) {
  try {
    await callback();
  } catch (error) {
    // Note: In a production add-in, you'd want to notify the user through your add-in's UI.
    console.error(error);
  }
}

如果我删除搜索部分,它会起作用。

这个issue可以重现,没有CF也可以重现。所以这是更多 API 相关的问题。创建了错误 4124929 来跟踪此问题。更有可能是 findAllOrNullObject API 中的问题,我们正在对此问题进行一些调查。