Context
In my company, I am in charge of developing an Add-in of type Content App only for PowerPoint. The add-in is built with ASP.NET MVC (4.5) and AngularJS (1.6.8) and works seamlessly on PowerPoint client (Version 1811, Build 11029.20079).
Tests procedure
Windows 10 64-bits
Chrome, v70.0.3538.110 (Official Build) (64-bit)
Adblocker disabled
Manifest used
This manifest passed the validation tool (https://www.npmjs.com/package/office-addin-validator).
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:type="ContentApp">
<Id>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</Id>
<Version>1.0.0.0</Version>
<ProviderName>My Company</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="Office Add-in name" />
<Description DefaultValue="Office Add-in description." />
<IconUrl DefaultValue="https://my-company.com/PluginLogo32.png" />
<HighResolutionIconUrl DefaultValue="https://my-company.com/PluginLogo64.png" />
<SupportUrl DefaultValue="https://my-company.com/support/" />
<AppDomains>
<AppDomain>my-company.com</AppDomain>
</AppDomains>
<Hosts>
<Host Name="Presentation" />
</Hosts>
<Requirements>
<Sets DefaultMinVersion="1.1">
<Set Name="Settings" />
</Sets>
<Methods>
<Method Name="Settings.get" />
<Method Name="Settings.set" />
<Method Name="Settings.remove" />
<Method Name="Settings.saveAsync" />
</Methods>
</Requirements>
<DefaultSettings>
<SourceLocation DefaultValue="https://my-company.com/plugin" />
<RequestedWidth>800</RequestedWidth>
<RequestedHeight>600</RequestedHeight>
</DefaultSettings>
<Permissions>ReadWriteDocument</Permissions>
<AllowSnapshot>true</AllowSnapshot>
</OfficeApp>
Office initialization used
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
<script type="text/javascript">
var init = function () {
App.tags = @Html.Raw(WorkContext.ActivPortalUserEntity.GetUserTagsAsJson());
App.languages = @Html.Raw(LocalizationManager.GetPortalJsonScript());
App.AP_URL = '@WorkContext.Uri';
App.V_KEY_FORM = '@AntiforgeryHelper.GetTokenName()';
App.V_VALUE_FORM = '@AntiforgeryHelper.GetToken()';
App.LabelURLSuffix = '';
App.URLSuffix = '@Model.TemplateDocument.URLSuffix';
App.IsDefaultUser = @Json.Encode(WorkContext.ActivPortalUserEntity.IsDefaultUser);
App.DashboardParametersQueryString = '@Html.Raw(Model.RenderContext.Request.GetParametersAsQuerystring())';
App.DashboardFilters = @Html.Raw(@JsonConvert.SerializeObject(Model.RenderContext.Request.GlobalCriteriaObjects));
App.ZoomFilters = @Html.Raw(@JsonConvert.SerializeObject(Model.RenderContext.Request.GlobalCriteriaIndexes));
App.WebPartFormatUseCorner = true;
App.DeportedToggleView = true;
App.ToggleViewMode = 'accordion';
App.searchPlaceHolderText = "@Resource("L_appSearchPlaceHolder_Text", "Portal")";
App.viewType = '';
App.documentRepository = '@ApplicationConfigService.ActivPortalServerConfig.DocumentsRepository';
App.WPAllowIconsHide = false;
App.Language = '@WorkContext.UserLanguage';
App.searchURL = [];
App.EditMode = false;
App.EditContentMode = false;
App.CATALOG_PROXY = '@WorkContext.Uri' + 'Portal/CatalogProvider';
App.RENDER_URL = '@WorkContext.Uri' + 'Portal/Render';
App.CHOICE_PROXY = '@WorkContext.Uri' + 'Portal/Render/TemplateRequest';
App.POST_TEMPLATE_PROXY = '@WorkContext.Uri' + 'Portal/Render/TemplateRequest';
App.moduleScripts = @Html.Raw(JsonConvert.SerializeObject(Model.GetPageScripts()));
App.moduleStylesSheets = @Html.Raw(@JsonConvert.SerializeObject(Model.GetPageStyles()));
App.angularClientContext = @Html.Raw(@Html.GetJsonClientContext());
App.scriptDebug = (typeof App.scriptDebug == undefined) ? false : App.scriptDebug;
App.ScriptsManager = new Activportal.UI.Resources({ scriptDebug: App.scriptDebug });
App.StylesManager = new Activportal.UI.Resources();
//Localization
MinimizeTip_Text = "@Resource("L_Minimize_Text", "Portal")";
ExpandTip_Text = "@Resource("L_Maximize_Text", "Portal")";
ErrorUpdatingPart_Text = "@Resource("L_InvalidURL_Text", "Portal")";
ConfirmRemoveGlobalFilter_Text = "@Resource("L_ConfirmRemoveGlobalFilter_Text", "Portal")";
WaitMessage_Text = "@Resource("L_WaitMessage_Text", "Portal")";
SessionEnd_Text = "@Resource("L_SessionEndMessage_Text", "Portal")";
window.addEvent('domready', function () {
App.isDashboardLoaded();
App.Start();
});
};
try {
if (Office) {
Office.initialize = init;
}
else {
console.log("Office.js is missing.");
if (!window.external.GetContext) {
init();
}
}
} catch (e) {
console.log(e);
}
</script>
Problem
Just to repeat myself, The Add-in works seamlessly on PowerPoint 2016 client (see above for version). However, in PowerPoint Online I struggle on an issue: the initialization of the add-in.
When inserting the Add-in or reloading the login page is displayed with an opacity as follow:
Then after 2 seconds this message appears: "Sorry...We could not start the Add-in because we encountered a problem. Try later or contact your system administrator."
The only message I get from the console are the followings:- At this point, i count 1 initialization. When I click on “DÉMARRER” the same thing happens (second init). And then, when I click again (third init). The Add-in finally works like on PowerPoint client. Here is what is look like when the login page works. https://imgur.com/F9QNvvg
So, on Office Online, it’s only the third initialization, the Add-in it works. I noticed approximately the same behavior for all major browser in their last version.
Question
Is there something I am missing?
I am open to any suggestions, I didn't find any solution on this particular matter.
What I did to fix this issue
Well, my mistake has been to not understand well how Office.js works.
In my login page
- I added the script Office.js.
- I initialize the script.
In my main page
- I change the way to initialize the script.
Conclusion
It seems Office.js must be present in the first page of the application. And in every pages which use Office API.
In addition, It is better to Use Office.onReady() instead of Office.initialize().
Things to note:
Documentation not that abvious, perhaps?