保留加载项状态和设置

Office 加载项实质上是在浏览器 iframe 或 Webview 控件的无状态环境中运行的 Web 应用程序。 (为简洁起见,本文使用“浏览器控件”表示“浏览器或 Web 视图控件”。) 在使用时,外接程序可能需要保留数据以保持会话中某些操作或功能的连续性。 例如,加载项可能具有在下一次初始化时保存和重新加载所需的自定义设置或其他值(例如用户的首选视图或默认位置)。 为此,您可以:

如果需要跨文档保留状态,例如跟踪打开的任何文档的用户首选项,则需要使用其他方法。 例如,可以使用 SSO 获取用户标识,然后将用户 ID 及其设置保存到联机数据库。

浏览器存储

使用来自基础浏览器控件的工具(例如浏览器 Cookie 或 HTML5 Web 存储 (localStoragesessionStorage) )跨外接程序实例持久保存数据。

某些浏览器或用户的浏览器设置可能会阻止基于浏览器的存储技术。 应按照 使用 Web 存储 API 中所述测试可用性。

存储分区

最佳做法是,任何专用数据都应存储在分区中 localStorageOffice.context.partitionKey 提供用于本地存储的键。 这可确保存储在本地存储中的数据仅在同一上下文中可用。 以下示例演示如何将分区键与 一起使用 localStorage。 请注意,在没有分区的环境中未定义分区键,例如 Windows 应用程序的浏览器控件。

// Store the value "Hello" in local storage with the key "myKey1".
setInLocalStorage("myKey1", "Hello");

// ... 

// Retrieve the value stored in local storage under the key "myKey1".
const message = getFromLocalStorage("myKey1");
console.log(message);

// ...

function setInLocalStorage(key: string, value: string) {
  const myPartitionKey = Office.context.partitionKey;

  // Check if local storage is partitioned. 
  // If so, use the partition to ensure the data is only accessible by your add-in.
  if (myPartitionKey) {
    localStorage.setItem(myPartitionKey + key, value);
  } else {
    localStorage.setItem(key, value);
  }
}

function getFromLocalStorage(key: string) {
  const myPartitionKey = Office.context.partitionKey;

  // Check if local storage is partitioned.
  if (myPartitionKey) {
    return localStorage.getItem(myPartitionKey + key);
  } else {
    return localStorage.getItem(key);
  }
}

从 Chrome 和 Edge 等基于 Chromium 的浏览器版本 115 开始, 启用存储分区 以防止特定侧通道跨站点跟踪 (另请参阅 Microsoft Edge 浏览器策略) 。 与基于 Office 键的分区类似,存储 API 存储的数据(例如本地存储)仅适用于具有相同源和相同顶级站点的上下文。

特定于应用程序的设置和持久性

Excel、Word 和 Outlook 提供特定于应用程序的 API 来保存设置和其他数据。 使用这些 API 而不是 本文后面提到的通用 API ,以便外接程序遵循一致的模式,并针对目标应用程序进行优化。

Excel 和 Word 中的设置

适用于 Excel 和 Word 的应用程序特定 JavaScript API 还提供对自定义设置的访问权限。 设置对单个 Excel 文件和加载项配对是唯一的。 有关详细信息,请参阅 Excel.SettingCollectionWord.SettingCollection

以下示例演示如何在 Excel 中创建和访问设置。 在 Word 中,该过程在功能上是等效的Workbook.settings,它使用 Document.settings 而不是 。

await Excel.run(async (context) => {
    const settings = context.workbook.settings;
    settings.add("NeedsReview", true);
    const needsReview = settings.getItem("NeedsReview");
    needsReview.load("value");

    await context.sync();
    console.log("Workbook needs review : " + needsReview.value);
});

Excel 和 Word 中的自定义 XML 数据

Open XML .xlsx.docx 文件格式允许外接程序在 Excel 工作簿或 Word 文档中嵌入自定义 XML 数据。 此数据与 文件一起保留,与加载项无关。

Word.DocumentExcel.Workbook 包含 ,CustomXmlPartCollection它是 的列表CustomXmlParts。 通过这些部件可以访问 XML 字符串并获得对应的唯一 ID。 将这些 ID 存储为设置后,加载项可以维护会话之间的 XML 部件密钥。

以下示例演示如何对 Excel 工作簿使用自定义 XML 部件。 第一个代码块演示如何嵌入 XML 数据。 它将会存储一个审阅者列表,然后使用工作簿的设置保存 XML 的 id,以供后续检索。 第二个代码块演示后续如何访问该 XML。 “ContosoReviewXmlPartId”设置将被加载和传递到工作簿的 customXmlParts。 XML 数据随后将打印至控制台。 在 Word 中,该过程在功能上是等效的Workbook.customXmlParts,它使用 Document.customXmlParts 而不是 。

await Excel.run(async (context) => {
    // Add reviewer data to the document as XML
    const originalXml = "<Reviewers xmlns='http://schemas.contoso.com/review/1.0'><Reviewer>Juan</Reviewer><Reviewer>Hong</Reviewer><Reviewer>Sally</Reviewer></Reviewers>";
    const customXmlPart = context.workbook.customXmlParts.add(originalXml);
    customXmlPart.load("id");
    await context.sync();

    // Store the XML part's ID in a setting
    const settings = context.workbook.settings;
    settings.add("ContosoReviewXmlPartId", customXmlPart.id);
});

注意

仅当顶级自定义 XML 元素包含 xmlns 属性时才会填充 CustomXMLPart.namespaceUri

Excel 和 Word 中的自定义属性

Excel.DocumentProperties.customWord.DocumentProperties.customProperties 属性表示用户定义的属性的键值对集合。 以下 Excel 示例演示如何使用值“Hello”创建名为 Introduction 的自定义属性,然后检索它。

await Excel.run(async (context) => {
    const customDocProperties = context.workbook.properties.custom;
    customDocProperties.add("Introduction", "Hello");
    await context.sync();
});

// ...

await Excel.run(async (context) => {
    const customDocProperties = context.workbook.properties.custom;
    const customProperty = customDocProperties.getItem("Introduction");
    customProperty.load(["key", "value"]);
    await context.sync();

    console.log("Custom key  : " + customProperty.key); // "Introduction"
    console.log("Custom value : " + customProperty.value); // "Hello"
});

提示

在 Excel 中,还可以使用 Worksheet.customProperties 属性在工作表级别设置自定义属性。 这些属性类似于文档级自定义属性,只不过可以在不同的工作表中重复相同的键。

如何在 Outlook 加载项中保存设置

有关如何在 Outlook 外接程序中保存设置的信息,请参阅获取和设置 Outlook 外接程序的加载项元数据和获取和设置 Outlook 外接程序中邮件的 Internet 标头

常见 API 设置和持久性

通用 API 提供用于跨会话保存加载项状态的对象。 保存的设置值与创建它们的加载项的 ID 相关联。 在内部,使用 SettingsCustomPropertiesRoamingSettings 对象访问的数据存储为序列化的 JavaScript 对象表示法, (包含名称/值对的 JSON) 对象。 每个值 (键) 的名称必须是 string,并且存储的值可以是 JavaScript stringnumberdateobject,但不能是 函数

此属性包结构示例包含三个名为 、 locationdefaultViewfirstName已定义字符串值。

{
    "firstName":"Erik",
    "location":"98052",
    "defaultView":"basic"
}

在前一个加载项会话中保存设置属性包之后,可以在加载项的当前会话中初始化加载项时或在之后的任何时间加载该设置属性包。 在会话期间,使用 get对象的 、 setremove 方法在内存中管理设置,这些方法对应于要创建的设置类型, (SettingsCustomPropertiesRoamingSettings) 。

重要

若要将加载项当前会话期间进行的任何添加、更新或删除保存到存储位置,必须调用 saveAsync 用于处理此类设置的相应对象的 方法。 getsetremove 方法仅在设置属性包的内存中副本上运行。 如果加载项在未调用 saveAsync的情况下关闭,则在该会话期间对设置所做的任何更改都将丢失。

如何按文档暂留内容和任务窗格加载项的加载项状态和设置

若要保留 Word、Excel 或 PowerPoint 的内容或任务窗格加载项的状态或自定义设置,请使用 Settings 对象及其方法。 使用 对象方法 Settings 创建的属性包仅适用于创建它的内容或任务窗格加载项的实例,并且只能从保存它的文档中使用。

对象 Settings 作为 Document 对象的一部分自动加载,并在激活任务窗格或内容加载项时可用。 实例 Document 化对象后,可以使用 对象的 Settingssettings 属性 Document 访问 对象。 在会话的生存期内,可以使用 Settings.getSettings.setSettings.remove 方法从属性包的内存中副本中读取、写入或删除保留的设置和加载项状态。

由于 set 和 remove 方法仅对 settings 属性包的内存中副本进行操作,因此若要将新设置或更改的设置保存回与外接程序关联的文档,必须调用 Settings.saveAsync 方法。

创建或更新设置值

以下代码示例演示如何使用 Settings.set 方法创建名为 'themeColor' 且值为 'green' 的设置。 set 方法的第一个参数是要设置或创建的设置 (ID) 区分大小写 的名称 。 第二个参数是设置的 value

Office.context.document.settings.set('themeColor', 'green');

如果具有指定名称的设置尚不存在,则创建此设置,如果此设置存在,则对值进行更新。 Settings.saveAsync使用 方法可将新的或更新的设置保存到文档中。

获取设置的值

下面的示例演示如何使用 Settings.get 方法获取名为“themeColor”的设置值。 方法的唯一 get 参数是设置的区分大小写 的名称

write('Current value for mySetting: ' + Office.context.document.settings.get('themeColor'));

// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message;
}

方法 get 返回之前为传入的设置 名称 保存的值。 如果不存在该设置,那么方法返回 null

删除设置

下面的示例演示如何使用 Settings.remove 方法删除名为“themeColor”的设置。 方法的唯一 remove 参数是设置的区分大小写 的名称

Office.context.document.settings.remove('themeColor');

如果设置不存在,则不会发生任何操作。 Settings.saveAsync使用 方法持久删除文档中的设置。

保存设置

若要保存当前会话中加载项对设置属性包内存副本所做的任意添加、更改或删除操作,必须调用 Settings.saveAsync 方法将它们存储在文档中。 方法的唯一 saveAsync 参数是 callback,它是具有单个参数的回调函数。

Office.context.document.settings.saveAsync(function (asyncResult) {
    if (asyncResult.status == Office.AsyncResultStatus.Failed) {
        write('Settings save failed. Error: ' + asyncResult.error.message);
    } else {
        write('Settings saved.');
    }
});
// Function that writes to a div with id='message' on the page.
function write(message){
    document.getElementById('message').innerText += message;
}

在操作完成时,将作为回调参数传入saveAsync方法的匿名函数执行。 回调的 asyncResult 参数提供对 AsyncResult 包含操作状态的对象的访问权限。 在此示例中,函数检查 AsyncResult.status 属性以查看保存操作是成功还是失败,然后在外接程序的页面中显示结果。

如何将自定义 XML 保存到文档

自定义 XML 部件是一个可用的存储选项,用于存储具有结构化字符的信息或需要跨外接程序实例访问的数据。 请注意,以这种方式存储的数据也可以由其他加载项访问。可以使用上一段) 中所述,在 Word (和 Excel 和 Word 的任务窗格外接程序中保留自定义 XML 标记。 在 Word 中,可以使用 CustomXmlPart 对象及其方法。 以下代码将创建自定义 XML 部件,并在页面的 divs 中显示其 ID 及内容。 请注意,XML 字符串中必须有一个 xmlns 属性。

function createCustomXmlPart() {
    const xmlString = "<Reviewers xmlns='http://schemas.contoso.com/review/1.0'><Reviewer>Juan</Reviewer><Reviewer>Hong</Reviewer><Reviewer>Sally</Reviewer></Reviewers>";
    Office.context.document.customXmlParts.addAsync(xmlString,
        (asyncResult) => {
            $("#xml-id").text("Your new XML part's ID: " + asyncResult.value.id);
            asyncResult.value.getXmlAsync(
                (asyncResult) => {
                    $("#xml-blob").text(asyncResult.value);
                }
            );
        }
    );
}

若要检索自定义 XML 部件,请使用 getByIdAsync 方法,但 ID 是在创建 XML 部件时生成的 GUID,因此在编码 ID 时无法知道。 因此,创建 XML 部件时,最好立即将 XML 部件的 ID 存储为设置,并为其指定一个令人难忘的键。 下面的方法展示了如何执行此操作。

function createCustomXmlPartAndStoreId() {
   const xmlString = "<Reviewers xmlns='http://schemas.contoso.com/review/1.0'><Reviewer>Juan</Reviewer><Reviewer>Hong</Reviewer><Reviewer>Sally</Reviewer></Reviewers>";
   Office.context.document.customXmlParts.addAsync(xmlString,
       (asyncResult) => {
           Office.context.document.settings.set('ReviewersID', asyncResult.value.id);
           Office.context.document.settings.saveAsync();
       }
   );
}

下面的代码展示了如何通过先从设置中获取 ID 来检索 XML 部分。

function getReviewers() {
   const reviewersXmlId = Office.context.document.settings.get('ReviewersID');
   Office.context.document.customXmlParts.getByIdAsync(reviewersXmlId,
       (asyncResult) => {
           asyncResult.value.getXmlAsync(
               (asyncResult) => {
                   $("#xml-blob").text(asyncResult.value);
               }
           );
       }
   );
}

另请参阅