PowerPoint Add-in with JavaScript

Open File Explorer and create the (C:\temp\vscode-yeoman) folder.
Open Visual Studio Code.
Display the Terminal window (View > Terminal).
Change to that folder.

cd C:\temp\vscode-yeoman 

Install Yeoman

The Yeoman generator is an open source scaffolding tool for creating web applications.
This generator creates a Node.js project.

npm install -g yo 
npm install -g generator-office

check the versions and update if necessary.

yo --version 
npm view generator-office version

Generate Template Files

Run the Yeoman generator to create the project.

yo office 

Choose a project type: Select "Office Add-in Task Pane project".

alt text

Choose a script type: Select "JavaScript".
What do you want to name your add-in: Type "PowerPoint-JavaScript".
Choose which office client application you want to target: Select "PowerPoint".
All the necessary files will then be created for you.


package.json file

Change to that folder.

cd PowerPoint-JavaScript 

Open this folder in the current Visual Studio Code instance.

code -a. 

Open the Explorer pane (View > Explorer).
Expand the project "PowerPoint-JavaScript".

alt text

Click on the package.json file.

{ 
  "name": "office-addin-taskpane-js",
  "version": "0.0.1",
  "repository": {
    "type": "git",
    "url": "https://github.com/OfficeDev/Office-Addin-TaskPane-JS.git"
  },
  "license": "MIT",
  "config": {
    "app_to_debug": "powerpoint",
    "app_type_to_debug": "desktop",
    "dev_server_port": 3000
  },
  "scripts": {
    "build": "webpack --mode production",
    "build:dev": "webpack --mode development",
    "dev-server": "webpack serve --mode development",
    "lint": "office-addin-lint check",
    "lint:fix": "office-addin-lint fix",
    "prettier": "office-addin-lint prettier",
    "start": "office-addin-debugging start manifest.xml",
    "start:desktop": "office-addin-debugging start manifest.xml desktop",
    "start:web": "office-addin-debugging start manifest.xml web",
    "stop": "office-addin-debugging stop manifest.xml",
    "validate": "office-addin-manifest validate manifest.xml",
    "watch": "webpack --mode development --watch"
  },
  "dependencies": {
    "core-js": "^3.9.1",
    "regenerator-runtime": "^0.13.7"
  },
  "devDependencies": {
    "@babel/core": "^7.13.10",
    "@babel/preset-env": "^7.12.11",
    "@babel/preset-typescript": "^7.13.0",
    "@types/office-js": "^1.0.256",
    "@types/office-runtime": "^1.0.23",
    "acorn": "^8.5.0",
    "babel-loader": "^8.2.2",
    "copy-webpack-plugin": "^9.0.1",
    "eslint-plugin-office-addins": "^2.0.3",
    "file-loader": "^6.2.0",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "^5.3.2",
    "office-addin-cli": "^1.3.8",
    "office-addin-debugging": "^4.3.14",
    "office-addin-dev-certs": "^1.7.10",
    "office-addin-lint": "^2.0.3",
    "office-addin-manifest": "^1.8.1",
    "office-addin-prettier-config": "^1.1.7",
    "os-browserify": "^0.3.0",
    "process": "^0.11.10",
    "source-map-loader": "^3.0.0",
    "ts-loader": "^9.2.5",
    "typescript": "^4.3.5",
    "webpack": "^5.50.0",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "4.7.4"
  },
  "prettier": "office-addin-prettier-config",
  "browserslist": [
    "ie 11"
  ]
}

manifest.xml

Click on the manifest.xml file.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
  <Id>1d9ebe41-a5a9-4059-896d-94f07d6c5632</Id>
  <Version>1.0.0.0</Version>
  <ProviderName>Contoso</ProviderName>
  <DefaultLocale>en-US</DefaultLocale>
  <DisplayName DefaultValue="PowerPoint-JavaScript"/>
  <Description DefaultValue="A template to get started."/>
  <IconUrl DefaultValue="https://localhost:3000/assets/icon-32.png"/>
  <HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/>
  <SupportUrl DefaultValue="https://www.contoso.com/help"/>
  <AppDomains>
    <AppDomain>https://www.contoso.com</AppDomain>
  </AppDomains>
  <Hosts>
    <Host Name="Presentation"/>
  </Hosts>
  <DefaultSettings>
    <SourceLocation DefaultValue="https://localhost:3000/taskpane.html"/>
  </DefaultSettings>
  <Permissions>ReadWriteDocument</Permissions>
  <VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
    <Hosts>
      <Host xsi:type="Presentation">
        <DesktopFormFactor>
          <GetStarted>
            <Title resid="GetStarted.Title"/>
            <Description resid="GetStarted.Description"/>
            <LearnMoreUrl resid="GetStarted.LearnMoreUrl"/>
          </GetStarted>
          <FunctionFile resid="Commands.Url"/>
          <ExtensionPoint xsi:type="PrimaryCommandSurface">
            <OfficeTab id="TabHome">
              <Group id="CommandsGroup">
                <Label resid="CommandsGroup.Label"/>
                <Icon>
                  <bt:Image size="16" resid="Icon.16x16"/>
                  <bt:Image size="32" resid="Icon.32x32"/>
                  <bt:Image size="80" resid="Icon.80x80"/>
                </Icon>
                <Control xsi:type="Button" id="TaskpaneButton">
                  <Label resid="TaskpaneButton.Label"/>
                  <Supertip>
                    <Title resid="TaskpaneButton.Label"/>
                    <Description resid="TaskpaneButton.Tooltip"/>
                  </Supertip>
                  <Icon>
                    <bt:Image size="16" resid="Icon.16x16"/>
                    <bt:Image size="32" resid="Icon.32x32"/>
                    <bt:Image size="80" resid="Icon.80x80"/>
                  </Icon>
                  <Action xsi:type="ShowTaskpane">
                    <TaskpaneId>ButtonId1</TaskpaneId>
                    <SourceLocation resid="Taskpane.Url"/>
                  </Action>
                </Control>
              </Group>
            </OfficeTab>
          </ExtensionPoint>
        </DesktopFormFactor>
      </Host>
    </Hosts>
    <Resources>
      <bt:Images>
        <bt:Image id="Icon.16x16" DefaultValue="https://localhost:3000/assets/icon-16.png"/>
        <bt:Image id="Icon.32x32" DefaultValue="https://localhost:3000/assets/icon-32.png"/>
        <bt:Image id="Icon.80x80" DefaultValue="https://localhost:3000/assets/icon-80.png"/>
      </bt:Images>
      <bt:Urls>
        <bt:Url id="GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812"/>
        <bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html"/>
        <bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html"/>
      </bt:Urls>
      <bt:ShortStrings>
        <bt:String id="GetStarted.Title" DefaultValue="Get started with your sample add-in!"/>
        <bt:String id="CommandsGroup.Label" DefaultValue="Commands Group"/>
        <bt:String id="TaskpaneButton.Label" DefaultValue="Show Taskpane"/>
      </bt:ShortStrings>
      <bt:LongStrings>
        <bt:String id="GetStarted.Description" DefaultValue="Your sample add-in loaded succesfully. Go to the HOME tab and click the 'Show Taskpane' button to get started."/>
        <bt:String id="TaskpaneButton.Tooltip" DefaultValue="Click to Show a Taskpane"/>
      </bt:LongStrings>
    </Resources>
  </VersionOverrides>
</OfficeApp>

webpack.config.js

Click on the webpack.config.js file.

/* eslint-disable no-undef */ 

const devCerts = require("office-addin-dev-certs");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const urlDev = "https://localhost:3000/";
const urlProd = "https://www.contoso.com/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION

async function getHttpsOptions() {
  const httpsOptions = await devCerts.getHttpsServerOptions();
  return { cacert: httpsOptions.ca, key: httpsOptions.key, cert: httpsOptions.cert };
}

module.exports = async (env, options) => {
  const dev = options.mode === "development";
  const config = {
    devtool: "source-map",
    entry: {
      polyfill: ["core-js/stable", "regenerator-runtime/runtime"],
      taskpane: "./src/taskpane/taskpane.js",
      commands: "./src/commands/commands.js",
    },
    output: {
      devtoolModuleFilenameTemplate: "webpack:///[resource-path]?[loaders]",
      clean: true,
    },
    resolve: {
      extensions: [".html", ".js"],
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env"],
            },
          },
        },
        {
          test: /\.html$/,
          exclude: /node_modules/,
          use: "html-loader",
        },
        {
          test: /\.(png|jpg|jpeg|gif|ico)$/,
          type: "asset/resource",
          generator: {
            filename: "assets/[name][ext][query]",
          },
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: "taskpane.html",
        template: "./src/taskpane/taskpane.html",
        chunks: ["polyfill", "taskpane"],
      }),
      new CopyWebpackPlugin({
        patterns: [
          {
            from: "assets/*",
            to: "assets/[name][ext][query]",
          },
          {
            from: "manifest*.xml",
            to: "[name]" + "[ext]",
            transform(content) {
              if (dev) {
                return content;
              } else {
                return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
              }
            },
          },
        ],
      }),
      new HtmlWebpackPlugin({
        filename: "commands.html",
        template: "./src/commands/commands.html",
        chunks: ["polyfill", "commands"],
      }),
    ],
    devServer: {
      headers: {
        "Access-Control-Allow-Origin": "*",
      },
      https: env.WEBPACK_BUILD || options.https !== undefined ? options.https : await getHttpsOptions(),
      port: process.env.npm_package_config_dev_server_port || 3000,
    },
  };

  return config;
};

Other Project Files

The other project files are displayed on this page for reference.


Load the Add-in - Desktop

The add-in can be sideloaded into your PowerPoint client.
Execute the following command:

cd C:\temp\vscode-yeoman\PowerPoint-JavaScript 
npm start

This will start the local web server and open PowerPoint with the add-in loaded.
A small node window will be displayed.
A security warning dialog box will be displayed (the first time), asking you to install the certificate. Press Yes.
Select the Home tab and you will see a new group called "Commands Group" on the right hand side.
Press the "Show Taskpane" button to display the taskpane.
Press the Run button to insert the text "Hello World".

alt text

When you have finished testing you need to execute the following command:

npm stop 

Load the Add-in - Online

The add-in can be sideloaded into your Office Online.
Execute the following command:

cd C:\temp\vscode-yeoman\PowerPoint-JavaScript 
npm start web

Allow localhost loopback for Microsoft Edge Web Browser?: Yes
This will start the local web server.
The add-in will not appear automatically and will require side loading.

alt text

© 2023 Better Solutions Limited. All Rights Reserved. © 2023 Better Solutions Limited TopPrevNext