Office中國(guó)論壇/Access中國(guó)論壇

 找回密碼
 注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

返回列表 發(fā)新帖
查看: 2593|回復(fù): 1
打印 上一主題 下一主題

[其他] Office Web Add-in的技術(shù)原理和開(kāi)發(fā)常見(jiàn)問(wèn)題剖析

[復(fù)制鏈接]

點(diǎn)擊這里給我發(fā)消息

跳轉(zhuǎn)到指定樓層
1#
發(fā)表于 2018-11-30 17:10:20 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
過(guò)去發(fā)表過(guò)一些Office Add-in開(kāi)發(fā)的文章,并且也在不同的場(chǎng)合分享過(guò)新的開(kāi)發(fā)模式及其帶來(lái)的機(jī)遇。有不少朋友給我反饋,也討論到一些常見(jiàn)問(wèn)題,我這里集中地總結(jié)一下給大家參考。

1. Office Web Add-in的適用場(chǎng)景
這是很多人的困惑。我在這篇文章中詳細(xì)對(duì)照了三種為Office開(kāi)發(fā)Add-in的技術(shù)和表現(xiàn)形式,這里再總結(jié)一下新的Web Add-in適用的場(chǎng)合

  • 開(kāi)發(fā)人員本身對(duì)于網(wǎng)絡(luò)開(kāi)發(fā)比較熟悉
  • 你希望這個(gè)插件能夠跨平臺(tái)使用
  • 你希望更加方便地進(jìn)行集中部署和更新
  • 這個(gè)插件的功能除了Office內(nèi)部的操作,還有大量的外部資源訪(fǎng)問(wèn)
  • 用戶(hù)能隨時(shí)訪(fǎng)問(wèn)網(wǎng)絡(luò),并且網(wǎng)絡(luò)條件有保障
用戶(hù)對(duì)于運(yùn)行速度的敏感度不是很高,并不是說(shuō)Web Add-in的運(yùn)行速度慢,是因?yàn)閃eb Add-in開(kāi)發(fā)中很多操作都是異步執(zhí)行的,所以會(huì)造成感覺(jué)上的運(yùn)行慢的體驗(yàn)


2. 工作原理到底是怎么樣的
這也是很多人的疑問(wèn)。我們可以稍微回顧一下歷史,VBA是直接運(yùn)行在Office進(jìn)程(例如Excel)中的,它應(yīng)該算是一個(gè)腳本,會(huì)有主程序動(dòng)態(tài)加載,編譯運(yùn)行。一旦運(yùn)行結(jié)束,則會(huì)釋放資源。而VSTO則更為復(fù)雜,因?yàn)樗怯?NET開(kāi)發(fā)出來(lái)的托管代碼,所以他本身是不能通過(guò)宿主程序直接運(yùn)行的,而是需要從宿主程序(其實(shí)是COM)通過(guò)平臺(tái)調(diào)用的方式(Interop)發(fā)起一個(gè)指令,然后由.NET CLR加載Add-in的組件,這個(gè)組件如果需要操作Excel的資源,又要通過(guò)平臺(tái)調(diào)用的方式反過(guò)來(lái)調(diào)用COM。

那么,今天的Web Add-in到底又是怎么樣加載和運(yùn)行的呢?它是通過(guò)一個(gè)獨(dú)立的瀏覽器進(jìn)程(例如IE)來(lái)運(yùn)行的。下面我將詳細(xì)解釋這方面的原理。
在不同的平臺(tái)上,Office Add-in所依賴(lài)的瀏覽器及其版本是不一樣的,這給開(kāi)發(fā)人員要提一個(gè)醒:瀏覽器兼容性測(cè)試還是很重要的。官方文檔有提到對(duì)于瀏覽器及其版本的要求:https://docs.microsoft.com/en-us/office/dev/add-ins/concepts/requirements-for-running-office-add-ins。

通過(guò)nslookup命令,可以看出我目前這個(gè)托管在azurewebsites.net上面的范例插件,它的服務(wù)器IP地址是 13.75.46.26(注意,因?yàn)锳zure平臺(tái)有很多服務(wù)器,所以實(shí)際上針對(duì)一個(gè)域名可能會(huì)有很多IP地址,如果你用nslookup命令可能得到的結(jié)果跟我不一樣)

在插件加載后,我們一般會(huì)在進(jìn)程管理器中看到兩個(gè)IE的進(jìn)程。這里有一個(gè)細(xì)節(jié),如果你的Office是32位的,那么它的核心進(jìn)程會(huì)是一個(gè)32位的,你可以查看如果加載多個(gè)插件的話(huà),它所占用的內(nèi)存會(huì)逐步增加。但是,仍然是一個(gè)進(jìn)程。

但是,如果你的Windows是64位的,此時(shí)它會(huì)另外創(chuàng)建一個(gè)64位的IE進(jìn)程,這兩個(gè)進(jìn)程其實(shí)是一個(gè)調(diào)用的關(guān)系。從下圖可以看出來(lái)32位的進(jìn)程其實(shí)是在調(diào)用64位那個(gè)進(jìn)程的。

如果要具體來(lái)證明這些進(jìn)程是訪(fǎng)問(wèn)到我們那個(gè)插件的網(wǎng)站,可以通過(guò)進(jìn)程查看器來(lái)觀察

3. 如何在Web Add-in的Javascript代碼中異步訪(fǎng)問(wèn)到遠(yuǎn)程的服務(wù)
既然我們知道Office Add-in本質(zhì)上是一個(gè)網(wǎng)絡(luò)應(yīng)用,根據(jù)你所選擇的開(kāi)發(fā)技術(shù)不同,對(duì)于訪(fǎng)問(wèn)遠(yuǎn)程服務(wù)資源的做法也不一樣。如果你是用ASP.NET MVC來(lái)實(shí)現(xiàn)的,那么可能會(huì)簡(jiǎn)單一些,因?yàn)镸VC本身就可以包含一些服務(wù)器代碼。但如果你更加喜歡用Javascript代碼來(lái)編程,你的服務(wù)資源調(diào)用,需要注意遵循一個(gè)兩個(gè)重要原則:

  • 這個(gè)資源必須使用Https的方式提供,而且證書(shū)必須是合法的。如果部署到Azure的應(yīng)用服務(wù),則默認(rèn)就帶有了合法的證書(shū),支持https訪(fǎng)問(wèn)。
  • 這個(gè)資源必須支持跨域訪(fǎng)問(wèn)。關(guān)于如何支持跨域訪(fǎng)問(wèn),我另外有一篇文章可以參考:http://www.cnblogs.com/chenxizhang/p/7975521.html

下面我這里有一個(gè)范例代碼可供參考。我專(zhuān)門(mén)寫(xiě)了一個(gè)范例的API服務(wù) https://webaddinapisample.azurewebsites.net/api/values,大家如果測(cè)試也可以直接使用它。
  1. $("#run").click(() => tryCatch(run));

  2. async function run() {
  3.     await Excel.run(async (context) => {
  4.         await $.get("https://webaddinapisample.azurewebsites.net/api/values").done(async function (result) {
  5.             //這里一定要注意,必須是https地址,而且證書(shū)要有效,并且設(shè)置跨域訪(fǎng)問(wèn)
  6.             var sheet = context.workbook.worksheets.getActiveWorksheet();
  7.             var range = sheet.getRange("A1:B1");
  8.             range.values = [result];

  9.             await context.sync();

  10.             
  11.         }).fail(function (jqXHR, textStatus, errorThrown) {
  12.             console.log(errorThrown);
  13.         });


  14.     });
  15. }

  16. /** 嘗試執(zhí)行某個(gè)方法 */
  17. async function tryCatch(callback) {
  18.     try {
  19.         await callback();
  20.     }
  21.     catch (error) {
  22.         OfficeHelpers.UI.notify(error);
  23.         OfficeHelpers.Utilities.log(error);
  24.     }
  25. }
復(fù)制代碼




4. 網(wǎng)絡(luò)斷開(kāi)是否可以繼續(xù)用
這個(gè)問(wèn)題的答案跟問(wèn)題本身一樣簡(jiǎn)單:不能。由于Web Add-in本質(zhì)上是一個(gè)網(wǎng)絡(luò)應(yīng)用,所以沒(méi)有網(wǎng)絡(luò),Add-in是無(wú)法加載的。

據(jù)官方提到,有可能日后會(huì)有支持本地緩存的技術(shù)實(shí)現(xiàn)。但目前還沒(méi)有看到這方面的路線(xiàn)圖。


5. 能不能通過(guò)代碼增加菜單
目前僅支持利用清單文件來(lái)定義界面元素,包括Ribbon和快捷菜單。如果你對(duì)這方面有興趣,請(qǐng)參考 詳解Office Add-in 清單文件。
這可能是跟VBA和VSTO相比較而言,比較大的劣勢(shì),其他的功能方面,也并不是完全一致,這個(gè)還有一個(gè)不斷發(fā)展的過(guò)程,好消息是,這些API還是快速地開(kāi)發(fā)中。





轉(zhuǎn)載自博客園   作者:陳希章      


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享分享 分享淘帖 訂閱訂閱

點(diǎn)擊這里給我發(fā)消息

2#
 樓主| 發(fā)表于 2018-11-30 17:10:38 | 只看該作者

6.怎么做基于事件的編程?
面向事件的編程,可能是絕大部分開(kāi)發(fā)人員根深蒂固的觀念。其實(shí)Office Add-in本身就是面向事件的編程。所有的代碼,都是從一個(gè) Office.initialize 的事件開(kāi)始的。再往深入地看,針對(duì)不同的宿主程序,不同的資源對(duì)象,是否還可以綁定事件并且進(jìn)行響應(yīng)處理呢?我們?cè)赩BA或VSTO中或多或少是可以這么做的,例如Workbook的Open事件等等。

在Web Add-in中,事件通過(guò)一個(gè)特殊的做法來(lái)實(shí)現(xiàn):Binding。但目前的支持是有限的,請(qǐng)參考官方文章:https://dev.office.com/reference/add-ins/excel/binding 。下面有一個(gè)簡(jiǎn)單的實(shí)例可供參考:
  1. $("#setup").click(() => tryCatch(setup));
  2. $("#register-data-changed-handler").click(() => tryCatch(registerDataChangedHandler));

  3. async function registerDataChangedHandler() {
  4.     await Excel.run(async (context) => {
  5.         const sheet = context.workbook.worksheets.getItem("Sample");   
  6.         const salesTable = sheet.tables.getItem("SalesTable");
  7.         const dataRange = salesTable.getDataBodyRange();
  8.         //創(chuàng)建事件綁定
  9.         const salesByQuarterBinding = context.workbook.bindings.add(dataRange, "range", "SalesByQuarter");
  10.         salesByQuarterBinding.onDataChanged.add(onSalesDataChanged);

  11.         OfficeHelpers.UI.notify("The handler is registered.", "Change the value in one of the data cells and watch this message banner. (Be sure to complete the edit by pressing Enter or clicking in another cell.)");

  12.         await context.sync();
  13.     });
  14. }

  15. //這是事件處理代碼
  16. async function onSalesDataChanged() {
  17.     await Excel.run(async (context) => {
  18.         OfficeHelpers.UI.notify("Data was changed!!!!", "");

  19.         await context.sync();
  20.     });
  21. }

  22. //準(zhǔn)備初始化數(shù)據(jù)
  23. async function setup() {
  24.     await Excel.run(async (context) => {
  25.         const sheet = await OfficeHelpers.ExcelUtilities.forceCreateSheet(context.workbook, "Sample");
  26.         let salesTable = sheet.tables.add('A1:E1', true);        
  27.         salesTable.name = "SalesTable";
  28.         salesTable.getHeaderRowRange().values = [["Sales Team", "Qtr1", "Qtr2", "Qtr3", "Qtr4"]];

  29.         salesTable.rows.add(null, [
  30.             ["London", 500, 700, 654, null ],
  31.             ["Hong Kong", 400, 323, 276, null ],
  32.             ["New York", 1200, 876, 845, null ],
  33.             ["Port-of-Spain", 600, 500, 854, null ],
  34.             ["Nairobi", 5001, 2232, 4763, null ]
  35.         ]);  

  36.         salesTable.getRange().format.autofitColumns();
  37.         salesTable.getRange().format.autofitRows();
  38.         sheet.activate();

  39.         await context.sync();
  40.     });
  41. }


  42. async function tryCatch(callback) {
  43.     try {
  44.         await callback();
  45.     }
  46.     catch (error) {
  47.         OfficeHelpers.UI.notify(error);
  48.         OfficeHelpers.Utilities.log(error);
  49.     }
  50. }
復(fù)制代碼


7. 能不能編寫(xiě)自定義函數(shù)
這個(gè)問(wèn)題很顯然是一個(gè)Excel的開(kāi)發(fā)人員問(wèn)的。

在Web Add-in的時(shí)代,目前已經(jīng)提供了針對(duì)發(fā)燒友(Office Insider)的Developer Preview支持,請(qǐng)參考 https://docs.microsoft.com/en-us/office/dev/add-ins/excel/custom-functions-overview


8. 能不能實(shí)現(xiàn)文檔打開(kāi)的時(shí)候自動(dòng)加載某個(gè)Add-in
可以,但是分兩種情況。

  • 第一種情況,如果是Content Add-in(目前在Excel和PowerPoint中受支持),則自動(dòng)就實(shí)現(xiàn)了,你可以創(chuàng)建一個(gè)文檔,然后插入好這個(gè)Add-in,保存后,下次打開(kāi)就自動(dòng)會(huì)加載進(jìn)來(lái)。
  • 第二種情況,如果是TaskPane Add-in(目前在Excel,Word,PowerPoint中受支持),則只有在沒(méi)有添加VersionOverrides的情況下可以實(shí)現(xiàn)類(lèi)似于Content Add-in 的效果,也就是說(shuō)不能有自定義的Ribbon和Context Menu。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--Created:ce44715c-8c4e-446b-879c-ea9ebe0f09c8-->
  3. <OfficeApp
  4.         xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
  5.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.         xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
  7.         xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides"
  8.         xsi:type="TaskPaneApp">

  9. <!-- Begin Basic Settings: Add-in metadata, used for all versions of Office unless override provided. -->

  10. <!-- IMPORTANT! Id must be unique for your add-in, if you reuse this manifest ensure that you change this id to a new GUID. -->
  11. <Id>f43cc685-d5de-464e-a97c-520017b901a3</Id>

  12. <!--Version. Updates from the store only get triggered if there is a version change. -->
  13. <Version>1.0.0.0</Version>
  14. <ProviderName>[Provider name]</ProviderName>
  15. <DefaultLocale>en-US</DefaultLocale>
  16. <!-- The display name of your add-in. Used on the store and various places of the Office UI such as the add-ins dialog. -->
  17. <DisplayName DefaultValue="WordWebAddInSample" />
  18. <Description DefaultValue="WordWebAddInSample"/>
  19. <!-- Icon for your add-in. Used on installation screens and the add-ins dialog. -->
  20. <IconUrl DefaultValue="~remoteAppUrl/Images/Button32x32.png" />

  21. <SupportUrl DefaultValue="http://www.contoso.com" />
  22. <!-- Domains that will be allowed when navigating. For example, if you use ShowTaskpane and then have an href link, navigation will only be allowed if the domain is on this list. -->
  23. <AppDomains>
  24.     <AppDomain>AppDomain1</AppDomain>
  25.     <AppDomain>AppDomain2</AppDomain>
  26.     <AppDomain>AppDomain3</AppDomain>
  27. </AppDomains>
  28. <!--End Basic Settings. -->

  29. <!--Begin TaskPane Mode integration. This section is used if there are no VersionOverrides or if the Office client version does not support add-in commands. -->
  30. <Hosts>
  31.     <Host Name="Document" />
  32. </Hosts>
  33. <DefaultSettings>
  34.     <SourceLocation DefaultValue="~remoteAppUrl/Home.html" />
  35. </DefaultSettings>
  36. <!-- End TaskPane Mode integration.  -->

  37. <Permissions>ReadWriteDocument</Permissions>
  38. <!-- End Add-in Commands Mode integration. -->

  39. </OfficeApp>
復(fù)制代碼
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則

QQ|站長(zhǎng)郵箱|小黑屋|手機(jī)版|Office中國(guó)/Access中國(guó) ( 粵ICP備10043721號(hào)-1 )  

GMT+8, 2025-7-17 00:37 , Processed in 0.103571 second(s), 25 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回復(fù) 返回頂部 返回列表