javascriptangularjsms-officeoffice-jsoffice-app

ReferenceError: Excel is not defined


I want to make an Office add-in with angularjs and angularjs-ui-router:

<bt:Urls>
    <bt:Url id="Contoso.Taskpane3.Url" DefaultValue="https://localhost:3000/addin/test" />            
</bt:Urls>

The name of the module is app, and the router is as follows:

.state('addinTest', {
    url: '/addin/test',
    tempalte: 'abc',
    controller: 'TestCtrl',
    resolve: {
        loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
            return $ocLazyLoad.load('https://appsforoffice.microsoft.com/lib/1/hosted/office.js');
        }],
        initOffice: ['loadMyCtrl', function (loadMyCtrl) {
            Office.initialize = function (reason) {
                $(document).ready(function () {
                    angular.element(document).ready(function () {
                        angular.bootstrap(document, ['app'])
                    })
                });
            }
            return Promise.resolve(null)
        }]
    }
})

And the controller:

app.controller('TestCtrl', [function () {
    function loadDataAndCreateChart() {
        Excel.run(function (ctx) {
            var sheet = ctx.workbook.worksheets.getActiveWorksheet();
            sheet.getRange("A1").values = "Quarterly Sales Report";
            return ctx.sync()
        })
    }
    loadDataAndCreateChart()
}])

I would expect that loading the add-in writes Quarterly Sales Report to A1. However, I got the following error:

ReferenceError: Excel is not defined at loadDataAndCreateChart

Does anyone know what's wrong? Is it OK to initialize Office and use angular.bootstrap like that?


Solution

  • You need to make sure that calls like

    Excel.run(function (ctx) {
            var sheet = ctx.workbook.worksheets.getActiveWorksheet();
            sheet.getRange("A1").values = "Quarterly Sales Report";
            return ctx.sync()
        });
    

    are executed after the initialization of Office is done.

    I created a small application that runs your code from above. Actually to run this there are only three files.

    1. manifest.xml
    2. index.html
    3. app.js

    Make sure that you replace in the following files the word PathToYourLocalFile with your actual local path.

    manifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <OfficeApp xsi:type="TaskPaneApp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/office/appforoffice/1.0">
         <Id>6ed5a5d8-57e4-4739-9a38-cff59f23e266</Id>
         <Version>1.0.0.0</Version>
         <ProviderName>Test Provider</ProviderName>
         <DefaultLocale>en-US</DefaultLocale>
         <DisplayName DefaultValue="Test" />
         <Description DefaultValue="Angular Test" />
         <Capabilities>
            <Capability Name="Workbook" />
         </Capabilities>
         <DefaultSettings>
             <SourceLocation DefaultValue="PathToYourLocalFile/index.html" />
         </DefaultSettings>
         <Permissions>ReadWriteDocument</Permissions>
    </OfficeApp>
    

    index.html

    <!DOCTYPE html>
    <html lang="en" ng-app="AngularTest"  ng-controller="MainController">
    <head>
        <meta charset="utf-8">
        <title>Angular Test</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
     </head>
     <body>
         <div ng-view></div>  
         <!-- Load Js Libaries -->
         <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
         </script>
         <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js">
         </script>
         <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-resource.min.js"></script>
         <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-route.min.js"></script>
    
         <script src="PathToYourLocalFile/app.js"></script>
      </body>
      </html>
    

    app.js

    'use strict';
    angular.module('AngularTest', [])
        .controller('MainController', [
            function () {
                Office.initialize = function () {
                    $(document).ready(function () {
                        loadDataAndCreateChart();
                    });
                };
    
                function loadDataAndCreateChart() {
                    Excel.run(function (ctx) {
                        var sheet = ctx.workbook.worksheets.getActiveWorksheet();
                        sheet.getRange("A1").values = "Quarterly Sales Report";
                        return ctx.sync();
                    });
                }
    
            }
        ]);
    

    You can see in the app.js file that the Method loadDataAndCreateChart is executed after the initialization of Office is done.

    Here you can find the documentation how you can add the manifest to excel: Office Dev Center