Office 脚本中的最佳实践

这些模式和做法旨在帮助脚本每次成功运行。 在开始自动执行 Excel 工作流时,请使用它们来避免常见陷阱。

使用操作录制器了解新功能

Excel 执行很多操作。 其中大多数都可以编写脚本。 操作录制器会记录 Excel 操作并将其转换为代码。 这是了解不同功能如何与 Office 脚本配合使用的最简单方法。 如果需要特定操作的代码,请切换到操作录制器,执行操作,选择 “复制为代码”,然后将生成的代码粘贴到脚本中。

操作记录器任务窗格,其中突出显示了“复制为代码”按钮。

重要

有时,操作录制器可能会使用Excel web 版之外不支持的 API。 其他平台上该脚本的用户在查看该脚本时会收到警告。

验证对象是否存在

脚本通常依赖于工作簿中存在的特定工作表或表格。 但是,它们可能会在脚本运行之间重命名或删除。 通过在对这些表或工作表调用方法之前检查是否存在,可以确保脚本不会突然结束。

以下示例代码检查工作簿中是否存在“索引”工作表。 如果工作表存在,则脚本将获取一个范围并继续。 如果不存在,则脚本会记录自定义错误消息。

// Make sure the "Index" worksheet exists before using it.
let indexSheet = workbook.getWorksheet('Index');
if (indexSheet) {
  let range = indexSheet.getRange("A1");
  // Continue using the range...
} else {
  console.log("Index sheet not found.");
}

TypeScript ? 运算符在调用方法之前检查对象是否存在。 如果不需要在对象不存在时执行任何特殊操作,则可以使代码更加简化。

// The ? ensures that the delete() API is only called if the object exists.
workbook.getWorksheet('Index')?.delete();

首先验证数据和工作簿状态

在处理数据之前,请确保所有工作表、表格、形状和其他对象都存在。 使用上一种模式,检查以查看工作簿中的所有内容是否都符合预期。 在写入任何数据之前执行此操作可确保脚本不会使工作簿处于部分状态。

以下脚本要求存在两个名为“Table1”和“Table2”的表。 该脚本首先检查表是否存在,然后以 return 语句结尾,如果不存在,则以相应的消息结尾。

function main(workbook: ExcelScript.Workbook) {
  // These tables must be in the workbook for the script.
  const TargetTableName = 'Table1';
  const SourceTableName = 'Table2';

  // Get the table objects.
  let targetTable = workbook.getTable(TargetTableName);
  let sourceTable = workbook.getTable(SourceTableName);

  // Check if the tables are there.
  if (!targetTable || !sourceTable) {
    console.log(`Required tables missing - Check that both the source (${TargetTableName}) and target (${SourceTableName}) tables are present before running the script.`);
    return;
  }

  // Continue...
}

如果验证是在单独的函数中发生的,则仍必须通过从 函数发出 return 语句来结束脚本 main 。 从子函数返回不会结束脚本。

以下脚本的行为与上一个脚本相同。 区别在于函数 main 调用 inputPresent 函数来验证所有内容。 inputPresent 返回一个布尔 (truefalse) 以指示是否存在所有必需的输入。 函数 main 使用该布尔值来决定是否继续或结束脚本。

function main(workbook: ExcelScript.Workbook) {

  // Get the table objects.
  if (!inputPresent(workbook)) {
    return;
  }

  // Continue...
}

function inputPresent(workbook: ExcelScript.Workbook): boolean {
  // These tables must be in the workbook for the script.
  const TargetTableName = 'Table1';
  const SourceTableName = 'Table2';

  // Get the table objects.
  let targetTable = workbook.getTable(TargetTableName);
  let sourceTable = workbook.getTable(SourceTableName);

  // Check if the tables are there.
  if (!targetTable || !sourceTable) {
    console.log(`Required tables missing - Check that both the source (${TargetTableName}) and target (${SourceTableName}) tables are present before running the script.`);
    return false;
  }

  return true;
}

何时使用 throw 语句

语句 throw 指示发生了意外错误。 它会立即结束代码。 在大多数情况下,不需要 throw 从脚本。 通常,脚本会自动通知用户脚本由于问题而无法运行。 在大多数情况下,使用来自 函数的错误消息和 return 语句结束脚本就足够了 main

但是,如果脚本作为 Power Automate 流的一部分运行,则可能需要阻止流继续。 语句 throw 停止脚本并指示流也停止。

以下脚本演示如何在表检查示例中使用 throw 语句。

function main(workbook: ExcelScript.Workbook) {
  // These tables must be in the workbook for the script.
  const TargetTableName = 'Table1';
  const SourceTableName = 'Table2';

  // Get the table objects.
  let targetTable = workbook.getTable(TargetTableName);
  let sourceTable = workbook.getTable(SourceTableName);

  // Check if the tables are there.
  if (!targetTable || !sourceTable) {
    // Immediately end the script with an error.
    throw `Required tables missing - Check that both the source (${TargetTableName}) and target (${SourceTableName}) tables are present before running the script.`;
  }
  

何时使用 try...catch 语句

语句 try...catch 是一种检测 API 调用是否失败并继续运行脚本的方法。

请考虑以下代码片段,该代码片段对某个区域执行大型数据更新。

range.setValues(someLargeValues);

如果 someLargeValues大于Excel web 版可以处理,则setValues()调用将失败。 然后,脚本也会失败并出现 运行时错误。 语句 try...catch 允许脚本识别此条件,而不会立即结束脚本并显示默认错误。

为脚本用户提供更好的体验的一种方法是向他们显示自定义错误消息。 以下代码片段演示了记录 try...catch 更多错误信息的语句,以更好地帮助读者。

try {
    range.setValues(someLargeValues);
} catch (error) {
    console.log(`The script failed to update the values at location ${range.getAddress()}. Please inspect and run again.`);
    console.log(error);
    return; // End the script (assuming this is in the main function).
}

处理错误的另一种方法是具有处理错误案例的回退行为。 以下代码片段使用 catch 块尝试使用备用方法将更新分解为较小的部分并避免错误。

提示

有关如何更新大范围的完整示例,请参阅 编写大型数据集

try {
    range.setValues(someLargeValues);
} catch (error) {
    console.log(`The script failed to update the values at location ${range.getAddress()}. Trying a different approach.`);
    handleUpdatesInSmallerBatches(someLargeValues);
}

// Continue...
}

注意

在循环内部或周围使用 try...catch 会减慢脚本的速度。 有关更多性能信息,请参阅 避免使用 try...catch

另请参阅