本文章是由機器翻譯。

Microsoft Office

探索 Office 全新的 JavaScript API

Stephen Oliver
Eric Schmidt

本文是深入介紹Microsoft Office2013 中新引入的 JavaScript API for Office 的系列文章的第一篇。 本文假設您熟悉用於 Office 的應用程式。 若您不熟悉,請參考 MSDN 文檔頁「用於 Office 的應用程式概述」(bit.ly/12nBWHG),那裡提供了對該 API 的大體概述和一般性介紹。

本文和此系列中其他文章雖不詳盡,但深入介紹了該 API,觸及到一些很關鍵的方面,能説明您對 Office API 應用程式的工作方式獲得更為豐富翔實的瞭解。

在此第一篇文章中,我們討論用於 Office 物件模型的應用程式。 第二部分著重介紹訪問 Office 檔內容的核心任務,並考察事件模型。 第三部分將考察資料繫結的概念,並介紹有關使用自訂 XML 部件的基本知識。 作為此系列文章的最後一篇,第四部分將著重介紹郵件應用程式。

在整個系列中,我們經常引用 Office API 應用程式文檔。 您可以在 MSDN 上的「Office 和 SharePoint 應用程式開發人員中心」(dev.office.com) 找到官方文檔、示例代碼和社區資源。

Overview of the JavaScript API for Office

JavaScript API for Office 包含完整的物件模型。 該 API 包含在一組 JavaScript 檔中,其中第一個檔是 office.js。 應用程式必須包含對 office.js 檔的引用才能使用 JavaScript API for Office。 office.js 檔在載入時會裝入它操作所必需的其他腳本,包括主機環境和地區設定字串所需的腳本。 幸運的是,您可以使用內容交付網路 (CDN) 添加對 office.js 的引用,而不必隨您的應用程式一起部署 office.js 檔的副本。 Here’s an example:

 

  <!-- When deploying an app, you should always
    load the CDN version of the office.js file.
  -->
  <script src=
    "https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js">
  </script>

該物件模型基於以下幾個目標而設計:

  1. “Write once, run everywhere.” It had to be extensible—not tied to a specific host application, but built around capabilities available in multiple host applications. 應用程式以一致的方式訪問特定于主機的功能。
  2. 跨平臺。 在這個目標清單中,相容性也是非常重要的一條;因此物件模型不能局限于某個特定的 Office 版本。 此外,相同的代碼同樣能在 Office 用戶端應用程式的受支援 Web 應用程式版本上運行。 例如,一個用於 Excel 的應用程式可以像在 Excel 用戶端應用程式中一樣在 Excel Web App 中運行。
  3. Performance and security. 它應該能夠實現最佳性能,以使應用程式在使用者眼中儘量不顯唐突。 此外,該 JavaScript API 還經過專門設計,無需自動運行 Office 應用程式就可直接與文檔內容交互,從而提高了解決方案的穩定性和安全性。

該 JavaScript API 的另一個重要目標是將 Web 開發人員吸引到 Office 平臺。 因此,該物件模型在構建時就考慮到了現代 Web 程式設計方法。 您在結合 JavaScript API for Office 創建應用程式時,可以利用您目前對其他 JavaScript 庫(如 jQuery)所掌握的技能和知識。

非同步程式設計模式

正前所述,在 Office API 應用程式的設計中,性能是很重要的目標。 設計人員增強 API 性能的方法之一是大量使用非同步函數。

使用非同步函數可避免應用程式在執行過程中因某函數長時間不返回而出現阻塞的情況。 調用非同步函數時,程式執行並不等待該函數返回, 而是在該非同步函數仍在執行的同時繼續。 這使使用者能夠在應用程式可能仍在運行的同時繼續使用 Office 文檔。

本節介紹以下一些有助於理解 Office API 應用程式非同步設計的要點:

  • Office API 應用程式中非同步函數的通用簽名
  • 在非同步函數中使用可選參數
  • AsyncResult 物件在非同步函數中的角色

我們將逐一討論這些要點。

Office API 應用程式中非同步函數的通用簽名 Office API 應用程式中的所有非同步函數都有相同的命名約定和相同的基本簽名。 每個非同步函數的名稱都以「Async」結尾,例如: Document.getSelectedDataAsync.

所有非同步函數的簽名都遵循以下基本模式:

functionNameAsync(
    requiredParameters,
    [, options], [callback]);

必需參數後面另有兩個參數:一個包含可選參數的物件和一個回呼函數,兩者始終都是可選的。

非同步函數中的可選參數非同步函數簽名中的可選 JavaScript 物件是用分號分隔的鍵/值對的集合,其中的鍵是參數名稱,值是您想對該參數使用的資料。 鍵/值對的順序無關緊要,只要參數名稱正確即可。 每個非同步函數的 MSDN 文檔詳細說明了可在該特定函數的選項物件中使用哪些參數。

例如,Document.setSelectedDataAsync 方法具有 Office 應用程式中所有非同步函數通用的相同基本簽名:

Office.context.document.setSelectedDataAsync(
  data [, options], callback);

與該 API 中所有非同步函數一樣,Document.set­SelectedDataAsync 也有一個選項物件,其中包含可選參數,但其選項物件的參數與該 API 中其他非同步函數的參數不同,因為此函數的用途是設置資料。 因此,Document.setSelectedDataAsync 的可選參數與設置資料有關:

  • coercionType:一個指定所插入資料格式(文本、HTML、OOXML、表或矩陣)的 CoercionType 枚舉
  • asyncCoNtext:一個使用者定義物件,在作為回呼函數唯一參數傳遞給該函數的 AsyncResult 物件中無變化返回。

這一概念同樣適用于其他所有非同步函數。

您可以在非同步函式呼叫中以内嵌物件文本的方式提供包含可選參數的物件,也可以先創建物件,然後為該參數傳遞該物件。 下面是兩段示例代碼,顯示了使用 Document.setSelectedDataAsync 函數提供選項物件的兩種方式。

傳遞內嵌選項參數:

function setData(data) {
  Office.context.document.setSelectedDataAsync(data, {
  coercionType: Office.CoercionType.Text }  
  );
}

在 JavaScript 物件中傳遞選項參數:

function setData(data) {
  var options = { coercionType: Office.CoercionType.Text };
  Office.context.document.setSelectedDataAsync(data, options );
}

AsyncResult 物件在非同步函數中的角色 JavaScript API for Office 中非同步函數的通用簽名中的第三個參數是可選的回檔參數。 該回檔參數的作用正如其名:它是您所提供的供非同步作業完成時調用的一個函數。 當然,您在非同步函式呼叫中提供命名函數或內嵌匿名函數都可以。 此處需要注意很重要的一點,那就是 AsyncResult 物件對於回呼函數的角色。

當運行時調用回呼函數時,它會將 Async­Result 物件作為回呼函數唯一的參數傳入。 AsyncResult 物件包含有關非同步作業的資訊,如:操作是否成功;發生了什麼錯誤(如果有);以及非同步函數的傳回值(如果有)。 實際上,在返回某種資料或物件的所有非同步函數中,AsyncResult 都是可以獲得傳回值的唯一方式。 您可以使用 AsyncResult.value 屬性實現這一點。

例如,以下代碼片段獲取文檔的大小,並將文檔大小顯示在應用程式 UI 的指定 HTML 元素中。 要獲取檔案大小,首先需要獲取 Document.getFileAsync 方法通過 AsyncResult.value 屬性返回的檔物件。 Here’s how to do this:

function getFileData(elementId) {
  Office.context.document.getFileAsync(Office.FileType.Text,
  function (asyncResult) {
    if (asyncResult.status === 'succeeded') {
      var myFile = asyncResult.value;
      $(elementId).val(myFile.size);
    }
  });
}

getFileData 函式呼叫 Document.getFileAsync 方法,調用時指定它應以文本方式返回檔內容。 然後,它使用傳入匿名函數回檔的 AsyncResult 物件的值屬性來獲取對 File 物件的引用。 然後,它使用 File 物件的 size 屬性在指定元素中顯示檔的大小。 同樣,您將使用 AsyncResult.value 屬性來獲取 Office API 應用程式中任何非同步函數的傳回值。

您可以在本系列下一篇文章中讀到關於 Document.getFileAsync 方法的更多內容。

物件模型層次結構

JavaScript API for Office 旨在提供跨各個 Office 版本的相容性,以及跨不同主機應用程式的對稱性。 為了實現這些目標,JavaScript API 使用了一個簡單的物件模型,該模型層次分明,並不直接局限于任何特定主機應用程式。 該物件模型包含一組用於與 Office 文檔交互的有針對性的功能,其可用範圍界定為使用它們的應用程式類型(工作窗格、內容或郵件應用程式)。

圖 1 是 JavaScript API for Office 中物件層次結構中頂層的概圖(請注意,此處並未顯示完整物件模型)。 該圖明確展現了 Office、CoNtext、Document、Settings、Mailbox 和 RoamingSettings 物件之間的關係。

The Object Model Hierarchy in the JavaScript API for Office
圖 1 JavaScript API for Office 中的物件模型層次結構

每個主機應用程式(Word、Excel、Excel Web App、PowerPoint、Project、Outlook 和 Outlook Web App)都可以使用該 API 中的一部分功能。 例如,物件模型中大約 40% 的功能都僅與 Outlook 和 Outlook Web App 中專用的郵件應用程式相關。 物件模型的另一部分則可用於與自訂 XML 部件(只在 Word 2013 中提供)交互。

圖 2 顯示了對特定主機應用程式可用的功能。

圖 2 JavaScript API for Office 中適用于主機應用程式的功能

Capability Word Excel/Excel Web App PowerPoint Outlook/Outlook Web App Project
以文本、表和矩陣形式獲取/設置資料 All All 僅文本   僅文本
Settings(設置) All All All (RoamingSettings)  
獲取檔 All   僅壓縮檔    
綁定 All All      
自訂 XML 部件 All        
HTML and OOXML All        
郵箱       All  

物件模型中的共用物件 JavaScript API for Office 有一個明確的進入點:Office 物件。該進入點對所有類型的應用程式並在所有主機應用程式中可用。 Office 物件代表插入文檔、活頁簿、演示文稿、專案、電子郵件或約會安排中的具體應用程式實例。 它可以使用 select 方法訪問應用程式和文檔之間的綁定。 (我們將在以後的文章中更深入地討論綁定。)最重要的是,Office 物件公開應用程式的初始化事件,這使您能夠構建應用程式的初始化邏輯(以後的文章中將介紹更多相關內容)。 最後,Office 物件包含對應用程式的 CoNtext 物件的引用。

CoNtext 物件也對所有類型的應用程式並在所有主機應用程式中可用,它公開有關託管應用程式的運行時環境的資訊。 除了存儲應用程式的語言設置之外,CoNtext 物件還提供 JavaScript API for Office 中的運行時功能的進入點,這些功能特定于啟動該應用程式的主機。

例如,可以通過 CoNtext.document 屬性訪問與應用程式相關聯的文檔(Document 物件)。 但是,此屬性僅當從支援它的主機應用程式中(也就是說從工作窗格或內容應用程式中)調用時才會傳回值。 如果嘗試從郵件應用程式訪問 CoNtext.document 屬性,則會出現「未定義的物件」錯誤。 CoNtext.mailbox 屬性也是如此:在郵件應用程式中,它返回主機應用程式中打開的郵箱(Mailbox 物件)。 在工作窗格應用程式中,該屬性未定義。

對工作窗格和內容的支援 物件模型中的應用程式對於工作窗格和內容應用程式,Document 物件代表插入了應用程式的文檔、活頁簿、演示文稿或專案。 Document 物件提供對檔內容最高程度的訪問,實質上,它是應用程式與 Office 文檔之間的主要聯繫點。

訪問 Office 文檔內容的所有方法幾乎都需要使用 Document 物件。 因此,如圖 3 所示,您可能希望在應用程式初始化時捕獲對 Document 物件的引用。

圖 3 在應用程式初始化時存儲對 Document 物件的引用

// Add a handler to the initialize event of the Office object
Office.initialize = function (reason) {
  $(document).ready(function () {
    app.get_Document(Office.context.document);
 
    // Other initialization logic goes here
  })
}
 
// Use a self-executing anonymous function to encapsulate the
// functionality that the app uses
var app = (function () {
 
  var _document;
  function get_Document(officeDocument) {
    _document = officeDocument;
  }
 
  // Other fields and functions associated with the app
 
  return {
    get_Document: get_Document
    // Other exposed members
  };
})()

在 Project 檔中啟動一個應用程式時,Document 物件將公開針對 Project 檔的其他特定功能。 通過 Document 物件,應用程式可以獲取專案中特定任務、視圖、欄位和資源的資料。 應用程式還可以添加事件攔截器以監視使用者對專案中所選視圖、任務或資源的更改。 (在下一篇文章中,我們將更詳細地討論如何在 Project 應用程式中使用 Document 物件。)

Document 物件還公開 Settings 物件,該物件表示應用程式的「屬性包」。 使用 Settings 物件,應用程式可以在同一文檔中跨不同應用程式會話存儲和持久保存自訂屬性。 這些屬性隨文檔移動:如果您與他人共用某個包含應用程式的 Office 檔,則當此人讀取該檔時,存儲在該應用程式中的自訂屬性將可用。

使用屬性包存儲和檢索設置很簡單。 Settings.set 方法會在記憶體中以鍵/值對形式創建設置。 為從屬性包中取出屬性,我們要傳入設置的名稱(鍵)來使用 Settings.get 方法獲取值。 Both the set and get methods are synchronous. 要跨會話存儲設置,我們需要調用 Settings.saveAsync 方法,該方法在保存文檔時保存包含在應用程式中的所有自訂屬性。

示例代碼「Office 應用程式:持久保存自訂設置」(bit.ly/UEiZff) 另外提供了一些示例,演示如何使用 Settings 物件以及如何在應用程式中存儲資料。

物件模型中對郵件應用程式的支援對於郵件應用程式,Mailbox 物件提供了郵件應用程式特定功能的資料訪問進入點。 顧名思義,Mailbox 物件對應于當前使用者的郵箱,無論使用者在何處(無論在 Outlook 用戶端應用程式還是在 Outlook Web App 中)閱讀他們的電子郵件,該物件都隨之移動。 除了提供對各電子郵件和約會安排的訪問(通過 Mailbox.item 屬性)之外,Mailbox 物件還允許應用程式創建新的約會安排、訪問本地使用者的設定檔,甚至獲取使用者的本地時間。

就像 Document 物件之于內容和工作窗格應用程式一樣,您可能希望在應用程式初始化時捕獲對 Mailbox 物件的引用,如圖 4 所示。

圖 4 應用程式初始化時在全域變數中存儲對 Mailbox 物件的引用

// Add a handler to the initialize event of the Office object
Office.initialize = function (reason) {
  $(document).ready(function () {
    app.get_Mailbox(Office.context.mailbox);
 
    // Other initialization logic goes here
  })
}
 
// Use a self-executing anonymous function to encapsulate the
// functionality that the app uses
var app = (function () {
 
  var _mailbox;
  function get_Mailbox(mailbox) {
    _mailbox = mailbox;
  }
 
  // Other fields and functions associated with the app
 
  return {
    get_Mailbox: get_Mailbox
    // Other exposed members
  };
})()

RoamingSettings 物件(也只在郵件應用程式中可用)類似于以以文件為主的應用程式(工作窗格和內容應用程式)的 Settings 物件。 該物件允許應用程式以名稱/值對的形式跨會話持久保存自訂屬性。 但是,與在主機 Office 檔中保存自訂屬性的 Settings 物件不同,RoamingSettings 物件將自訂設置保存到當前使用者的郵箱。 這樣,無論使用者正在查看什麼郵件,或使用者如何訪問其郵箱(無論在 Outlook 中還是 Outlook Web App 中訪問),都能使自訂屬性對應用程式可用。

有關 JavaScript API for Office 中物件模型層次結構的更多資訊,請參見 MSDN 文檔頁面「瞭解 JavaScript API for Office」(bit.ly/UV2POY)。

測試某項功能在主機應用程式中是否可用

如前所述,JavaScript API for Office 的優勢之一是 Office 應用程式的「一次開發,多處使用」性質。 例如,同一個工作窗格應用程式在 Word、Excel、Project 和 PowerPoint 中都可啟動(假設其清單允許所有這些功能)。

但是,由於並非所有應用程式都可以訪問完全相同的一組功能,所以某個應用程式可能被插入一個不允許該應用程式所需功能的主機應用程式中。 例如,Project 目前不提供對 Settings 物件的訪問。 如果某個插入 Project 的應用程式嘗試訪問 Settings 物件,則會引發「未定義的物件」錯誤。

因此,開發人員必須在其應用程式中包含用於測試他們所需要的功能是否可用的邏輯。 在 Project 的示例中,檢測主機應用程式中的功能的最佳方法是使用一個簡單的 if 塊:

// Test for Settings object in host application
if (Office.context.document.settings) {
 
  // Provide implementation that uses the Settings object
 
}
else {
 
  // Use some other technique for saving custom properties,
  // like localStorage, sessionStorage or cookies
 
}

有關如何檢測某成員在主機應用程式中是否可用的更多資訊,請參見 MSDN 文檔頁面「如何:確定主機應用程式是否支援特定 API 成員」,位址是 bit.ly/TR5ZlB

在本文中,我們討論了 JavaScript API for Office 的重要概念。 我們概括描述了物件模型層次結構,討論了非同步模式在物件模型中的實現。 我們還介紹了如何測試在主機應用程式中是否支援某個功能。

在本系列的下一篇文章中,我們將進一步討論在用於 Office 的應用程式中處理資料的最簡單而又最強大的方法。 文章將更深入地描述如何獲取和設置選定資料。 我們將介紹如何獲取所有檔內容以及如何對內容進行解析。 此外,還會討論 Project 中的應用程式以及如何讀取任務、資源和視圖資料。 最後,我們將考察 JavaScript API for Office 中的事件模型:您可以編寫代碼的事件以及處理結果的方法。

Stephen Oliver*  *是 Office 部門的一位程式師,也是 Microsoft 認證專業開發人員 (SharePoint 2010)。 他針對 Excel 服務和 Word 自動化服務編寫開發人員文檔,還編寫 PowerPoint 自動化服務開發人員文檔。 他説明組織和設計過 Excel Mashup 網站,網址是 ExcelMashup.com

Eric Schmidt*  *是 Office 部門的一位程式師。 他為用於 Office 的應用程式創建了多段示例代碼,包括很普及的「持久保存自訂設置」示例代碼。 此外,他還就 Office 可程式設計性撰寫過有關其他產品和技術的文章並創建過相關視頻。

衷心感謝以下技術專家對本文的審閱: MarkBrewster、Shilpa Kothari 和 Juan Balmori Labra